diff options
| author | fishsoupisgood <github@madingley.org> | 2019-04-29 01:17:54 +0100 | 
|---|---|---|
| committer | fishsoupisgood <github@madingley.org> | 2019-05-27 03:43:43 +0100 | 
| commit | 3f2546b2ef55b661fd8dd69682b38992225e86f6 (patch) | |
| tree | 65ca85f13617aee1dce474596800950f266a456c /include/hw | |
| download | qemu-master.tar.gz qemu-master.tar.bz2 qemu-master.zip  | |
Diffstat (limited to 'include/hw')
197 files changed, 22046 insertions, 0 deletions
diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h new file mode 100644 index 00000000..2b431e62 --- /dev/null +++ b/include/hw/acpi/acpi-defs.h @@ -0,0 +1,564 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along + * with this program; if not, see <http://www.gnu.org/licenses/>. + */ +#ifndef QEMU_ACPI_DEFS_H +#define QEMU_ACPI_DEFS_H + +enum { +    ACPI_FADT_F_WBINVD, +    ACPI_FADT_F_WBINVD_FLUSH, +    ACPI_FADT_F_PROC_C1, +    ACPI_FADT_F_P_LVL2_UP, +    ACPI_FADT_F_PWR_BUTTON, +    ACPI_FADT_F_SLP_BUTTON, +    ACPI_FADT_F_FIX_RTC, +    ACPI_FADT_F_RTC_S4, +    ACPI_FADT_F_TMR_VAL_EXT, +    ACPI_FADT_F_DCK_CAP, +    ACPI_FADT_F_RESET_REG_SUP, +    ACPI_FADT_F_SEALED_CASE, +    ACPI_FADT_F_HEADLESS, +    ACPI_FADT_F_CPU_SW_SLP, +    ACPI_FADT_F_PCI_EXP_WAK, +    ACPI_FADT_F_USE_PLATFORM_CLOCK, +    ACPI_FADT_F_S4_RTC_STS_VALID, +    ACPI_FADT_F_REMOTE_POWER_ON_CAPABLE, +    ACPI_FADT_F_FORCE_APIC_CLUSTER_MODEL, +    ACPI_FADT_F_FORCE_APIC_PHYSICAL_DESTINATION_MODE, +    ACPI_FADT_F_HW_REDUCED_ACPI, +    ACPI_FADT_F_LOW_POWER_S0_IDLE_CAPABLE, +}; + +/* + * ACPI 2.0 Generic Address Space definition. + */ +struct Acpi20GenericAddress { +    uint8_t  address_space_id; +    uint8_t  register_bit_width; +    uint8_t  register_bit_offset; +    uint8_t  reserved; +    uint64_t address; +} QEMU_PACKED; +typedef struct Acpi20GenericAddress Acpi20GenericAddress; + +struct AcpiRsdpDescriptor {        /* Root System Descriptor Pointer */ +    uint64_t signature;              /* ACPI signature, contains "RSD PTR " */ +    uint8_t  checksum;               /* To make sum of struct == 0 */ +    uint8_t  oem_id [6];             /* OEM identification */ +    uint8_t  revision;               /* Must be 0 for 1.0, 2 for 2.0 */ +    uint32_t rsdt_physical_address;  /* 32-bit physical address of RSDT */ +    uint32_t length;                 /* XSDT Length in bytes including hdr */ +    uint64_t xsdt_physical_address;  /* 64-bit physical address of XSDT */ +    uint8_t  extended_checksum;      /* Checksum of entire table */ +    uint8_t  reserved [3];           /* Reserved field must be 0 */ +} QEMU_PACKED; +typedef struct AcpiRsdpDescriptor AcpiRsdpDescriptor; + +/* Table structure from Linux kernel (the ACPI tables are under the +   BSD license) */ + + +#define ACPI_TABLE_HEADER_DEF   /* ACPI common table header */ \ +    uint32_t signature;          /* ACPI signature (4 ASCII characters) */ \ +    uint32_t length;                 /* Length of table, in bytes, including header */ \ +    uint8_t  revision;               /* ACPI Specification minor version # */ \ +    uint8_t  checksum;               /* To make sum of entire table == 0 */ \ +    uint8_t  oem_id [6];             /* OEM identification */ \ +    uint8_t  oem_table_id [8];       /* OEM table identification */ \ +    uint32_t oem_revision;           /* OEM revision number */ \ +    uint8_t  asl_compiler_id [4];    /* ASL compiler vendor ID */ \ +    uint32_t asl_compiler_revision;  /* ASL compiler revision number */ + + +struct AcpiTableHeader         /* ACPI common table header */ +{ +    ACPI_TABLE_HEADER_DEF +} QEMU_PACKED; +typedef struct AcpiTableHeader AcpiTableHeader; + +/* + * ACPI Fixed ACPI Description Table (FADT) + */ +#define ACPI_FADT_COMMON_DEF /* FADT common definition */ \ +    ACPI_TABLE_HEADER_DEF    /* ACPI common table header */ \ +    uint32_t firmware_ctrl;  /* Physical address of FACS */ \ +    uint32_t dsdt;         /* Physical address of DSDT */ \ +    uint8_t  model;        /* System Interrupt Model */ \ +    uint8_t  reserved1;    /* Reserved */ \ +    uint16_t sci_int;      /* System vector of SCI interrupt */ \ +    uint32_t smi_cmd;      /* Port address of SMI command port */ \ +    uint8_t  acpi_enable;  /* Value to write to smi_cmd to enable ACPI */ \ +    uint8_t  acpi_disable; /* Value to write to smi_cmd to disable ACPI */ \ +    /* Value to write to SMI CMD to enter S4BIOS state */ \ +    uint8_t  S4bios_req; \ +    uint8_t  reserved2;    /* Reserved - must be zero */ \ +    /* Port address of Power Mgt 1a acpi_event Reg Blk */ \ +    uint32_t pm1a_evt_blk; \ +    /* Port address of Power Mgt 1b acpi_event Reg Blk */ \ +    uint32_t pm1b_evt_blk; \ +    uint32_t pm1a_cnt_blk; /* Port address of Power Mgt 1a Control Reg Blk */ \ +    uint32_t pm1b_cnt_blk; /* Port address of Power Mgt 1b Control Reg Blk */ \ +    uint32_t pm2_cnt_blk;  /* Port address of Power Mgt 2 Control Reg Blk */ \ +    uint32_t pm_tmr_blk;   /* Port address of Power Mgt Timer Ctrl Reg Blk */ \ +    /* Port addr of General Purpose acpi_event 0 Reg Blk */ \ +    uint32_t gpe0_blk; \ +    /* Port addr of General Purpose acpi_event 1 Reg Blk */ \ +    uint32_t gpe1_blk; \ +    uint8_t  pm1_evt_len;  /* Byte length of ports at pm1_x_evt_blk */ \ +    uint8_t  pm1_cnt_len;  /* Byte length of ports at pm1_x_cnt_blk */ \ +    uint8_t  pm2_cnt_len;  /* Byte Length of ports at pm2_cnt_blk */ \ +    uint8_t  pm_tmr_len;   /* Byte Length of ports at pm_tm_blk */ \ +    uint8_t  gpe0_blk_len; /* Byte Length of ports at gpe0_blk */ \ +    uint8_t  gpe1_blk_len; /* Byte Length of ports at gpe1_blk */ \ +    uint8_t  gpe1_base;    /* Offset in gpe model where gpe1 events start */ \ +    uint8_t  reserved3;    /* Reserved */ \ +    uint16_t plvl2_lat;    /* Worst case HW latency to enter/exit C2 state */ \ +    uint16_t plvl3_lat;    /* Worst case HW latency to enter/exit C3 state */ \ +    uint16_t flush_size;   /* Size of area read to flush caches */ \ +    uint16_t flush_stride; /* Stride used in flushing caches */ \ +    uint8_t  duty_offset;  /* Bit location of duty cycle field in p_cnt reg */ \ +    uint8_t  duty_width;   /* Bit width of duty cycle field in p_cnt reg */ \ +    uint8_t  day_alrm;     /* Index to day-of-month alarm in RTC CMOS RAM */ \ +    uint8_t  mon_alrm;     /* Index to month-of-year alarm in RTC CMOS RAM */ \ +    uint8_t  century;      /* Index to century in RTC CMOS RAM */ + +struct AcpiFadtDescriptorRev1 +{ +    ACPI_FADT_COMMON_DEF +    uint8_t  reserved4;              /* Reserved */ +    uint8_t  reserved4a;             /* Reserved */ +    uint8_t  reserved4b;             /* Reserved */ +    uint32_t flags; +} QEMU_PACKED; +typedef struct AcpiFadtDescriptorRev1 AcpiFadtDescriptorRev1; + +struct AcpiGenericAddress { +    uint8_t space_id;        /* Address space where struct or register exists */ +    uint8_t bit_width;       /* Size in bits of given register */ +    uint8_t bit_offset;      /* Bit offset within the register */ +    uint8_t access_width;    /* Minimum Access size (ACPI 3.0) */ +    uint64_t address;        /* 64-bit address of struct or register */ +} QEMU_PACKED; + +struct AcpiFadtDescriptorRev5_1 { +    ACPI_FADT_COMMON_DEF +    /* IA-PC Boot Architecture Flags (see below for individual flags) */ +    uint16_t boot_flags; +    uint8_t reserved;    /* Reserved, must be zero */ +    /* Miscellaneous flag bits (see below for individual flags) */ +    uint32_t flags; +    /* 64-bit address of the Reset register */ +    struct AcpiGenericAddress reset_register; +    /* Value to write to the reset_register port to reset the system */ +    uint8_t reset_value; +    /* ARM-Specific Boot Flags (see below for individual flags) (ACPI 5.1) */ +    uint16_t arm_boot_flags; +    uint8_t minor_revision;  /* FADT Minor Revision (ACPI 5.1) */ +    uint64_t Xfacs;          /* 64-bit physical address of FACS */ +    uint64_t Xdsdt;          /* 64-bit physical address of DSDT */ +    /* 64-bit Extended Power Mgt 1a Event Reg Blk address */ +    struct AcpiGenericAddress xpm1a_event_block; +    /* 64-bit Extended Power Mgt 1b Event Reg Blk address */ +    struct AcpiGenericAddress xpm1b_event_block; +    /* 64-bit Extended Power Mgt 1a Control Reg Blk address */ +    struct AcpiGenericAddress xpm1a_control_block; +    /* 64-bit Extended Power Mgt 1b Control Reg Blk address */ +    struct AcpiGenericAddress xpm1b_control_block; +    /* 64-bit Extended Power Mgt 2 Control Reg Blk address */ +    struct AcpiGenericAddress xpm2_control_block; +    /* 64-bit Extended Power Mgt Timer Ctrl Reg Blk address */ +    struct AcpiGenericAddress xpm_timer_block; +    /* 64-bit Extended General Purpose Event 0 Reg Blk address */ +    struct AcpiGenericAddress xgpe0_block; +    /* 64-bit Extended General Purpose Event 1 Reg Blk address */ +    struct AcpiGenericAddress xgpe1_block; +    /* 64-bit Sleep Control register (ACPI 5.0) */ +    struct AcpiGenericAddress sleep_control; +    /* 64-bit Sleep Status register (ACPI 5.0) */ +    struct AcpiGenericAddress sleep_status; +} QEMU_PACKED; + +typedef struct AcpiFadtDescriptorRev5_1 AcpiFadtDescriptorRev5_1; + +enum { +    ACPI_FADT_ARM_USE_PSCI_G_0_2 = 0, +    ACPI_FADT_ARM_PSCI_USE_HVC = 1, +}; + +/* + * Serial Port Console Redirection Table (SPCR), Rev. 1.02 + * + * For .interface_type see Debug Port Table 2 (DBG2) serial port + * subtypes in Table 3, Rev. May 22, 2012 + */ +struct AcpiSerialPortConsoleRedirection { +    ACPI_TABLE_HEADER_DEF +    uint8_t  interface_type; +    uint8_t  reserved1[3]; +    struct AcpiGenericAddress base_address; +    uint8_t  interrupt_types; +    uint8_t  irq; +    uint32_t gsi; +    uint8_t  baud; +    uint8_t  parity; +    uint8_t  stopbits; +    uint8_t  flowctrl; +    uint8_t  term_type; +    uint8_t  reserved2; +    uint16_t pci_device_id; +    uint16_t pci_vendor_id; +    uint8_t  pci_bus; +    uint8_t  pci_slot; +    uint8_t  pci_func; +    uint32_t pci_flags; +    uint8_t  pci_seg; +    uint32_t reserved3; +} QEMU_PACKED; +typedef struct AcpiSerialPortConsoleRedirection +               AcpiSerialPortConsoleRedirection; + +/* + * ACPI 1.0 Root System Description Table (RSDT) + */ +struct AcpiRsdtDescriptorRev1 +{ +    ACPI_TABLE_HEADER_DEF       /* ACPI common table header */ +    uint32_t table_offset_entry[0];  /* Array of pointers to other */ +    /* ACPI tables */ +} QEMU_PACKED; +typedef struct AcpiRsdtDescriptorRev1 AcpiRsdtDescriptorRev1; + +/* + * ACPI 1.0 Firmware ACPI Control Structure (FACS) + */ +struct AcpiFacsDescriptorRev1 +{ +    uint32_t signature;           /* ACPI Signature */ +    uint32_t length;                 /* Length of structure, in bytes */ +    uint32_t hardware_signature;     /* Hardware configuration signature */ +    uint32_t firmware_waking_vector; /* ACPI OS waking vector */ +    uint32_t global_lock;            /* Global Lock */ +    uint32_t flags; +    uint8_t  resverved3 [40];        /* Reserved - must be zero */ +} QEMU_PACKED; +typedef struct AcpiFacsDescriptorRev1 AcpiFacsDescriptorRev1; + +/* + * Differentiated System Description Table (DSDT) + */ + +/* + * MADT values and structures + */ + +/* Values for MADT PCATCompat */ + +#define ACPI_DUAL_PIC                0 +#define ACPI_MULTIPLE_APIC           1 + +/* Master MADT */ + +struct AcpiMultipleApicTable +{ +    ACPI_TABLE_HEADER_DEF     /* ACPI common table header */ +    uint32_t local_apic_address;     /* Physical address of local APIC */ +    uint32_t flags; +} QEMU_PACKED; +typedef struct AcpiMultipleApicTable AcpiMultipleApicTable; + +/* Values for Type in APIC sub-headers */ + +#define ACPI_APIC_PROCESSOR          0 +#define ACPI_APIC_IO                 1 +#define ACPI_APIC_XRUPT_OVERRIDE     2 +#define ACPI_APIC_NMI                3 +#define ACPI_APIC_LOCAL_NMI          4 +#define ACPI_APIC_ADDRESS_OVERRIDE   5 +#define ACPI_APIC_IO_SAPIC           6 +#define ACPI_APIC_LOCAL_SAPIC        7 +#define ACPI_APIC_XRUPT_SOURCE       8 +#define ACPI_APIC_LOCAL_X2APIC       9 +#define ACPI_APIC_LOCAL_X2APIC_NMI      10 +#define ACPI_APIC_GENERIC_INTERRUPT     11 +#define ACPI_APIC_GENERIC_DISTRIBUTOR   12 +#define ACPI_APIC_GENERIC_MSI_FRAME     13 +#define ACPI_APIC_GENERIC_REDISTRIBUTOR 14 +#define ACPI_APIC_RESERVED              15   /* 15 and greater are reserved */ + +/* + * MADT sub-structures (Follow MULTIPLE_APIC_DESCRIPTION_TABLE) + */ +#define ACPI_SUB_HEADER_DEF   /* Common ACPI sub-structure header */\ +    uint8_t  type;                               \ +    uint8_t  length; + +/* Sub-structures for MADT */ + +struct AcpiMadtProcessorApic +{ +    ACPI_SUB_HEADER_DEF +    uint8_t  processor_id;           /* ACPI processor id */ +    uint8_t  local_apic_id;          /* Processor's local APIC id */ +    uint32_t flags; +} QEMU_PACKED; +typedef struct AcpiMadtProcessorApic AcpiMadtProcessorApic; + +struct AcpiMadtIoApic +{ +    ACPI_SUB_HEADER_DEF +    uint8_t  io_apic_id;             /* I/O APIC ID */ +    uint8_t  reserved;               /* Reserved - must be zero */ +    uint32_t address;                /* APIC physical address */ +    uint32_t interrupt;              /* Global system interrupt where INTI +                                 * lines start */ +} QEMU_PACKED; +typedef struct AcpiMadtIoApic AcpiMadtIoApic; + +struct AcpiMadtIntsrcovr { +    ACPI_SUB_HEADER_DEF +    uint8_t  bus; +    uint8_t  source; +    uint32_t gsi; +    uint16_t flags; +} QEMU_PACKED; +typedef struct AcpiMadtIntsrcovr AcpiMadtIntsrcovr; + +struct AcpiMadtLocalNmi { +    ACPI_SUB_HEADER_DEF +    uint8_t  processor_id;           /* ACPI processor id */ +    uint16_t flags;                  /* MPS INTI flags */ +    uint8_t  lint;                   /* Local APIC LINT# */ +} QEMU_PACKED; +typedef struct AcpiMadtLocalNmi AcpiMadtLocalNmi; + +struct AcpiMadtGenericInterrupt { +    ACPI_SUB_HEADER_DEF +    uint16_t reserved; +    uint32_t cpu_interface_number; +    uint32_t uid; +    uint32_t flags; +    uint32_t parking_version; +    uint32_t performance_interrupt; +    uint64_t parked_address; +    uint64_t base_address; +    uint64_t gicv_base_address; +    uint64_t gich_base_address; +    uint32_t vgic_interrupt; +    uint64_t gicr_base_address; +    uint64_t arm_mpidr; +} QEMU_PACKED; + +typedef struct AcpiMadtGenericInterrupt AcpiMadtGenericInterrupt; + +struct AcpiMadtGenericDistributor { +    ACPI_SUB_HEADER_DEF +    uint16_t reserved; +    uint32_t gic_id; +    uint64_t base_address; +    uint32_t global_irq_base; +    uint32_t reserved2; +} QEMU_PACKED; + +typedef struct AcpiMadtGenericDistributor AcpiMadtGenericDistributor; + +struct AcpiMadtGenericMsiFrame { +    ACPI_SUB_HEADER_DEF +    uint16_t reserved; +    uint32_t gic_msi_frame_id; +    uint64_t base_address; +    uint32_t flags; +    uint16_t spi_count; +    uint16_t spi_base; +} QEMU_PACKED; + +typedef struct AcpiMadtGenericMsiFrame AcpiMadtGenericMsiFrame; + +/* + * Generic Timer Description Table (GTDT) + */ + +#define ACPI_GTDT_INTERRUPT_MODE        (1 << 0) +#define ACPI_GTDT_INTERRUPT_POLARITY    (1 << 1) +#define ACPI_GTDT_ALWAYS_ON             (1 << 2) + +/* Triggering */ + +#define ACPI_LEVEL_SENSITIVE            ((uint8_t) 0x00) +#define ACPI_EDGE_SENSITIVE             ((uint8_t) 0x01) + +/* Polarity */ + +#define ACPI_ACTIVE_HIGH                ((uint8_t) 0x00) +#define ACPI_ACTIVE_LOW                 ((uint8_t) 0x01) +#define ACPI_ACTIVE_BOTH                ((uint8_t) 0x02) + +struct AcpiGenericTimerTable { +    ACPI_TABLE_HEADER_DEF +    uint64_t counter_block_addresss; +    uint32_t reserved; +    uint32_t secure_el1_interrupt; +    uint32_t secure_el1_flags; +    uint32_t non_secure_el1_interrupt; +    uint32_t non_secure_el1_flags; +    uint32_t virtual_timer_interrupt; +    uint32_t virtual_timer_flags; +    uint32_t non_secure_el2_interrupt; +    uint32_t non_secure_el2_flags; +    uint64_t counter_read_block_address; +    uint32_t platform_timer_count; +    uint32_t platform_timer_offset; +} QEMU_PACKED; +typedef struct AcpiGenericTimerTable AcpiGenericTimerTable; + +/* + * HPET Description Table + */ +struct Acpi20Hpet { +    ACPI_TABLE_HEADER_DEF                    /* ACPI common table header */ +    uint32_t           timer_block_id; +    Acpi20GenericAddress addr; +    uint8_t            hpet_number; +    uint16_t           min_tick; +    uint8_t            page_protect; +} QEMU_PACKED; +typedef struct Acpi20Hpet Acpi20Hpet; + +/* + * SRAT (NUMA topology description) table + */ + +struct AcpiSystemResourceAffinityTable +{ +    ACPI_TABLE_HEADER_DEF +    uint32_t    reserved1; +    uint32_t    reserved2[2]; +} QEMU_PACKED; +typedef struct AcpiSystemResourceAffinityTable AcpiSystemResourceAffinityTable; + +#define ACPI_SRAT_PROCESSOR          0 +#define ACPI_SRAT_MEMORY             1 + +struct AcpiSratProcessorAffinity +{ +    ACPI_SUB_HEADER_DEF +    uint8_t     proximity_lo; +    uint8_t     local_apic_id; +    uint32_t    flags; +    uint8_t     local_sapic_eid; +    uint8_t     proximity_hi[3]; +    uint32_t    reserved; +} QEMU_PACKED; +typedef struct AcpiSratProcessorAffinity AcpiSratProcessorAffinity; + +struct AcpiSratMemoryAffinity +{ +    ACPI_SUB_HEADER_DEF +    uint8_t     proximity[4]; +    uint16_t    reserved1; +    uint64_t    base_addr; +    uint64_t    range_length; +    uint32_t    reserved2; +    uint32_t    flags; +    uint32_t    reserved3[2]; +} QEMU_PACKED; +typedef struct AcpiSratMemoryAffinity AcpiSratMemoryAffinity; + +/* PCI fw r3.0 MCFG table. */ +/* Subtable */ +struct AcpiMcfgAllocation { +    uint64_t address;                /* Base address, processor-relative */ +    uint16_t pci_segment;            /* PCI segment group number */ +    uint8_t start_bus_number;       /* Starting PCI Bus number */ +    uint8_t end_bus_number;         /* Final PCI Bus number */ +    uint32_t reserved; +} QEMU_PACKED; +typedef struct AcpiMcfgAllocation AcpiMcfgAllocation; + +struct AcpiTableMcfg { +    ACPI_TABLE_HEADER_DEF; +    uint8_t reserved[8]; +    AcpiMcfgAllocation allocation[0]; +} QEMU_PACKED; +typedef struct AcpiTableMcfg AcpiTableMcfg; + +/* + * TCPA Description Table + * + * Following Level 00, Rev 00.37 of specs: + * http://www.trustedcomputinggroup.org/resources/tcg_acpi_specification + */ +struct Acpi20Tcpa { +    ACPI_TABLE_HEADER_DEF                    /* ACPI common table header */ +    uint16_t platform_class; +    uint32_t log_area_minimum_length; +    uint64_t log_area_start_address; +} QEMU_PACKED; +typedef struct Acpi20Tcpa Acpi20Tcpa; + +/* + * TPM2 + * + * Following Level 00, Rev 00.37 of specs: + * http://www.trustedcomputinggroup.org/resources/tcg_acpi_specification + */ +struct Acpi20TPM2 { +    ACPI_TABLE_HEADER_DEF +    uint16_t platform_class; +    uint16_t reserved; +    uint64_t control_area_address; +    uint32_t start_method; +} QEMU_PACKED; +typedef struct Acpi20TPM2 Acpi20TPM2; + +/* DMAR - DMA Remapping table r2.2 */ +struct AcpiTableDmar { +    ACPI_TABLE_HEADER_DEF +    uint8_t host_address_width; /* Maximum DMA physical addressability */ +    uint8_t flags; +    uint8_t reserved[10]; +} QEMU_PACKED; +typedef struct AcpiTableDmar AcpiTableDmar; + +/* Masks for Flags field above */ +#define ACPI_DMAR_INTR_REMAP        1 +#define ACPI_DMAR_X2APIC_OPT_OUT    (1 << 1) + +/* Values for sub-structure type for DMAR */ +enum { +    ACPI_DMAR_TYPE_HARDWARE_UNIT = 0,       /* DRHD */ +    ACPI_DMAR_TYPE_RESERVED_MEMORY = 1,     /* RMRR */ +    ACPI_DMAR_TYPE_ATSR = 2,                /* ATSR */ +    ACPI_DMAR_TYPE_HARDWARE_AFFINITY = 3,   /* RHSR */ +    ACPI_DMAR_TYPE_ANDD = 4,                /* ANDD */ +    ACPI_DMAR_TYPE_RESERVED = 5             /* Reserved for furture use */ +}; + +/* + * Sub-structures for DMAR + */ +/* Type 0: Hardware Unit Definition */ +struct AcpiDmarHardwareUnit { +    uint16_t type; +    uint16_t length; +    uint8_t flags; +    uint8_t reserved; +    uint16_t pci_segment;   /* The PCI Segment associated with this unit */ +    uint64_t address;   /* Base address of remapping hardware register-set */ +} QEMU_PACKED; +typedef struct AcpiDmarHardwareUnit AcpiDmarHardwareUnit; + +/* Masks for Flags field above */ +#define ACPI_DMAR_INCLUDE_PCI_ALL   1 + +#endif diff --git a/include/hw/acpi/acpi.h b/include/hw/acpi/acpi.h new file mode 100644 index 00000000..b20bd55a --- /dev/null +++ b/include/hw/acpi/acpi.h @@ -0,0 +1,199 @@ +#ifndef QEMU_HW_ACPI_H +#define QEMU_HW_ACPI_H +/* + *  Copyright (c) 2009 Isaku Yamahata <yamahata at valinux co jp> + *                     VA Linux Systems Japan K.K. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see + * <http://www.gnu.org/licenses/>. + */ + +#include "qapi/error.h" +#include "qemu/typedefs.h" +#include "qemu/notify.h" +#include "qemu/option.h" +#include "exec/memory.h" +#include "hw/irq.h" + +/* + * current device naming scheme supports up to 256 memory devices + */ +#define ACPI_MAX_RAM_SLOTS 256 + +/* from linux include/acpi/actype.h */ +/* Default ACPI register widths */ + +#define ACPI_GPE_REGISTER_WIDTH         8 +#define ACPI_PM1_REGISTER_WIDTH         16 +#define ACPI_PM2_REGISTER_WIDTH         8 +#define ACPI_PM_TIMER_WIDTH             32 + +/* PM Timer ticks per second (HZ) */ +#define PM_TIMER_FREQUENCY  3579545 + + +/* ACPI fixed hardware registers */ + +/* from linux/drivers/acpi/acpica/aclocal.h */ +/* Masks used to access the bit_registers */ + +/* PM1x_STS */ +#define ACPI_BITMASK_TIMER_STATUS               0x0001 +#define ACPI_BITMASK_BUS_MASTER_STATUS          0x0010 +#define ACPI_BITMASK_GLOBAL_LOCK_STATUS         0x0020 +#define ACPI_BITMASK_POWER_BUTTON_STATUS        0x0100 +#define ACPI_BITMASK_SLEEP_BUTTON_STATUS        0x0200 +#define ACPI_BITMASK_RT_CLOCK_STATUS            0x0400 +#define ACPI_BITMASK_PCIEXP_WAKE_STATUS         0x4000	/* ACPI 3.0 */ +#define ACPI_BITMASK_WAKE_STATUS                0x8000 + +#define ACPI_BITMASK_ALL_FIXED_STATUS           (\ +	ACPI_BITMASK_TIMER_STATUS          | \ +	ACPI_BITMASK_BUS_MASTER_STATUS     | \ +	ACPI_BITMASK_GLOBAL_LOCK_STATUS    | \ +	ACPI_BITMASK_POWER_BUTTON_STATUS   | \ +	ACPI_BITMASK_SLEEP_BUTTON_STATUS   | \ +	ACPI_BITMASK_RT_CLOCK_STATUS       | \ +	ACPI_BITMASK_WAKE_STATUS) + +/* PM1x_EN */ +#define ACPI_BITMASK_TIMER_ENABLE               0x0001 +#define ACPI_BITMASK_GLOBAL_LOCK_ENABLE         0x0020 +#define ACPI_BITMASK_POWER_BUTTON_ENABLE        0x0100 +#define ACPI_BITMASK_SLEEP_BUTTON_ENABLE        0x0200 +#define ACPI_BITMASK_RT_CLOCK_ENABLE            0x0400 +#define ACPI_BITMASK_PCIEXP_WAKE_DISABLE        0x4000	/* ACPI 3.0 */ + +#define ACPI_BITMASK_PM1_COMMON_ENABLED         ( \ +        ACPI_BITMASK_RT_CLOCK_ENABLE        | \ +        ACPI_BITMASK_POWER_BUTTON_ENABLE    | \ +        ACPI_BITMASK_GLOBAL_LOCK_ENABLE     | \ +        ACPI_BITMASK_TIMER_ENABLE) + +/* PM1x_CNT */ +#define ACPI_BITMASK_SCI_ENABLE                 0x0001 +#define ACPI_BITMASK_BUS_MASTER_RLD             0x0002 +#define ACPI_BITMASK_GLOBAL_LOCK_RELEASE        0x0004 +#define ACPI_BITMASK_SLEEP_TYPE                 0x1C00 +#define ACPI_BITMASK_SLEEP_ENABLE               0x2000 + +/* PM2_CNT */ +#define ACPI_BITMASK_ARB_DISABLE                0x0001 + +/* These values are part of guest ABI, and can not be changed */ +typedef enum { +    ACPI_PCI_HOTPLUG_STATUS = 2, +    ACPI_CPU_HOTPLUG_STATUS = 4, +    ACPI_MEMORY_HOTPLUG_STATUS = 8, +} AcpiGPEStatusBits; + +/* structs */ +typedef struct ACPIPMTimer ACPIPMTimer; +typedef struct ACPIPM1EVT ACPIPM1EVT; +typedef struct ACPIPM1CNT ACPIPM1CNT; +typedef struct ACPIGPE ACPIGPE; +typedef struct ACPIREGS ACPIREGS; + +typedef void (*acpi_update_sci_fn)(ACPIREGS *ar); + +struct ACPIPMTimer { +    QEMUTimer *timer; +    MemoryRegion io; +    int64_t overflow_time; + +    acpi_update_sci_fn update_sci; +}; + +struct ACPIPM1EVT { +    MemoryRegion io; +    uint16_t sts; +    uint16_t en; +    acpi_update_sci_fn update_sci; +}; + +struct ACPIPM1CNT { +    MemoryRegion io; +    uint16_t cnt; +    uint8_t s4_val; +}; + +struct ACPIGPE { +    uint8_t len; + +    uint8_t *sts; +    uint8_t *en; +}; + +struct ACPIREGS { +    ACPIPMTimer     tmr; +    ACPIGPE         gpe; +    struct { +        ACPIPM1EVT  evt; +        ACPIPM1CNT  cnt; +    } pm1; +    Notifier wakeup; +}; + +/* PM_TMR */ +void acpi_pm_tmr_update(ACPIREGS *ar, bool enable); +void acpi_pm_tmr_calc_overflow_time(ACPIREGS *ar); +void acpi_pm_tmr_init(ACPIREGS *ar, acpi_update_sci_fn update_sci, +                      MemoryRegion *parent); +void acpi_pm_tmr_reset(ACPIREGS *ar); + +#include "qemu/timer.h" +static inline int64_t acpi_pm_tmr_get_clock(void) +{ +    return muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), PM_TIMER_FREQUENCY, +                    get_ticks_per_sec()); +} + +/* PM1a_EVT: piix and ich9 don't implement PM1b. */ +uint16_t acpi_pm1_evt_get_sts(ACPIREGS *ar); +void acpi_pm1_evt_power_down(ACPIREGS *ar); +void acpi_pm1_evt_reset(ACPIREGS *ar); +void acpi_pm1_evt_init(ACPIREGS *ar, acpi_update_sci_fn update_sci, +                       MemoryRegion *parent); + +/* PM1a_CNT: piix and ich9 don't implement PM1b CNT. */ +void acpi_pm1_cnt_init(ACPIREGS *ar, MemoryRegion *parent, +                       bool disable_s3, bool disable_s4, uint8_t s4_val); +void acpi_pm1_cnt_update(ACPIREGS *ar, +                         bool sci_enable, bool sci_disable); +void acpi_pm1_cnt_reset(ACPIREGS *ar); + +/* GPE0 */ +void acpi_gpe_init(ACPIREGS *ar, uint8_t len); +void acpi_gpe_reset(ACPIREGS *ar); + +void acpi_gpe_ioport_writeb(ACPIREGS *ar, uint32_t addr, uint32_t val); +uint32_t acpi_gpe_ioport_readb(ACPIREGS *ar, uint32_t addr); + +void acpi_send_gpe_event(ACPIREGS *ar, qemu_irq irq, +                         AcpiGPEStatusBits status); + +void acpi_update_sci(ACPIREGS *acpi_regs, qemu_irq irq); + +/* acpi.c */ +extern int acpi_enabled; +extern char unsigned *acpi_tables; +extern size_t acpi_tables_len; + +uint8_t *acpi_table_first(void); +uint8_t *acpi_table_next(uint8_t *current); +unsigned acpi_table_len(void *current); +void acpi_table_add(const QemuOpts *opts, Error **errp); +void acpi_table_add_builtin(const QemuOpts *opts, Error **errp); + +#endif /* !QEMU_HW_ACPI_H */ diff --git a/include/hw/acpi/acpi_dev_interface.h b/include/hw/acpi/acpi_dev_interface.h new file mode 100644 index 00000000..f245f8d2 --- /dev/null +++ b/include/hw/acpi/acpi_dev_interface.h @@ -0,0 +1,43 @@ +#ifndef ACPI_DEV_INTERFACE_H +#define ACPI_DEV_INTERFACE_H + +#include "qom/object.h" +#include "qapi-types.h" + +#define TYPE_ACPI_DEVICE_IF "acpi-device-interface" + +#define ACPI_DEVICE_IF_CLASS(klass) \ +     OBJECT_CLASS_CHECK(AcpiDeviceIfClass, (klass), \ +                        TYPE_ACPI_DEVICE_IF) +#define ACPI_DEVICE_IF_GET_CLASS(obj) \ +     OBJECT_GET_CLASS(AcpiDeviceIfClass, (obj), \ +                      TYPE_ACPI_DEVICE_IF) +#define ACPI_DEVICE_IF(obj) \ +     INTERFACE_CHECK(AcpiDeviceIf, (obj), \ +                     TYPE_ACPI_DEVICE_IF) + + +typedef struct AcpiDeviceIf { +    /* <private> */ +    Object Parent; +} AcpiDeviceIf; + +/** + * AcpiDeviceIfClass: + * + * ospm_status: returns status of ACPI device objects, reported + *              via _OST method if device supports it. + * + * Interface is designed for providing unified interface + * to generic ACPI functionality that could be used without + * knowledge about internals of actual device that implements + * ACPI interface. + */ +typedef struct AcpiDeviceIfClass { +    /* <private> */ +    InterfaceClass parent_class; + +    /* <public> */ +    void (*ospm_status)(AcpiDeviceIf *adev, ACPIOSTInfoList ***list); +} AcpiDeviceIfClass; +#endif diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h new file mode 100644 index 00000000..e3afa136 --- /dev/null +++ b/include/hw/acpi/aml-build.h @@ -0,0 +1,290 @@ +#ifndef HW_ACPI_GEN_UTILS_H +#define HW_ACPI_GEN_UTILS_H + +#include <stdint.h> +#include <glib.h> +#include "qemu/compiler.h" +#include "hw/acpi/acpi-defs.h" + +/* Reserve RAM space for tables: add another order of magnitude. */ +#define ACPI_BUILD_TABLE_MAX_SIZE         0x200000 + +#define ACPI_BUILD_APPNAME  "Bochs" +#define ACPI_BUILD_APPNAME6 "BOCHS " +#define ACPI_BUILD_APPNAME4 "BXPC" + +#define ACPI_BUILD_TABLE_FILE "etc/acpi/tables" +#define ACPI_BUILD_RSDP_FILE "etc/acpi/rsdp" +#define ACPI_BUILD_TPMLOG_FILE "etc/tpm/log" + +typedef enum { +    AML_NO_OPCODE = 0,/* has only data */ +    AML_OPCODE,       /* has opcode optionally followed by data */ +    AML_PACKAGE,      /* has opcode and uses PkgLength for its length */ +    AML_EXT_PACKAGE,  /* Same as AML_PACKAGE but also has 'ExOpPrefix' */ +    AML_BUFFER,       /* data encoded as 'DefBuffer' */ +    AML_RES_TEMPLATE, /* encoded as ResourceTemplate macro */ +} AmlBlockFlags; + +struct Aml { +    GArray *buf; + +    /*< private >*/ +    uint8_t op; +    AmlBlockFlags block_flags; +}; +typedef struct Aml Aml; + +typedef enum { +    AML_DECODE10 = 0, +    AML_DECODE16 = 1, +} AmlIODecode; + +typedef enum { +    AML_ANY_ACC = 0, +    AML_BYTE_ACC = 1, +    AML_WORD_ACC = 2, +    AML_DWORD_ACC = 3, +    AML_QWORD_ACC = 4, +    AML_BUFFER_ACC = 5, +} AmlAccessType; + +typedef enum { +    AML_PRESERVE = 0, +    AML_WRITE_AS_ONES = 1, +    AML_WRITE_AS_ZEROS = 2, +} AmlUpdateRule; + +typedef enum { +    AML_SYSTEM_MEMORY = 0X00, +    AML_SYSTEM_IO = 0X01, +} AmlRegionSpace; + +typedef enum { +    AML_MEMORY_RANGE = 0, +    AML_IO_RANGE = 1, +    AML_BUS_NUMBER_RANGE = 2, +} AmlResourceType; + +typedef enum { +    AML_SUB_DECODE = 1 << 1, +    AML_POS_DECODE = 0 +} AmlDecode; + +typedef enum { +    AML_MAX_FIXED = 1 << 3, +    AML_MAX_NOT_FIXED = 0, +} AmlMaxFixed; + +typedef enum { +    AML_MIN_FIXED = 1 << 2, +    AML_MIN_NOT_FIXED = 0 +} AmlMinFixed; + +/* + * ACPI 1.0b: Table 6-26 I/O Resource Flag (Resource Type = 1) Definitions + * _RNG field definition + */ +typedef enum { +    AML_ISA_ONLY = 1, +    AML_NON_ISA_ONLY = 2, +    AML_ENTIRE_RANGE = 3, +} AmlISARanges; + +/* + * ACPI 1.0b: Table 6-25 Memory Resource Flag (Resource Type = 0) Definitions + * _MEM field definition + */ +typedef enum { +    AML_NON_CACHEABLE = 0, +    AML_CACHEABLE = 1, +    AML_WRITE_COMBINING = 2, +    AML_PREFETCHABLE = 3, +} AmlCacheable; + +/* + * ACPI 1.0b: Table 6-25 Memory Resource Flag (Resource Type = 0) Definitions + * _RW field definition + */ +typedef enum { +    AML_READ_ONLY = 0, +    AML_READ_WRITE = 1, +} AmlReadAndWrite; + +/* + * ACPI 5.0: Table 6-187 Extended Interrupt Descriptor Definition + * Interrupt Vector Flags Bits[0] Consumer/Producer + */ +typedef enum { +    AML_CONSUMER_PRODUCER = 0, +    AML_CONSUMER = 1, +} AmlConsumerAndProducer; + +/* + * ACPI 5.0: Table 6-187 Extended Interrupt Descriptor Definition + * _HE field definition + */ +typedef enum { +    AML_LEVEL = 0, +    AML_EDGE = 1, +} AmlLevelAndEdge; + +/* + * ACPI 5.0: Table 6-187 Extended Interrupt Descriptor Definition + * _LL field definition + */ +typedef enum { +    AML_ACTIVE_HIGH = 0, +    AML_ACTIVE_LOW = 1, +} AmlActiveHighAndLow; + +/* + * ACPI 5.0: Table 6-187 Extended Interrupt Descriptor Definition + * _SHR field definition + */ +typedef enum { +    AML_EXCLUSIVE = 0, +    AML_SHARED = 1, +    AML_EXCLUSIVE_AND_WAKE = 2, +    AML_SHARED_AND_WAKE = 3, +} AmlShared; + +typedef +struct AcpiBuildTables { +    GArray *table_data; +    GArray *rsdp; +    GArray *tcpalog; +    GArray *linker; +} AcpiBuildTables; + +/** + * init_aml_allocator: + * + * Called for initializing API allocator which allow to use + * AML API. + * Returns: toplevel container which accumulates all other + * AML elements for a table. + */ +Aml *init_aml_allocator(void); + +/** + * free_aml_allocator: + * + * Releases all elements used by AML API, frees associated memory + * and invalidates AML allocator. After this call @init_aml_allocator + * should be called again if AML API is to be used again. + */ +void free_aml_allocator(void); + +/** + * aml_append: + * @parent_ctx: context to which @child element is added + * @child: element that is copied into @parent_ctx context + * + * Joins Aml elements together and helps to construct AML tables + * Examle of usage: + *   Aml *table = aml_def_block("SSDT", ...); + *   Aml *sb = aml_scope("\\_SB"); + *   Aml *dev = aml_device("PCI0"); + * + *   aml_append(dev, aml_name_decl("HID", aml_eisaid("PNP0A03"))); + *   aml_append(sb, dev); + *   aml_append(table, sb); + */ +void aml_append(Aml *parent_ctx, Aml *child); + +/* non block AML object primitives */ +Aml *aml_name(const char *name_format, ...) GCC_FMT_ATTR(1, 2); +Aml *aml_name_decl(const char *name, Aml *val); +Aml *aml_return(Aml *val); +Aml *aml_int(const uint64_t val); +Aml *aml_arg(int pos); +Aml *aml_store(Aml *val, Aml *target); +Aml *aml_and(Aml *arg1, Aml *arg2); +Aml *aml_or(Aml *arg1, Aml *arg2); +Aml *aml_shiftleft(Aml *arg1, Aml *count); +Aml *aml_shiftright(Aml *arg1, Aml *count); +Aml *aml_lless(Aml *arg1, Aml *arg2); +Aml *aml_add(Aml *arg1, Aml *arg2); +Aml *aml_increment(Aml *arg); +Aml *aml_index(Aml *arg1, Aml *idx); +Aml *aml_notify(Aml *arg1, Aml *arg2); +Aml *aml_call1(const char *method, Aml *arg1); +Aml *aml_call2(const char *method, Aml *arg1, Aml *arg2); +Aml *aml_call3(const char *method, Aml *arg1, Aml *arg2, Aml *arg3); +Aml *aml_call4(const char *method, Aml *arg1, Aml *arg2, Aml *arg3, Aml *arg4); +Aml *aml_memory32_fixed(uint32_t addr, uint32_t size, +                        AmlReadAndWrite read_and_write); +Aml *aml_interrupt(AmlConsumerAndProducer con_and_pro, +                   AmlLevelAndEdge level_and_edge, +                   AmlActiveHighAndLow high_and_low, AmlShared shared, +                   uint32_t irq); +Aml *aml_io(AmlIODecode dec, uint16_t min_base, uint16_t max_base, +            uint8_t aln, uint8_t len); +Aml *aml_operation_region(const char *name, AmlRegionSpace rs, +                          uint32_t offset, uint32_t len); +Aml *aml_irq_no_flags(uint8_t irq); +Aml *aml_named_field(const char *name, unsigned length); +Aml *aml_reserved_field(unsigned length); +Aml *aml_local(int num); +Aml *aml_string(const char *name_format, ...) GCC_FMT_ATTR(1, 2); +Aml *aml_lnot(Aml *arg); +Aml *aml_equal(Aml *arg1, Aml *arg2); +Aml *aml_processor(uint8_t proc_id, uint32_t pblk_addr, uint8_t pblk_len, +                   const char *name_format, ...) GCC_FMT_ATTR(4, 5); +Aml *aml_eisaid(const char *str); +Aml *aml_word_bus_number(AmlMinFixed min_fixed, AmlMaxFixed max_fixed, +                         AmlDecode dec, uint16_t addr_gran, +                         uint16_t addr_min, uint16_t addr_max, +                         uint16_t addr_trans, uint16_t len); +Aml *aml_word_io(AmlMinFixed min_fixed, AmlMaxFixed max_fixed, +                 AmlDecode dec, AmlISARanges isa_ranges, +                 uint16_t addr_gran, uint16_t addr_min, +                 uint16_t addr_max, uint16_t addr_trans, +                 uint16_t len); +Aml *aml_dword_io(AmlMinFixed min_fixed, AmlMaxFixed max_fixed, +                 AmlDecode dec, AmlISARanges isa_ranges, +                 uint32_t addr_gran, uint32_t addr_min, +                 uint32_t addr_max, uint32_t addr_trans, +                 uint32_t len); +Aml *aml_dword_memory(AmlDecode dec, AmlMinFixed min_fixed, +                      AmlMaxFixed max_fixed, AmlCacheable cacheable, +                      AmlReadAndWrite read_and_write, +                      uint32_t addr_gran, uint32_t addr_min, +                      uint32_t addr_max, uint32_t addr_trans, +                      uint32_t len); +Aml *aml_qword_memory(AmlDecode dec, AmlMinFixed min_fixed, +                      AmlMaxFixed max_fixed, AmlCacheable cacheable, +                      AmlReadAndWrite read_and_write, +                      uint64_t addr_gran, uint64_t addr_min, +                      uint64_t addr_max, uint64_t addr_trans, +                      uint64_t len); + +/* Block AML object primitives */ +Aml *aml_scope(const char *name_format, ...) GCC_FMT_ATTR(1, 2); +Aml *aml_device(const char *name_format, ...) GCC_FMT_ATTR(1, 2); +Aml *aml_method(const char *name, int arg_count); +Aml *aml_if(Aml *predicate); +Aml *aml_else(void); +Aml *aml_while(Aml *predicate); +Aml *aml_package(uint8_t num_elements); +Aml *aml_buffer(int buffer_size, uint8_t *byte_list); +Aml *aml_resource_template(void); +Aml *aml_field(const char *name, AmlAccessType type, AmlUpdateRule rule); +Aml *aml_create_dword_field(Aml *srcbuf, Aml *index, const char *name); +Aml *aml_varpackage(uint32_t num_elements); +Aml *aml_touuid(const char *uuid); +Aml *aml_unicode(const char *str); + +void +build_header(GArray *linker, GArray *table_data, +             AcpiTableHeader *h, const char *sig, int len, uint8_t rev); +void *acpi_data_push(GArray *table_data, unsigned size); +unsigned acpi_data_len(GArray *table); +void acpi_add_table(GArray *table_offsets, GArray *table_data); +void acpi_build_tables_init(AcpiBuildTables *tables); +void acpi_build_tables_cleanup(AcpiBuildTables *tables, bool mfre); +void +build_rsdt(GArray *table_data, GArray *linker, GArray *table_offsets); + +#endif diff --git a/include/hw/acpi/bios-linker-loader.h b/include/hw/acpi/bios-linker-loader.h new file mode 100644 index 00000000..498c0af7 --- /dev/null +++ b/include/hw/acpi/bios-linker-loader.h @@ -0,0 +1,27 @@ +#ifndef BIOS_LINKER_LOADER_H +#define BIOS_LINKER_LOADER_H + +#include <glib.h> +#include <stdbool.h> +#include <inttypes.h> + +GArray *bios_linker_loader_init(void); + +void bios_linker_loader_alloc(GArray *linker, +                              const char *file, +                              uint32_t alloc_align, +                              bool alloc_fseg); + +void bios_linker_loader_add_checksum(GArray *linker, const char *file, +                                     void *table, +                                     void *start, unsigned size, +                                     uint8_t *checksum); + +void bios_linker_loader_add_pointer(GArray *linker, +                                    const char *dest_file, +                                    const char *src_file, +                                    GArray *table, void *pointer, +                                    uint8_t pointer_size); + +void *bios_linker_loader_cleanup(GArray *linker); +#endif diff --git a/include/hw/acpi/cpu_hotplug.h b/include/hw/acpi/cpu_hotplug.h new file mode 100644 index 00000000..f6d358de --- /dev/null +++ b/include/hw/acpi/cpu_hotplug.h @@ -0,0 +1,28 @@ +/* + * QEMU ACPI hotplug utilities + * + * Copyright (C) 2013 Red Hat Inc + * + * Authors: + *   Igor Mammedov <imammedo@redhat.com> + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ +#ifndef ACPI_HOTPLUG_H +#define ACPI_HOTPLUG_H + +#include "hw/acpi/acpi.h" +#include "hw/acpi/pc-hotplug.h" + +typedef struct AcpiCpuHotplug { +    MemoryRegion io; +    uint8_t sts[ACPI_GPE_PROC_LEN]; +} AcpiCpuHotplug; + +void acpi_cpu_plug_cb(ACPIREGS *ar, qemu_irq irq, +                      AcpiCpuHotplug *g, DeviceState *dev, Error **errp); + +void acpi_cpu_hotplug_init(MemoryRegion *parent, Object *owner, +                           AcpiCpuHotplug *gpe_cpu, uint16_t base); +#endif diff --git a/include/hw/acpi/ich9.h b/include/hw/acpi/ich9.h new file mode 100644 index 00000000..345fd8d9 --- /dev/null +++ b/include/hw/acpi/ich9.h @@ -0,0 +1,80 @@ +/* + * QEMU GMCH/ICH9 LPC PM Emulation + * + *  Copyright (c) 2009 Isaku Yamahata <yamahata at valinux co jp> + *                     VA Linux Systems Japan K.K. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/> + */ + +#ifndef HW_ACPI_ICH9_H +#define HW_ACPI_ICH9_H + +#include "hw/acpi/acpi.h" +#include "hw/acpi/cpu_hotplug.h" +#include "hw/acpi/memory_hotplug.h" +#include "hw/acpi/acpi_dev_interface.h" +#include "hw/acpi/tco.h" + +typedef struct ICH9LPCPMRegs { +    /* +     * In ich9 spec says that pm1_cnt register is 32bit width and +     * that the upper 16bits are reserved and unused. +     * PM1a_CNT_BLK = 2 in FADT so it is defined as uint16_t. +     */ +    ACPIREGS acpi_regs; + +    MemoryRegion io; +    MemoryRegion io_gpe; +    MemoryRegion io_smi; + +    uint32_t smi_en; +    uint32_t smi_en_wmask; +    uint32_t smi_sts; + +    qemu_irq irq;      /* SCI */ + +    uint32_t pm_io_base; +    Notifier powerdown_notifier; + +    AcpiCpuHotplug gpe_cpu; + +    MemHotplugState acpi_memory_hotplug; + +    uint8_t disable_s3; +    uint8_t disable_s4; +    uint8_t s4_val; +    uint8_t smm_enabled; +    bool enable_tco; +    TCOIORegs tco_regs; +} ICH9LPCPMRegs; + +void ich9_pm_init(PCIDevice *lpc_pci, ICH9LPCPMRegs *pm, +                  bool smm_enabled, +                  bool enable_tco, +                  qemu_irq sci_irq); + +void ich9_pm_iospace_update(ICH9LPCPMRegs *pm, uint32_t pm_io_base); +extern const VMStateDescription vmstate_ich9_pm; + +void ich9_pm_add_properties(Object *obj, ICH9LPCPMRegs *pm, Error **errp); + +void ich9_pm_device_plug_cb(ICH9LPCPMRegs *pm, DeviceState *dev, Error **errp); +void ich9_pm_device_unplug_request_cb(ICH9LPCPMRegs *pm, DeviceState *dev, +                                      Error **errp); +void ich9_pm_device_unplug_cb(ICH9LPCPMRegs *pm, DeviceState *dev, +                              Error **errp); + +void ich9_pm_ospm_status(AcpiDeviceIf *adev, ACPIOSTInfoList ***list); +#endif /* HW_ACPI_ICH9_H */ diff --git a/include/hw/acpi/memory_hotplug.h b/include/hw/acpi/memory_hotplug.h new file mode 100644 index 00000000..1342adb0 --- /dev/null +++ b/include/hw/acpi/memory_hotplug.h @@ -0,0 +1,48 @@ +#ifndef QEMU_HW_ACPI_MEMORY_HOTPLUG_H +#define QEMU_HW_ACPI_MEMORY_HOTPLUG_H + +#include "hw/qdev-core.h" +#include "hw/acpi/acpi.h" +#include "migration/vmstate.h" + +/** + * MemStatus: + * @is_removing: the memory device in slot has been requested to be ejected. + * + * This structure stores memory device's status. + */ +typedef struct MemStatus { +    DeviceState *dimm; +    bool is_enabled; +    bool is_inserting; +    bool is_removing; +    uint32_t ost_event; +    uint32_t ost_status; +} MemStatus; + +typedef struct MemHotplugState { +    bool is_enabled; /* true if memory hotplug is supported */ +    MemoryRegion io; +    uint32_t selector; +    uint32_t dev_count; +    MemStatus *devs; +} MemHotplugState; + +void acpi_memory_hotplug_init(MemoryRegion *as, Object *owner, +                              MemHotplugState *state); + +void acpi_memory_plug_cb(ACPIREGS *ar, qemu_irq irq, MemHotplugState *mem_st, +                         DeviceState *dev, Error **errp); +void acpi_memory_unplug_request_cb(ACPIREGS *ar, qemu_irq irq, +                                   MemHotplugState *mem_st, +                                   DeviceState *dev, Error **errp); +void acpi_memory_unplug_cb(MemHotplugState *mem_st, +                           DeviceState *dev, Error **errp); + +extern const VMStateDescription vmstate_memory_hotplug; +#define VMSTATE_MEMORY_HOTPLUG(memhp, state) \ +    VMSTATE_STRUCT(memhp, state, 1, \ +                   vmstate_memory_hotplug, MemHotplugState) + +void acpi_memory_ospm_status(MemHotplugState *mem_st, ACPIOSTInfoList ***list); +#endif diff --git a/include/hw/acpi/pc-hotplug.h b/include/hw/acpi/pc-hotplug.h new file mode 100644 index 00000000..77b15690 --- /dev/null +++ b/include/hw/acpi/pc-hotplug.h @@ -0,0 +1,59 @@ +/* + * QEMU ACPI hotplug utilities shared defines + * + * Copyright (C) 2014 Red Hat Inc + * + * Authors: + *   Igor Mammedov <imammedo@redhat.com> + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ +#ifndef PC_HOTPLUG_H +#define PC_HOTPLUG_H + +/* + * ONLY DEFINEs are permited in this file since it's shared + * between C and ASL code. + */ + +/* Limit for CPU arch IDs for CPU hotplug. All hotpluggable CPUs should + * have CPUClass.get_arch_id() < ACPI_CPU_HOTPLUG_ID_LIMIT. + */ +#define ACPI_CPU_HOTPLUG_ID_LIMIT 256 + +/* 256 CPU IDs, 8 bits per entry: */ +#define ACPI_GPE_PROC_LEN 32 + +#define ICH9_CPU_HOTPLUG_IO_BASE 0x0CD8 +#define PIIX4_CPU_HOTPLUG_IO_BASE 0xaf00 +#define CPU_HOTPLUG_RESOURCE_DEVICE PRES + +#define ACPI_MEMORY_HOTPLUG_IO_LEN 24 +#define ACPI_MEMORY_HOTPLUG_BASE 0x0a00 + +#define MEMORY_HOTPLUG_DEVICE        MHPD +#define MEMORY_SLOTS_NUMBER          MDNR +#define MEMORY_HOTPLUG_IO_REGION     HPMR +#define MEMORY_SLOT_ADDR_LOW         MRBL +#define MEMORY_SLOT_ADDR_HIGH        MRBH +#define MEMORY_SLOT_SIZE_LOW         MRLL +#define MEMORY_SLOT_SIZE_HIGH        MRLH +#define MEMORY_SLOT_PROXIMITY        MPX +#define MEMORY_SLOT_ENABLED          MES +#define MEMORY_SLOT_INSERT_EVENT     MINS +#define MEMORY_SLOT_REMOVE_EVENT     MRMV +#define MEMORY_SLOT_EJECT            MEJ +#define MEMORY_SLOT_SLECTOR          MSEL +#define MEMORY_SLOT_OST_EVENT        MOEV +#define MEMORY_SLOT_OST_STATUS       MOSC +#define MEMORY_SLOT_LOCK             MLCK +#define MEMORY_SLOT_STATUS_METHOD    MRST +#define MEMORY_SLOT_CRS_METHOD       MCRS +#define MEMORY_SLOT_OST_METHOD       MOST +#define MEMORY_SLOT_PROXIMITY_METHOD MPXM +#define MEMORY_SLOT_EJECT_METHOD     MEJ0 +#define MEMORY_SLOT_NOTIFY_METHOD    MTFY +#define MEMORY_SLOT_SCAN_METHOD      MSCN + +#endif diff --git a/include/hw/acpi/pcihp.h b/include/hw/acpi/pcihp.h new file mode 100644 index 00000000..f3526d4a --- /dev/null +++ b/include/hw/acpi/pcihp.h @@ -0,0 +1,80 @@ +/* + * QEMU<->ACPI BIOS PCI hotplug interface + * + * QEMU supports PCI hotplug via ACPI. This module + * implements the interface between QEMU and the ACPI BIOS. + * Interface specification - see docs/specs/acpi_pci_hotplug.txt + * + * Copyright (c) 2013, Red Hat Inc, Michael S. Tsirkin (mst@redhat.com) + * Copyright (c) 2006 Fabrice Bellard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/> + * + * Contributions after 2012-01-13 are licensed under the terms of the + * GNU GPL, version 2 or (at your option) any later version. + */ + +#ifndef HW_ACPI_PCIHP_H +#define HW_ACPI_PCIHP_H + +#include <inttypes.h> +#include <qemu/typedefs.h> +#include "hw/acpi/acpi.h" +#include "migration/vmstate.h" + +#define ACPI_PCIHP_IO_BASE_PROP "acpi-pcihp-io-base" +#define ACPI_PCIHP_IO_LEN_PROP "acpi-pcihp-io-len" + +typedef struct AcpiPciHpPciStatus { +    uint32_t up; +    uint32_t down; +    uint32_t hotplug_enable; +} AcpiPciHpPciStatus; + +#define ACPI_PCIHP_PROP_BSEL "acpi-pcihp-bsel" +#define ACPI_PCIHP_MAX_HOTPLUG_BUS 256 +#define ACPI_PCIHP_BSEL_DEFAULT 0x0 + +typedef struct AcpiPciHpState { +    AcpiPciHpPciStatus acpi_pcihp_pci_status[ACPI_PCIHP_MAX_HOTPLUG_BUS]; +    uint32_t hotplug_select; +    PCIBus *root; +    MemoryRegion io; +    bool legacy_piix; +    uint16_t io_base; +    uint16_t io_len; +} AcpiPciHpState; + +void acpi_pcihp_init(Object *owner, AcpiPciHpState *, PCIBus *root, +                     MemoryRegion *address_space_io, bool bridges_enabled); + +void acpi_pcihp_device_plug_cb(ACPIREGS *ar, qemu_irq irq, AcpiPciHpState *s, +                               DeviceState *dev, Error **errp); +void acpi_pcihp_device_unplug_cb(ACPIREGS *ar, qemu_irq irq, AcpiPciHpState *s, +                                 DeviceState *dev, Error **errp); + +/* Called on reset */ +void acpi_pcihp_reset(AcpiPciHpState *s); + +extern const VMStateDescription vmstate_acpi_pcihp_pci_status; + +#define VMSTATE_PCI_HOTPLUG(pcihp, state, test_pcihp) \ +        VMSTATE_UINT32_TEST(pcihp.hotplug_select, state, \ +                            test_pcihp), \ +        VMSTATE_STRUCT_ARRAY_TEST(pcihp.acpi_pcihp_pci_status, state, \ +                                  ACPI_PCIHP_MAX_HOTPLUG_BUS, \ +                                  test_pcihp, 1, \ +                                  vmstate_acpi_pcihp_pci_status, \ +                                  AcpiPciHpPciStatus) + +#endif diff --git a/include/hw/acpi/piix4.h b/include/hw/acpi/piix4.h new file mode 100644 index 00000000..65e6fd7a --- /dev/null +++ b/include/hw/acpi/piix4.h @@ -0,0 +1,8 @@ +#ifndef HW_ACPI_PIIX4_H +#define HW_ACPI_PIIX4_H + +#include "qemu/typedefs.h" + +Object *piix4_pm_find(void); + +#endif diff --git a/include/hw/acpi/tco.h b/include/hw/acpi/tco.h new file mode 100644 index 00000000..c63afc8c --- /dev/null +++ b/include/hw/acpi/tco.h @@ -0,0 +1,82 @@ +/* + * QEMU ICH9 TCO emulation + * + * Copyright (c) 2015 Paulo Alcantara <pcacjr@zytor.com> + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ +#ifndef HW_ACPI_TCO_H +#define HW_ACPI_TCO_H + +#include "qemu/typedefs.h" +#include "qemu-common.h" + +/* As per ICH9 spec, the internal timer has an error of ~0.6s on every tick */ +#define TCO_TICK_NSEC 600000000LL + +/* TCO I/O register offsets */ +enum { +    TCO_RLD           = 0x00, +    TCO_DAT_IN        = 0x02, +    TCO_DAT_OUT       = 0x03, +    TCO1_STS          = 0x04, +    TCO2_STS          = 0x06, +    TCO1_CNT          = 0x08, +    TCO2_CNT          = 0x0a, +    TCO_MESSAGE1      = 0x0c, +    TCO_MESSAGE2      = 0x0d, +    TCO_WDCNT         = 0x0e, +    SW_IRQ_GEN        = 0x10, +    TCO_TMR           = 0x12, +}; + +/* TCO I/O register control/status bits */ +enum { +    SW_TCO_SMI           = 1 << 1, +    TCO_INT_STS          = 1 << 2, +    TCO_LOCK             = 1 << 12, +    TCO_TMR_HLT          = 1 << 11, +    TCO_TIMEOUT          = 1 << 3, +    TCO_SECOND_TO_STS    = 1 << 1, +    TCO_BOOT_STS         = 1 << 2, +}; + +/* TCO I/O registers mask bits */ +enum { +    TCO_RLD_MASK     = 0x3ff, +    TCO1_STS_MASK    = 0xe870, +    TCO2_STS_MASK    = 0xfff8, +    TCO1_CNT_MASK    = 0xfeff, +    TCO_TMR_MASK     = 0x3ff, +}; + +typedef struct TCOIORegs { +    struct { +        uint16_t rld; +        uint8_t din; +        uint8_t dout; +        uint16_t sts1; +        uint16_t sts2; +        uint16_t cnt1; +        uint16_t cnt2; +        uint8_t msg1; +        uint8_t msg2; +        uint8_t wdcnt; +        uint16_t tmr; +    } tco; +    uint8_t sw_irq_gen; + +    QEMUTimer *tco_timer; +    int64_t expire_time; +    uint8_t timeouts_no; + +    MemoryRegion io; +} TCOIORegs; + +/* tco.c */ +void acpi_pm_tco_init(TCOIORegs *tr, MemoryRegion *parent); + +extern const VMStateDescription vmstate_tco_io_sts; + +#endif /* HW_ACPI_TCO_H */ diff --git a/include/hw/acpi/tpm.h b/include/hw/acpi/tpm.h new file mode 100644 index 00000000..6d516c6a --- /dev/null +++ b/include/hw/acpi/tpm.h @@ -0,0 +1,34 @@ +/* + * tpm.h - TPM ACPI definitions + * + * Copyright (C) 2014 IBM Corporation + * + * Authors: + *  Stefan Berger <stefanb@us.ibm.com> + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + * Implementation of the TIS interface according to specs found at + * http://www.trustedcomputinggroup.org + * + */ +#ifndef HW_ACPI_TPM_H +#define HW_ACPI_TPM_H + +#define TPM_TIS_ADDR_BASE           0xFED40000 +#define TPM_TIS_ADDR_SIZE           0x5000 + +#define TPM_TIS_IRQ                 5 + +#define TPM_LOG_AREA_MINIMUM_SIZE   (64 * 1024) + +#define TPM_TCPA_ACPI_CLASS_CLIENT  0 +#define TPM_TCPA_ACPI_CLASS_SERVER  1 + +#define TPM2_ACPI_CLASS_CLIENT      0 +#define TPM2_ACPI_CLASS_SERVER      1 + +#define TPM2_START_METHOD_MMIO      6 + +#endif /* HW_ACPI_TPM_H */ diff --git a/include/hw/arm/allwinner-a10.h b/include/hw/arm/allwinner-a10.h new file mode 100644 index 00000000..01a189bc --- /dev/null +++ b/include/hw/arm/allwinner-a10.h @@ -0,0 +1,38 @@ +#ifndef ALLWINNER_H_ + +#include "qemu-common.h" +#include "qemu/error-report.h" +#include "hw/char/serial.h" +#include "hw/arm/arm.h" +#include "hw/timer/allwinner-a10-pit.h" +#include "hw/intc/allwinner-a10-pic.h" +#include "hw/net/allwinner_emac.h" + +#include "sysemu/sysemu.h" +#include "exec/address-spaces.h" + + +#define AW_A10_PIC_REG_BASE     0x01c20400 +#define AW_A10_PIT_REG_BASE     0x01c20c00 +#define AW_A10_UART0_REG_BASE   0x01c28000 +#define AW_A10_EMAC_BASE        0x01c0b000 + +#define AW_A10_SDRAM_BASE       0x40000000 + +#define TYPE_AW_A10 "allwinner-a10" +#define AW_A10(obj) OBJECT_CHECK(AwA10State, (obj), TYPE_AW_A10) + +typedef struct AwA10State { +    /*< private >*/ +    DeviceState parent_obj; +    /*< public >*/ + +    ARMCPU cpu; +    qemu_irq irq[AW_A10_PIC_INT_NR]; +    AwA10PITState timer; +    AwA10PICState intc; +    AwEmacState emac; +} AwA10State; + +#define ALLWINNER_H_ +#endif diff --git a/include/hw/arm/arm.h b/include/hw/arm/arm.h new file mode 100644 index 00000000..4dcd4f9b --- /dev/null +++ b/include/hw/arm/arm.h @@ -0,0 +1,113 @@ +/* + * Misc ARM declarations + * + * Copyright (c) 2006 CodeSourcery. + * Written by Paul Brook + * + * This code is licensed under the LGPL. + * + */ + +#ifndef ARM_MISC_H +#define ARM_MISC_H 1 + +#include "exec/memory.h" +#include "hw/irq.h" +#include "qemu/notify.h" +#include "cpu.h" + +/* armv7m.c */ +qemu_irq *armv7m_init(MemoryRegion *system_memory, int mem_size, int num_irq, +                      const char *kernel_filename, const char *cpu_model); + +/* + * struct used as a parameter of the arm_load_kernel machine init + * done notifier + */ +typedef struct { +    Notifier notifier; /* actual notifier */ +    ARMCPU *cpu; /* handle to the first cpu object */ +} ArmLoadKernelNotifier; + +/* arm_boot.c */ +struct arm_boot_info { +    uint64_t ram_size; +    const char *kernel_filename; +    const char *kernel_cmdline; +    const char *initrd_filename; +    const char *dtb_filename; +    hwaddr loader_start; +    /* multicore boards that use the default secondary core boot functions +     * need to put the address of the secondary boot code, the boot reg, +     * and the GIC address in the next 3 values, respectively. boards that +     * have their own boot functions can use these values as they want. +     */ +    hwaddr smp_loader_start; +    hwaddr smp_bootreg_addr; +    hwaddr gic_cpu_if_addr; +    int nb_cpus; +    int board_id; +    /* ARM machines that support the ARM Security Extensions use this field to +     * control whether Linux is booted as secure(true) or non-secure(false). +     */ +    bool secure_boot; +    int (*atag_board)(const struct arm_boot_info *info, void *p); +    /* multicore boards that use the default secondary core boot functions +     * can ignore these two function calls. If the default functions won't +     * work, then write_secondary_boot() should write a suitable blob of +     * code mimicking the secondary CPU startup process used by the board's +     * boot loader/boot ROM code, and secondary_cpu_reset_hook() should +     * perform any necessary CPU reset handling and set the PC for the +     * secondary CPUs to point at this boot blob. +     */ +    void (*write_secondary_boot)(ARMCPU *cpu, +                                 const struct arm_boot_info *info); +    void (*secondary_cpu_reset_hook)(ARMCPU *cpu, +                                     const struct arm_boot_info *info); +    /* if a board is able to create a dtb without a dtb file then it +     * sets get_dtb. This will only be used if no dtb file is provided +     * by the user. On success, sets *size to the length of the created +     * dtb, and returns a pointer to it. (The caller must free this memory +     * with g_free() when it has finished with it.) On failure, returns NULL. +     */ +    void *(*get_dtb)(const struct arm_boot_info *info, int *size); +    /* if a board needs to be able to modify a device tree provided by +     * the user it should implement this hook. +     */ +    void (*modify_dtb)(const struct arm_boot_info *info, void *fdt); +    /* machine init done notifier executing arm_load_dtb */ +    ArmLoadKernelNotifier load_kernel_notifier; +    /* Used internally by arm_boot.c */ +    int is_linux; +    hwaddr initrd_start; +    hwaddr initrd_size; +    hwaddr entry; + +    /* Boot firmware has been loaded, typically at address 0, with -bios or +     * -pflash. It also implies that fw_cfg_find() will succeed. +     */ +    bool firmware_loaded; +}; + +/** + * arm_load_kernel - Loads memory with everything needed to boot + * + * @cpu: handle to the first CPU object + * @info: handle to the boot info struct + * Registers a machine init done notifier that copies to memory + * everything needed to boot, depending on machine and user options: + * kernel image, boot loaders, initrd, dtb. Also registers the CPU + * reset handler. + * + * In case the machine file supports the platform bus device and its + * dynamically instantiable sysbus devices, this function must be called + * before sysbus-fdt arm_register_platform_bus_fdt_creator. Indeed the + * machine init done notifiers are called in registration reverse order. + */ +void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info); + +/* Multiplication factor to convert from system clock ticks to qemu timer +   ticks.  */ +extern int system_clock_scale; + +#endif /* !ARM_MISC_H */ diff --git a/include/hw/arm/digic.h b/include/hw/arm/digic.h new file mode 100644 index 00000000..a739d6ae --- /dev/null +++ b/include/hw/arm/digic.h @@ -0,0 +1,43 @@ +/* + * Misc Canon DIGIC declarations. + * + * Copyright (C) 2013 Antony Pavlov <antonynpavlov@gmail.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef HW_ARM_DIGIC_H +#define HW_ARM_DIGIC_H + +#include "cpu.h" + +#include "hw/timer/digic-timer.h" +#include "hw/char/digic-uart.h" + +#define TYPE_DIGIC "digic" + +#define DIGIC(obj) OBJECT_CHECK(DigicState, (obj), TYPE_DIGIC) + +#define DIGIC4_NB_TIMERS 3 + +typedef struct DigicState { +    /*< private >*/ +    DeviceState parent_obj; +    /*< public >*/ + +    ARMCPU cpu; + +    DigicTimerState timer[DIGIC4_NB_TIMERS]; +    DigicUartState uart; +} DigicState; + +#endif /* HW_ARM_DIGIC_H */ diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h new file mode 100644 index 00000000..5c1820f8 --- /dev/null +++ b/include/hw/arm/exynos4210.h @@ -0,0 +1,137 @@ +/* + *  Samsung exynos4210 SoC emulation + * + *  Copyright (c) 2011 Samsung Electronics Co., Ltd. All rights reserved. + *    Maksim Kozlov <m.kozlov@samsung.com> + *    Evgeny Voevodin <e.voevodin@samsung.com> + *    Igor Mitsyanko <i.mitsyanko@samsung.com> + * + * + *  This program is free software; you can redistribute it and/or modify it + *  under the terms of the GNU General Public License as published by the + *  Free Software Foundation; either version 2 of the License, or + *  (at your option) any later version. + * + *  This program is distributed in the hope that it will be useful, but WITHOUT + *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + *  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + *  for more details. + * + *  You should have received a copy of the GNU General Public License along + *  with this program; if not, see <http://www.gnu.org/licenses/>. + * + */ + + +#ifndef EXYNOS4210_H_ +#define EXYNOS4210_H_ + +#include "qemu-common.h" +#include "exec/memory.h" + +#define EXYNOS4210_NCPUS                    2 + +#define EXYNOS4210_DRAM0_BASE_ADDR          0x40000000 +#define EXYNOS4210_DRAM1_BASE_ADDR          0xa0000000 +#define EXYNOS4210_DRAM_MAX_SIZE            0x60000000  /* 1.5 GB */ + +#define EXYNOS4210_IROM_BASE_ADDR           0x00000000 +#define EXYNOS4210_IROM_SIZE                0x00010000  /* 64 KB */ +#define EXYNOS4210_IROM_MIRROR_BASE_ADDR    0x02000000 +#define EXYNOS4210_IROM_MIRROR_SIZE         0x00010000  /* 64 KB */ + +#define EXYNOS4210_IRAM_BASE_ADDR           0x02020000 +#define EXYNOS4210_IRAM_SIZE                0x00020000  /* 128 KB */ + +/* Secondary CPU startup code is in IROM memory */ +#define EXYNOS4210_SMP_BOOT_ADDR            EXYNOS4210_IROM_BASE_ADDR +#define EXYNOS4210_SMP_BOOT_SIZE            0x1000 +#define EXYNOS4210_BASE_BOOT_ADDR           EXYNOS4210_DRAM0_BASE_ADDR +/* Secondary CPU polling address to get loader start from */ +#define EXYNOS4210_SECOND_CPU_BOOTREG       0x10020814 + +#define EXYNOS4210_SMP_PRIVATE_BASE_ADDR    0x10500000 +#define EXYNOS4210_L2X0_BASE_ADDR           0x10502000 + +/* + * exynos4210 IRQ subsystem stub definitions. + */ +#define EXYNOS4210_IRQ_GATE_NINPUTS 2 /* Internal and External GIC */ + +#define EXYNOS4210_MAX_INT_COMBINER_OUT_IRQ  64 +#define EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ  16 +#define EXYNOS4210_MAX_INT_COMBINER_IN_IRQ   \ +    (EXYNOS4210_MAX_INT_COMBINER_OUT_IRQ * 8) +#define EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ   \ +    (EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ * 8) + +#define EXYNOS4210_COMBINER_GET_IRQ_NUM(grp, bit)  ((grp)*8 + (bit)) +#define EXYNOS4210_COMBINER_GET_GRP_NUM(irq)       ((irq) / 8) +#define EXYNOS4210_COMBINER_GET_BIT_NUM(irq) \ +    ((irq) - 8 * EXYNOS4210_COMBINER_GET_GRP_NUM(irq)) + +/* IRQs number for external and internal GIC */ +#define EXYNOS4210_EXT_GIC_NIRQ     (160-32) +#define EXYNOS4210_INT_GIC_NIRQ     64 + +#define EXYNOS4210_I2C_NUMBER               9 + +typedef struct Exynos4210Irq { +    qemu_irq int_combiner_irq[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ]; +    qemu_irq ext_combiner_irq[EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ]; +    qemu_irq int_gic_irq[EXYNOS4210_INT_GIC_NIRQ]; +    qemu_irq ext_gic_irq[EXYNOS4210_EXT_GIC_NIRQ]; +    qemu_irq board_irqs[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ]; +} Exynos4210Irq; + +typedef struct Exynos4210State { +    ARMCPU *cpu[EXYNOS4210_NCPUS]; +    Exynos4210Irq irqs; +    qemu_irq *irq_table; + +    MemoryRegion chipid_mem; +    MemoryRegion iram_mem; +    MemoryRegion irom_mem; +    MemoryRegion irom_alias_mem; +    MemoryRegion dram0_mem; +    MemoryRegion dram1_mem; +    MemoryRegion boot_secondary; +    MemoryRegion bootreg_mem; +    I2CBus *i2c_if[EXYNOS4210_I2C_NUMBER]; +} Exynos4210State; + +void exynos4210_write_secondary(ARMCPU *cpu, +        const struct arm_boot_info *info); + +Exynos4210State *exynos4210_init(MemoryRegion *system_mem, +        unsigned long ram_size); + +/* Initialize exynos4210 IRQ subsystem stub */ +qemu_irq *exynos4210_init_irq(Exynos4210Irq *env); + +/* Initialize board IRQs. + * These IRQs contain splitted Int/External Combiner and External Gic IRQs */ +void exynos4210_init_board_irqs(Exynos4210Irq *s); + +/* Get IRQ number from exynos4210 IRQ subsystem stub. + * To identify IRQ source use internal combiner group and bit number + *  grp - group number + *  bit - bit number inside group */ +uint32_t exynos4210_get_irq(uint32_t grp, uint32_t bit); + +/* + * Get Combiner input GPIO into irqs structure + */ +void exynos4210_combiner_get_gpioin(Exynos4210Irq *irqs, DeviceState *dev, +        int ext); + +/* + * exynos4210 UART + */ +DeviceState *exynos4210_uart_create(hwaddr addr, +                                    int fifo_size, +                                    int channel, +                                    CharDriverState *chr, +                                    qemu_irq irq); + +#endif /* EXYNOS4210_H_ */ diff --git a/include/hw/arm/fdt.h b/include/hw/arm/fdt.h new file mode 100644 index 00000000..c3d50150 --- /dev/null +++ b/include/hw/arm/fdt.h @@ -0,0 +1,34 @@ +/* + * + * Copyright (c) 2015 Linaro Limited + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program.  If not, see <http://www.gnu.org/licenses/>. + * + * Define macros useful when building ARM device tree nodes + */ + +#ifndef QEMU_ARM_FDT_H +#define QEMU_ARM_FDT_H + +#define GIC_FDT_IRQ_TYPE_SPI 0 +#define GIC_FDT_IRQ_TYPE_PPI 1 + +#define GIC_FDT_IRQ_FLAGS_EDGE_LO_HI 1 +#define GIC_FDT_IRQ_FLAGS_EDGE_HI_LO 2 +#define GIC_FDT_IRQ_FLAGS_LEVEL_HI 4 +#define GIC_FDT_IRQ_FLAGS_LEVEL_LO 8 + +#define GIC_FDT_IRQ_PPI_CPU_START 8 +#define GIC_FDT_IRQ_PPI_CPU_WIDTH 8 + +#endif diff --git a/include/hw/arm/imx.h b/include/hw/arm/imx.h new file mode 100644 index 00000000..ea9e0932 --- /dev/null +++ b/include/hw/arm/imx.h @@ -0,0 +1,34 @@ +/* + * i.MX31 emulation + * + * Copyright (C) 2012 Peter Chubb + * NICTA + * + * This code is released under the GPL, version 2.0 or later + * See the file `../COPYING' for details. + */ + +#ifndef IMX_H +#define IMX_H + +void imx_serial_create(int uart, const hwaddr addr, qemu_irq irq); + +typedef enum  { +    NOCLK, +    MCU, +    HSP, +    IPG, +    CLK_32k +} IMXClk; + +uint32_t imx_clock_frequency(DeviceState *s, IMXClk clock); + +void imx_timerp_create(const hwaddr addr, +                      qemu_irq irq, +                      DeviceState *ccm); +void imx_timerg_create(const hwaddr addr, +                      qemu_irq irq, +                      DeviceState *ccm); + + +#endif /* IMX_H */ diff --git a/include/hw/arm/omap.h b/include/hw/arm/omap.h new file mode 100644 index 00000000..0ad5fb88 --- /dev/null +++ b/include/hw/arm/omap.h @@ -0,0 +1,1015 @@ +/* + * Texas Instruments OMAP processors. + * + * Copyright (C) 2006-2008 Andrzej Zaborowski  <balrog@zabor.org> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 or + * (at your option) version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, see <http://www.gnu.org/licenses/>. + */ +#ifndef hw_omap_h +#include "exec/memory.h" +# define hw_omap_h		"omap.h" +#include "hw/irq.h" + +# define OMAP_EMIFS_BASE	0x00000000 +# define OMAP2_Q0_BASE		0x00000000 +# define OMAP_CS0_BASE		0x00000000 +# define OMAP_CS1_BASE		0x04000000 +# define OMAP_CS2_BASE		0x08000000 +# define OMAP_CS3_BASE		0x0c000000 +# define OMAP_EMIFF_BASE	0x10000000 +# define OMAP_IMIF_BASE		0x20000000 +# define OMAP_LOCALBUS_BASE	0x30000000 +# define OMAP2_Q1_BASE		0x40000000 +# define OMAP2_L4_BASE		0x48000000 +# define OMAP2_SRAM_BASE	0x40200000 +# define OMAP2_L3_BASE		0x68000000 +# define OMAP2_Q2_BASE		0x80000000 +# define OMAP2_Q3_BASE		0xc0000000 +# define OMAP_MPUI_BASE		0xe1000000 + +# define OMAP730_SRAM_SIZE	0x00032000 +# define OMAP15XX_SRAM_SIZE	0x00030000 +# define OMAP16XX_SRAM_SIZE	0x00004000 +# define OMAP1611_SRAM_SIZE	0x0003e800 +# define OMAP242X_SRAM_SIZE	0x000a0000 +# define OMAP243X_SRAM_SIZE	0x00010000 +# define OMAP_CS0_SIZE		0x04000000 +# define OMAP_CS1_SIZE		0x04000000 +# define OMAP_CS2_SIZE		0x04000000 +# define OMAP_CS3_SIZE		0x04000000 + +/* omap_clk.c */ +struct omap_mpu_state_s; +typedef struct clk *omap_clk; +omap_clk omap_findclk(struct omap_mpu_state_s *mpu, const char *name); +void omap_clk_init(struct omap_mpu_state_s *mpu); +void omap_clk_adduser(struct clk *clk, qemu_irq user); +void omap_clk_get(omap_clk clk); +void omap_clk_put(omap_clk clk); +void omap_clk_onoff(omap_clk clk, int on); +void omap_clk_canidle(omap_clk clk, int can); +void omap_clk_setrate(omap_clk clk, int divide, int multiply); +int64_t omap_clk_getrate(omap_clk clk); +void omap_clk_reparent(omap_clk clk, omap_clk parent); + +/* OMAP2 l4 Interconnect */ +struct omap_l4_s; +struct omap_l4_region_s { +    hwaddr offset; +    size_t size; +    int access; +}; +struct omap_l4_agent_info_s { +    int ta; +    int region; +    int regions; +    int ta_region; +}; +struct omap_target_agent_s { +    MemoryRegion iomem; +    struct omap_l4_s *bus; +    int regions; +    const struct omap_l4_region_s *start; +    hwaddr base; +    uint32_t component; +    uint32_t control; +    uint32_t status; +}; +struct omap_l4_s *omap_l4_init(MemoryRegion *address_space, +                               hwaddr base, int ta_num); + +struct omap_target_agent_s; +struct omap_target_agent_s *omap_l4ta_get( +    struct omap_l4_s *bus, +    const struct omap_l4_region_s *regions, +    const struct omap_l4_agent_info_s *agents, +    int cs); +hwaddr omap_l4_attach(struct omap_target_agent_s *ta, +                                         int region, MemoryRegion *mr); +hwaddr omap_l4_region_base(struct omap_target_agent_s *ta, +                                       int region); +hwaddr omap_l4_region_size(struct omap_target_agent_s *ta, +                                       int region); + +/* OMAP2 SDRAM controller */ +struct omap_sdrc_s; +struct omap_sdrc_s *omap_sdrc_init(MemoryRegion *sysmem, +                                   hwaddr base); +void omap_sdrc_reset(struct omap_sdrc_s *s); + +/* OMAP2 general purpose memory controller */ +struct omap_gpmc_s; +struct omap_gpmc_s *omap_gpmc_init(struct omap_mpu_state_s *mpu, +                                   hwaddr base, +                                   qemu_irq irq, qemu_irq drq); +void omap_gpmc_reset(struct omap_gpmc_s *s); +void omap_gpmc_attach(struct omap_gpmc_s *s, int cs, MemoryRegion *iomem); +void omap_gpmc_attach_nand(struct omap_gpmc_s *s, int cs, DeviceState *nand); + +/* + * Common IRQ numbers for level 1 interrupt handler + * See /usr/include/asm-arm/arch-omap/irqs.h in Linux. + */ +# define OMAP_INT_CAMERA		1 +# define OMAP_INT_FIQ			3 +# define OMAP_INT_RTDX			6 +# define OMAP_INT_DSP_MMU_ABORT		7 +# define OMAP_INT_HOST			8 +# define OMAP_INT_ABORT			9 +# define OMAP_INT_BRIDGE_PRIV		13 +# define OMAP_INT_GPIO_BANK1		14 +# define OMAP_INT_UART3			15 +# define OMAP_INT_TIMER3		16 +# define OMAP_INT_DMA_CH0_6		19 +# define OMAP_INT_DMA_CH1_7		20 +# define OMAP_INT_DMA_CH2_8		21 +# define OMAP_INT_DMA_CH3		22 +# define OMAP_INT_DMA_CH4		23 +# define OMAP_INT_DMA_CH5		24 +# define OMAP_INT_DMA_LCD		25 +# define OMAP_INT_TIMER1		26 +# define OMAP_INT_WD_TIMER		27 +# define OMAP_INT_BRIDGE_PUB		28 +# define OMAP_INT_TIMER2		30 +# define OMAP_INT_LCD_CTRL		31 + +/* + * Common OMAP-15xx IRQ numbers for level 1 interrupt handler + */ +# define OMAP_INT_15XX_IH2_IRQ		0 +# define OMAP_INT_15XX_LB_MMU		17 +# define OMAP_INT_15XX_LOCAL_BUS	29 + +/* + * OMAP-1510 specific IRQ numbers for level 1 interrupt handler + */ +# define OMAP_INT_1510_SPI_TX		4 +# define OMAP_INT_1510_SPI_RX		5 +# define OMAP_INT_1510_DSP_MAILBOX1	10 +# define OMAP_INT_1510_DSP_MAILBOX2	11 + +/* + * OMAP-310 specific IRQ numbers for level 1 interrupt handler + */ +# define OMAP_INT_310_McBSP2_TX		4 +# define OMAP_INT_310_McBSP2_RX		5 +# define OMAP_INT_310_HSB_MAILBOX1	12 +# define OMAP_INT_310_HSAB_MMU		18 + +/* + * OMAP-1610 specific IRQ numbers for level 1 interrupt handler + */ +# define OMAP_INT_1610_IH2_IRQ		0 +# define OMAP_INT_1610_IH2_FIQ		2 +# define OMAP_INT_1610_McBSP2_TX	4 +# define OMAP_INT_1610_McBSP2_RX	5 +# define OMAP_INT_1610_DSP_MAILBOX1	10 +# define OMAP_INT_1610_DSP_MAILBOX2	11 +# define OMAP_INT_1610_LCD_LINE		12 +# define OMAP_INT_1610_GPTIMER1		17 +# define OMAP_INT_1610_GPTIMER2		18 +# define OMAP_INT_1610_SSR_FIFO_0	29 + +/* + * OMAP-730 specific IRQ numbers for level 1 interrupt handler + */ +# define OMAP_INT_730_IH2_FIQ		0 +# define OMAP_INT_730_IH2_IRQ		1 +# define OMAP_INT_730_USB_NON_ISO	2 +# define OMAP_INT_730_USB_ISO		3 +# define OMAP_INT_730_ICR		4 +# define OMAP_INT_730_EAC		5 +# define OMAP_INT_730_GPIO_BANK1	6 +# define OMAP_INT_730_GPIO_BANK2	7 +# define OMAP_INT_730_GPIO_BANK3	8 +# define OMAP_INT_730_McBSP2TX		10 +# define OMAP_INT_730_McBSP2RX		11 +# define OMAP_INT_730_McBSP2RX_OVF	12 +# define OMAP_INT_730_LCD_LINE		14 +# define OMAP_INT_730_GSM_PROTECT	15 +# define OMAP_INT_730_TIMER3		16 +# define OMAP_INT_730_GPIO_BANK5	17 +# define OMAP_INT_730_GPIO_BANK6	18 +# define OMAP_INT_730_SPGIO_WR		29 + +/* + * Common IRQ numbers for level 2 interrupt handler + */ +# define OMAP_INT_KEYBOARD		1 +# define OMAP_INT_uWireTX		2 +# define OMAP_INT_uWireRX		3 +# define OMAP_INT_I2C			4 +# define OMAP_INT_MPUIO			5 +# define OMAP_INT_USB_HHC_1		6 +# define OMAP_INT_McBSP3TX		10 +# define OMAP_INT_McBSP3RX		11 +# define OMAP_INT_McBSP1TX		12 +# define OMAP_INT_McBSP1RX		13 +# define OMAP_INT_UART1			14 +# define OMAP_INT_UART2			15 +# define OMAP_INT_USB_W2FC		20 +# define OMAP_INT_1WIRE			21 +# define OMAP_INT_OS_TIMER		22 +# define OMAP_INT_OQN			23 +# define OMAP_INT_GAUGE_32K		24 +# define OMAP_INT_RTC_TIMER		25 +# define OMAP_INT_RTC_ALARM		26 +# define OMAP_INT_DSP_MMU		28 + +/* + * OMAP-1510 specific IRQ numbers for level 2 interrupt handler + */ +# define OMAP_INT_1510_BT_MCSI1TX	16 +# define OMAP_INT_1510_BT_MCSI1RX	17 +# define OMAP_INT_1510_SoSSI_MATCH	19 +# define OMAP_INT_1510_MEM_STICK	27 +# define OMAP_INT_1510_COM_SPI_RO	31 + +/* + * OMAP-310 specific IRQ numbers for level 2 interrupt handler + */ +# define OMAP_INT_310_FAC		0 +# define OMAP_INT_310_USB_HHC_2		7 +# define OMAP_INT_310_MCSI1_FE		16 +# define OMAP_INT_310_MCSI2_FE		17 +# define OMAP_INT_310_USB_W2FC_ISO	29 +# define OMAP_INT_310_USB_W2FC_NON_ISO	30 +# define OMAP_INT_310_McBSP2RX_OF	31 + +/* + * OMAP-1610 specific IRQ numbers for level 2 interrupt handler + */ +# define OMAP_INT_1610_FAC		0 +# define OMAP_INT_1610_USB_HHC_2	7 +# define OMAP_INT_1610_USB_OTG		8 +# define OMAP_INT_1610_SoSSI		9 +# define OMAP_INT_1610_BT_MCSI1TX	16 +# define OMAP_INT_1610_BT_MCSI1RX	17 +# define OMAP_INT_1610_SoSSI_MATCH	19 +# define OMAP_INT_1610_MEM_STICK	27 +# define OMAP_INT_1610_McBSP2RX_OF	31 +# define OMAP_INT_1610_STI		32 +# define OMAP_INT_1610_STI_WAKEUP	33 +# define OMAP_INT_1610_GPTIMER3		34 +# define OMAP_INT_1610_GPTIMER4		35 +# define OMAP_INT_1610_GPTIMER5		36 +# define OMAP_INT_1610_GPTIMER6		37 +# define OMAP_INT_1610_GPTIMER7		38 +# define OMAP_INT_1610_GPTIMER8		39 +# define OMAP_INT_1610_GPIO_BANK2	40 +# define OMAP_INT_1610_GPIO_BANK3	41 +# define OMAP_INT_1610_MMC2		42 +# define OMAP_INT_1610_CF		43 +# define OMAP_INT_1610_WAKE_UP_REQ	46 +# define OMAP_INT_1610_GPIO_BANK4	48 +# define OMAP_INT_1610_SPI		49 +# define OMAP_INT_1610_DMA_CH6		53 +# define OMAP_INT_1610_DMA_CH7		54 +# define OMAP_INT_1610_DMA_CH8		55 +# define OMAP_INT_1610_DMA_CH9		56 +# define OMAP_INT_1610_DMA_CH10		57 +# define OMAP_INT_1610_DMA_CH11		58 +# define OMAP_INT_1610_DMA_CH12		59 +# define OMAP_INT_1610_DMA_CH13		60 +# define OMAP_INT_1610_DMA_CH14		61 +# define OMAP_INT_1610_DMA_CH15		62 +# define OMAP_INT_1610_NAND		63 + +/* + * OMAP-730 specific IRQ numbers for level 2 interrupt handler + */ +# define OMAP_INT_730_HW_ERRORS		0 +# define OMAP_INT_730_NFIQ_PWR_FAIL	1 +# define OMAP_INT_730_CFCD		2 +# define OMAP_INT_730_CFIREQ		3 +# define OMAP_INT_730_I2C		4 +# define OMAP_INT_730_PCC		5 +# define OMAP_INT_730_MPU_EXT_NIRQ	6 +# define OMAP_INT_730_SPI_100K_1	7 +# define OMAP_INT_730_SYREN_SPI		8 +# define OMAP_INT_730_VLYNQ		9 +# define OMAP_INT_730_GPIO_BANK4	10 +# define OMAP_INT_730_McBSP1TX		11 +# define OMAP_INT_730_McBSP1RX		12 +# define OMAP_INT_730_McBSP1RX_OF	13 +# define OMAP_INT_730_UART_MODEM_IRDA_2	14 +# define OMAP_INT_730_UART_MODEM_1	15 +# define OMAP_INT_730_MCSI		16 +# define OMAP_INT_730_uWireTX		17 +# define OMAP_INT_730_uWireRX		18 +# define OMAP_INT_730_SMC_CD		19 +# define OMAP_INT_730_SMC_IREQ		20 +# define OMAP_INT_730_HDQ_1WIRE		21 +# define OMAP_INT_730_TIMER32K		22 +# define OMAP_INT_730_MMC_SDIO		23 +# define OMAP_INT_730_UPLD		24 +# define OMAP_INT_730_USB_HHC_1		27 +# define OMAP_INT_730_USB_HHC_2		28 +# define OMAP_INT_730_USB_GENI		29 +# define OMAP_INT_730_USB_OTG		30 +# define OMAP_INT_730_CAMERA_IF		31 +# define OMAP_INT_730_RNG		32 +# define OMAP_INT_730_DUAL_MODE_TIMER	33 +# define OMAP_INT_730_DBB_RF_EN		34 +# define OMAP_INT_730_MPUIO_KEYPAD	35 +# define OMAP_INT_730_SHA1_MD5		36 +# define OMAP_INT_730_SPI_100K_2	37 +# define OMAP_INT_730_RNG_IDLE		38 +# define OMAP_INT_730_MPUIO		39 +# define OMAP_INT_730_LLPC_LCD_CTRL_OFF	40 +# define OMAP_INT_730_LLPC_OE_FALLING	41 +# define OMAP_INT_730_LLPC_OE_RISING	42 +# define OMAP_INT_730_LLPC_VSYNC	43 +# define OMAP_INT_730_WAKE_UP_REQ	46 +# define OMAP_INT_730_DMA_CH6		53 +# define OMAP_INT_730_DMA_CH7		54 +# define OMAP_INT_730_DMA_CH8		55 +# define OMAP_INT_730_DMA_CH9		56 +# define OMAP_INT_730_DMA_CH10		57 +# define OMAP_INT_730_DMA_CH11		58 +# define OMAP_INT_730_DMA_CH12		59 +# define OMAP_INT_730_DMA_CH13		60 +# define OMAP_INT_730_DMA_CH14		61 +# define OMAP_INT_730_DMA_CH15		62 +# define OMAP_INT_730_NAND		63 + +/* + * OMAP-24xx common IRQ numbers + */ +# define OMAP_INT_24XX_STI		4 +# define OMAP_INT_24XX_SYS_NIRQ		7 +# define OMAP_INT_24XX_L3_IRQ		10 +# define OMAP_INT_24XX_PRCM_MPU_IRQ	11 +# define OMAP_INT_24XX_SDMA_IRQ0	12 +# define OMAP_INT_24XX_SDMA_IRQ1	13 +# define OMAP_INT_24XX_SDMA_IRQ2	14 +# define OMAP_INT_24XX_SDMA_IRQ3	15 +# define OMAP_INT_243X_MCBSP2_IRQ	16 +# define OMAP_INT_243X_MCBSP3_IRQ	17 +# define OMAP_INT_243X_MCBSP4_IRQ	18 +# define OMAP_INT_243X_MCBSP5_IRQ	19 +# define OMAP_INT_24XX_GPMC_IRQ		20 +# define OMAP_INT_24XX_GUFFAW_IRQ	21 +# define OMAP_INT_24XX_IVA_IRQ		22 +# define OMAP_INT_24XX_EAC_IRQ		23 +# define OMAP_INT_24XX_CAM_IRQ		24 +# define OMAP_INT_24XX_DSS_IRQ		25 +# define OMAP_INT_24XX_MAIL_U0_MPU	26 +# define OMAP_INT_24XX_DSP_UMA		27 +# define OMAP_INT_24XX_DSP_MMU		28 +# define OMAP_INT_24XX_GPIO_BANK1	29 +# define OMAP_INT_24XX_GPIO_BANK2	30 +# define OMAP_INT_24XX_GPIO_BANK3	31 +# define OMAP_INT_24XX_GPIO_BANK4	32 +# define OMAP_INT_243X_GPIO_BANK5	33 +# define OMAP_INT_24XX_MAIL_U3_MPU	34 +# define OMAP_INT_24XX_WDT3		35 +# define OMAP_INT_24XX_WDT4		36 +# define OMAP_INT_24XX_GPTIMER1		37 +# define OMAP_INT_24XX_GPTIMER2		38 +# define OMAP_INT_24XX_GPTIMER3		39 +# define OMAP_INT_24XX_GPTIMER4		40 +# define OMAP_INT_24XX_GPTIMER5		41 +# define OMAP_INT_24XX_GPTIMER6		42 +# define OMAP_INT_24XX_GPTIMER7		43 +# define OMAP_INT_24XX_GPTIMER8		44 +# define OMAP_INT_24XX_GPTIMER9		45 +# define OMAP_INT_24XX_GPTIMER10	46 +# define OMAP_INT_24XX_GPTIMER11	47 +# define OMAP_INT_24XX_GPTIMER12	48 +# define OMAP_INT_24XX_PKA_IRQ		50 +# define OMAP_INT_24XX_SHA1MD5_IRQ	51 +# define OMAP_INT_24XX_RNG_IRQ		52 +# define OMAP_INT_24XX_MG_IRQ		53 +# define OMAP_INT_24XX_I2C1_IRQ		56 +# define OMAP_INT_24XX_I2C2_IRQ		57 +# define OMAP_INT_24XX_MCBSP1_IRQ_TX	59 +# define OMAP_INT_24XX_MCBSP1_IRQ_RX	60 +# define OMAP_INT_24XX_MCBSP2_IRQ_TX	62 +# define OMAP_INT_24XX_MCBSP2_IRQ_RX	63 +# define OMAP_INT_243X_MCBSP1_IRQ	64 +# define OMAP_INT_24XX_MCSPI1_IRQ	65 +# define OMAP_INT_24XX_MCSPI2_IRQ	66 +# define OMAP_INT_24XX_SSI1_IRQ0	67 +# define OMAP_INT_24XX_SSI1_IRQ1	68 +# define OMAP_INT_24XX_SSI2_IRQ0	69 +# define OMAP_INT_24XX_SSI2_IRQ1	70 +# define OMAP_INT_24XX_SSI_GDD_IRQ	71 +# define OMAP_INT_24XX_UART1_IRQ	72 +# define OMAP_INT_24XX_UART2_IRQ	73 +# define OMAP_INT_24XX_UART3_IRQ	74 +# define OMAP_INT_24XX_USB_IRQ_GEN	75 +# define OMAP_INT_24XX_USB_IRQ_NISO	76 +# define OMAP_INT_24XX_USB_IRQ_ISO	77 +# define OMAP_INT_24XX_USB_IRQ_HGEN	78 +# define OMAP_INT_24XX_USB_IRQ_HSOF	79 +# define OMAP_INT_24XX_USB_IRQ_OTG	80 +# define OMAP_INT_24XX_VLYNQ_IRQ	81 +# define OMAP_INT_24XX_MMC_IRQ		83 +# define OMAP_INT_24XX_MS_IRQ		84 +# define OMAP_INT_24XX_FAC_IRQ		85 +# define OMAP_INT_24XX_MCSPI3_IRQ	91 +# define OMAP_INT_243X_HS_USB_MC	92 +# define OMAP_INT_243X_HS_USB_DMA	93 +# define OMAP_INT_243X_CARKIT		94 +# define OMAP_INT_34XX_GPTIMER12	95 + +/* omap_dma.c */ +enum omap_dma_model { +    omap_dma_3_0, +    omap_dma_3_1, +    omap_dma_3_2, +    omap_dma_4, +}; + +struct soc_dma_s; +struct soc_dma_s *omap_dma_init(hwaddr base, qemu_irq *irqs, +                MemoryRegion *sysmem, +                qemu_irq lcd_irq, struct omap_mpu_state_s *mpu, omap_clk clk, +                enum omap_dma_model model); +struct soc_dma_s *omap_dma4_init(hwaddr base, qemu_irq *irqs, +                MemoryRegion *sysmem, +                struct omap_mpu_state_s *mpu, int fifo, +                int chans, omap_clk iclk, omap_clk fclk); +void omap_dma_reset(struct soc_dma_s *s); + +struct dma_irq_map { +    int ih; +    int intr; +}; + +/* Only used in OMAP DMA 3.x gigacells */ +enum omap_dma_port { +    emiff = 0, +    emifs, +    imif,	/* omap16xx: ocp_t1 */ +    tipb, +    local,	/* omap16xx: ocp_t2 */ +    tipb_mpui, +    __omap_dma_port_last, +}; + +typedef enum { +    constant = 0, +    post_incremented, +    single_index, +    double_index, +} omap_dma_addressing_t; + +/* Only used in OMAP DMA 3.x gigacells */ +struct omap_dma_lcd_channel_s { +    enum omap_dma_port src; +    hwaddr src_f1_top; +    hwaddr src_f1_bottom; +    hwaddr src_f2_top; +    hwaddr src_f2_bottom; + +    /* Used in OMAP DMA 3.2 gigacell */ +    unsigned char brust_f1; +    unsigned char pack_f1; +    unsigned char data_type_f1; +    unsigned char brust_f2; +    unsigned char pack_f2; +    unsigned char data_type_f2; +    unsigned char end_prog; +    unsigned char repeat; +    unsigned char auto_init; +    unsigned char priority; +    unsigned char fs; +    unsigned char running; +    unsigned char bs; +    unsigned char omap_3_1_compatible_disable; +    unsigned char dst; +    unsigned char lch_type; +    int16_t element_index_f1; +    int16_t element_index_f2; +    int32_t frame_index_f1; +    int32_t frame_index_f2; +    uint16_t elements_f1; +    uint16_t frames_f1; +    uint16_t elements_f2; +    uint16_t frames_f2; +    omap_dma_addressing_t mode_f1; +    omap_dma_addressing_t mode_f2; + +    /* Destination port is fixed.  */ +    int interrupts; +    int condition; +    int dual; + +    int current_frame; +    hwaddr phys_framebuffer[2]; +    qemu_irq irq; +    struct omap_mpu_state_s *mpu; +} *omap_dma_get_lcdch(struct soc_dma_s *s); + +/* + * DMA request numbers for OMAP1 + * See /usr/include/asm-arm/arch-omap/dma.h in Linux. + */ +# define OMAP_DMA_NO_DEVICE		0 +# define OMAP_DMA_MCSI1_TX		1 +# define OMAP_DMA_MCSI1_RX		2 +# define OMAP_DMA_I2C_RX		3 +# define OMAP_DMA_I2C_TX		4 +# define OMAP_DMA_EXT_NDMA_REQ0		5 +# define OMAP_DMA_EXT_NDMA_REQ1		6 +# define OMAP_DMA_UWIRE_TX		7 +# define OMAP_DMA_MCBSP1_TX		8 +# define OMAP_DMA_MCBSP1_RX		9 +# define OMAP_DMA_MCBSP3_TX		10 +# define OMAP_DMA_MCBSP3_RX		11 +# define OMAP_DMA_UART1_TX		12 +# define OMAP_DMA_UART1_RX		13 +# define OMAP_DMA_UART2_TX		14 +# define OMAP_DMA_UART2_RX		15 +# define OMAP_DMA_MCBSP2_TX		16 +# define OMAP_DMA_MCBSP2_RX		17 +# define OMAP_DMA_UART3_TX		18 +# define OMAP_DMA_UART3_RX		19 +# define OMAP_DMA_CAMERA_IF_RX		20 +# define OMAP_DMA_MMC_TX		21 +# define OMAP_DMA_MMC_RX		22 +# define OMAP_DMA_NAND			23	/* Not in OMAP310 */ +# define OMAP_DMA_IRQ_LCD_LINE		24	/* Not in OMAP310 */ +# define OMAP_DMA_MEMORY_STICK		25	/* Not in OMAP310 */ +# define OMAP_DMA_USB_W2FC_RX0		26 +# define OMAP_DMA_USB_W2FC_RX1		27 +# define OMAP_DMA_USB_W2FC_RX2		28 +# define OMAP_DMA_USB_W2FC_TX0		29 +# define OMAP_DMA_USB_W2FC_TX1		30 +# define OMAP_DMA_USB_W2FC_TX2		31 + +/* These are only for 1610 */ +# define OMAP_DMA_CRYPTO_DES_IN		32 +# define OMAP_DMA_SPI_TX		33 +# define OMAP_DMA_SPI_RX		34 +# define OMAP_DMA_CRYPTO_HASH		35 +# define OMAP_DMA_CCP_ATTN		36 +# define OMAP_DMA_CCP_FIFO_NOT_EMPTY	37 +# define OMAP_DMA_CMT_APE_TX_CHAN_0	38 +# define OMAP_DMA_CMT_APE_RV_CHAN_0	39 +# define OMAP_DMA_CMT_APE_TX_CHAN_1	40 +# define OMAP_DMA_CMT_APE_RV_CHAN_1	41 +# define OMAP_DMA_CMT_APE_TX_CHAN_2	42 +# define OMAP_DMA_CMT_APE_RV_CHAN_2	43 +# define OMAP_DMA_CMT_APE_TX_CHAN_3	44 +# define OMAP_DMA_CMT_APE_RV_CHAN_3	45 +# define OMAP_DMA_CMT_APE_TX_CHAN_4	46 +# define OMAP_DMA_CMT_APE_RV_CHAN_4	47 +# define OMAP_DMA_CMT_APE_TX_CHAN_5	48 +# define OMAP_DMA_CMT_APE_RV_CHAN_5	49 +# define OMAP_DMA_CMT_APE_TX_CHAN_6	50 +# define OMAP_DMA_CMT_APE_RV_CHAN_6	51 +# define OMAP_DMA_CMT_APE_TX_CHAN_7	52 +# define OMAP_DMA_CMT_APE_RV_CHAN_7	53 +# define OMAP_DMA_MMC2_TX		54 +# define OMAP_DMA_MMC2_RX		55 +# define OMAP_DMA_CRYPTO_DES_OUT	56 + +/* + * DMA request numbers for the OMAP2 + */ +# define OMAP24XX_DMA_NO_DEVICE		0 +# define OMAP24XX_DMA_XTI_DMA		1	/* Not in OMAP2420 */ +# define OMAP24XX_DMA_EXT_DMAREQ0	2 +# define OMAP24XX_DMA_EXT_DMAREQ1	3 +# define OMAP24XX_DMA_GPMC		4 +# define OMAP24XX_DMA_GFX		5	/* Not in OMAP2420 */ +# define OMAP24XX_DMA_DSS		6 +# define OMAP24XX_DMA_VLYNQ_TX		7	/* Not in OMAP2420 */ +# define OMAP24XX_DMA_CWT		8	/* Not in OMAP2420 */ +# define OMAP24XX_DMA_AES_TX		9	/* Not in OMAP2420 */ +# define OMAP24XX_DMA_AES_RX		10	/* Not in OMAP2420 */ +# define OMAP24XX_DMA_DES_TX		11	/* Not in OMAP2420 */ +# define OMAP24XX_DMA_DES_RX		12	/* Not in OMAP2420 */ +# define OMAP24XX_DMA_SHA1MD5_RX	13	/* Not in OMAP2420 */ +# define OMAP24XX_DMA_EXT_DMAREQ2	14 +# define OMAP24XX_DMA_EXT_DMAREQ3	15 +# define OMAP24XX_DMA_EXT_DMAREQ4	16 +# define OMAP24XX_DMA_EAC_AC_RD		17 +# define OMAP24XX_DMA_EAC_AC_WR		18 +# define OMAP24XX_DMA_EAC_MD_UL_RD	19 +# define OMAP24XX_DMA_EAC_MD_UL_WR	20 +# define OMAP24XX_DMA_EAC_MD_DL_RD	21 +# define OMAP24XX_DMA_EAC_MD_DL_WR	22 +# define OMAP24XX_DMA_EAC_BT_UL_RD	23 +# define OMAP24XX_DMA_EAC_BT_UL_WR	24 +# define OMAP24XX_DMA_EAC_BT_DL_RD	25 +# define OMAP24XX_DMA_EAC_BT_DL_WR	26 +# define OMAP24XX_DMA_I2C1_TX		27 +# define OMAP24XX_DMA_I2C1_RX		28 +# define OMAP24XX_DMA_I2C2_TX		29 +# define OMAP24XX_DMA_I2C2_RX		30 +# define OMAP24XX_DMA_MCBSP1_TX		31 +# define OMAP24XX_DMA_MCBSP1_RX		32 +# define OMAP24XX_DMA_MCBSP2_TX		33 +# define OMAP24XX_DMA_MCBSP2_RX		34 +# define OMAP24XX_DMA_SPI1_TX0		35 +# define OMAP24XX_DMA_SPI1_RX0		36 +# define OMAP24XX_DMA_SPI1_TX1		37 +# define OMAP24XX_DMA_SPI1_RX1		38 +# define OMAP24XX_DMA_SPI1_TX2		39 +# define OMAP24XX_DMA_SPI1_RX2		40 +# define OMAP24XX_DMA_SPI1_TX3		41 +# define OMAP24XX_DMA_SPI1_RX3		42 +# define OMAP24XX_DMA_SPI2_TX0		43 +# define OMAP24XX_DMA_SPI2_RX0		44 +# define OMAP24XX_DMA_SPI2_TX1		45 +# define OMAP24XX_DMA_SPI2_RX1		46 + +# define OMAP24XX_DMA_UART1_TX		49 +# define OMAP24XX_DMA_UART1_RX		50 +# define OMAP24XX_DMA_UART2_TX		51 +# define OMAP24XX_DMA_UART2_RX		52 +# define OMAP24XX_DMA_UART3_TX		53 +# define OMAP24XX_DMA_UART3_RX		54 +# define OMAP24XX_DMA_USB_W2FC_TX0	55 +# define OMAP24XX_DMA_USB_W2FC_RX0	56 +# define OMAP24XX_DMA_USB_W2FC_TX1	57 +# define OMAP24XX_DMA_USB_W2FC_RX1	58 +# define OMAP24XX_DMA_USB_W2FC_TX2	59 +# define OMAP24XX_DMA_USB_W2FC_RX2	60 +# define OMAP24XX_DMA_MMC1_TX		61 +# define OMAP24XX_DMA_MMC1_RX		62 +# define OMAP24XX_DMA_MS		63	/* Not in OMAP2420 */ +# define OMAP24XX_DMA_EXT_DMAREQ5	64 + +/* omap[123].c */ +/* OMAP2 gp timer */ +struct omap_gp_timer_s; +struct omap_gp_timer_s *omap_gp_timer_init(struct omap_target_agent_s *ta, +                qemu_irq irq, omap_clk fclk, omap_clk iclk); +void omap_gp_timer_reset(struct omap_gp_timer_s *s); + +/* OMAP2 sysctimer */ +struct omap_synctimer_s; +struct omap_synctimer_s *omap_synctimer_init(struct omap_target_agent_s *ta, +                struct omap_mpu_state_s *mpu, omap_clk fclk, omap_clk iclk); +void omap_synctimer_reset(struct omap_synctimer_s *s); + +struct omap_uart_s; +struct omap_uart_s *omap_uart_init(hwaddr base, +                qemu_irq irq, omap_clk fclk, omap_clk iclk, +                qemu_irq txdma, qemu_irq rxdma, +                const char *label, CharDriverState *chr); +struct omap_uart_s *omap2_uart_init(MemoryRegion *sysmem, +                struct omap_target_agent_s *ta, +                qemu_irq irq, omap_clk fclk, omap_clk iclk, +                qemu_irq txdma, qemu_irq rxdma, +                const char *label, CharDriverState *chr); +void omap_uart_reset(struct omap_uart_s *s); +void omap_uart_attach(struct omap_uart_s *s, CharDriverState *chr); + +struct omap_mpuio_s; +qemu_irq *omap_mpuio_in_get(struct omap_mpuio_s *s); +void omap_mpuio_out_set(struct omap_mpuio_s *s, int line, qemu_irq handler); +void omap_mpuio_key(struct omap_mpuio_s *s, int row, int col, int down); + +struct uWireSlave { +    uint16_t (*receive)(void *opaque); +    void (*send)(void *opaque, uint16_t data); +    void *opaque; +}; +struct omap_uwire_s; +void omap_uwire_attach(struct omap_uwire_s *s, +                uWireSlave *slave, int chipselect); + +/* OMAP2 spi */ +struct omap_mcspi_s; +struct omap_mcspi_s *omap_mcspi_init(struct omap_target_agent_s *ta, int chnum, +                qemu_irq irq, qemu_irq *drq, omap_clk fclk, omap_clk iclk); +void omap_mcspi_attach(struct omap_mcspi_s *s, +                uint32_t (*txrx)(void *opaque, uint32_t, int), void *opaque, +                int chipselect); +void omap_mcspi_reset(struct omap_mcspi_s *s); + +struct I2SCodec { +    void *opaque; + +    /* The CPU can call this if it is generating the clock signal on the +     * i2s port.  The CODEC can ignore it if it is set up as a clock +     * master and generates its own clock.  */ +    void (*set_rate)(void *opaque, int in, int out); + +    void (*tx_swallow)(void *opaque); +    qemu_irq rx_swallow; +    qemu_irq tx_start; + +    int tx_rate; +    int cts; +    int rx_rate; +    int rts; + +    struct i2s_fifo_s { +        uint8_t *fifo; +        int len; +        int start; +        int size; +    } in, out; +}; +struct omap_mcbsp_s; +void omap_mcbsp_i2s_attach(struct omap_mcbsp_s *s, I2SCodec *slave); + +void omap_tap_init(struct omap_target_agent_s *ta, +                struct omap_mpu_state_s *mpu); + +/* omap_lcdc.c */ +struct omap_lcd_panel_s; +void omap_lcdc_reset(struct omap_lcd_panel_s *s); +struct omap_lcd_panel_s *omap_lcdc_init(MemoryRegion *sysmem, +                                        hwaddr base, +                                        qemu_irq irq, +                                        struct omap_dma_lcd_channel_s *dma, +                                        omap_clk clk); + +/* omap_dss.c */ +struct rfbi_chip_s { +    void *opaque; +    void (*write)(void *opaque, int dc, uint16_t value); +    void (*block)(void *opaque, int dc, void *buf, size_t len, int pitch); +    uint16_t (*read)(void *opaque, int dc); +}; +struct omap_dss_s; +void omap_dss_reset(struct omap_dss_s *s); +struct omap_dss_s *omap_dss_init(struct omap_target_agent_s *ta, +                MemoryRegion *sysmem, +                hwaddr l3_base, +                qemu_irq irq, qemu_irq drq, +                omap_clk fck1, omap_clk fck2, omap_clk ck54m, +                omap_clk ick1, omap_clk ick2); +void omap_rfbi_attach(struct omap_dss_s *s, int cs, struct rfbi_chip_s *chip); + +/* omap_mmc.c */ +struct omap_mmc_s; +struct omap_mmc_s *omap_mmc_init(hwaddr base, +                MemoryRegion *sysmem, +                BlockBackend *blk, +                qemu_irq irq, qemu_irq dma[], omap_clk clk); +struct omap_mmc_s *omap2_mmc_init(struct omap_target_agent_s *ta, +                BlockBackend *blk, qemu_irq irq, qemu_irq dma[], +                omap_clk fclk, omap_clk iclk); +void omap_mmc_reset(struct omap_mmc_s *s); +void omap_mmc_handlers(struct omap_mmc_s *s, qemu_irq ro, qemu_irq cover); +void omap_mmc_enable(struct omap_mmc_s *s, int enable); + +/* omap_i2c.c */ +I2CBus *omap_i2c_bus(DeviceState *omap_i2c); + +# define cpu_is_omap310(cpu)		(cpu->mpu_model == omap310) +# define cpu_is_omap1510(cpu)		(cpu->mpu_model == omap1510) +# define cpu_is_omap1610(cpu)		(cpu->mpu_model == omap1610) +# define cpu_is_omap1710(cpu)		(cpu->mpu_model == omap1710) +# define cpu_is_omap2410(cpu)		(cpu->mpu_model == omap2410) +# define cpu_is_omap2420(cpu)		(cpu->mpu_model == omap2420) +# define cpu_is_omap2430(cpu)		(cpu->mpu_model == omap2430) +# define cpu_is_omap3430(cpu)		(cpu->mpu_model == omap3430) +# define cpu_is_omap3630(cpu)           (cpu->mpu_model == omap3630) + +# define cpu_is_omap15xx(cpu)		\ +        (cpu_is_omap310(cpu) || cpu_is_omap1510(cpu)) +# define cpu_is_omap16xx(cpu)		\ +        (cpu_is_omap1610(cpu) || cpu_is_omap1710(cpu)) +# define cpu_is_omap24xx(cpu)		\ +        (cpu_is_omap2410(cpu) || cpu_is_omap2420(cpu) || cpu_is_omap2430(cpu)) + +# define cpu_class_omap1(cpu)		\ +        (cpu_is_omap15xx(cpu) || cpu_is_omap16xx(cpu)) +# define cpu_class_omap2(cpu)		cpu_is_omap24xx(cpu) +# define cpu_class_omap3(cpu) \ +        (cpu_is_omap3430(cpu) || cpu_is_omap3630(cpu)) + +struct omap_mpu_state_s { +    enum omap_mpu_model { +        omap310, +        omap1510, +        omap1610, +        omap1710, +        omap2410, +        omap2420, +        omap2422, +        omap2423, +        omap2430, +        omap3430, +        omap3630, +    } mpu_model; + +    ARMCPU *cpu; + +    qemu_irq *drq; + +    qemu_irq wakeup; + +    MemoryRegion ulpd_pm_iomem; +    MemoryRegion pin_cfg_iomem; +    MemoryRegion id_iomem; +    MemoryRegion id_iomem_e18; +    MemoryRegion id_iomem_ed4; +    MemoryRegion id_iomem_e20; +    MemoryRegion mpui_iomem; +    MemoryRegion tcmi_iomem; +    MemoryRegion clkm_iomem; +    MemoryRegion clkdsp_iomem; +    MemoryRegion mpui_io_iomem; +    MemoryRegion tap_iomem; +    MemoryRegion imif_ram; +    MemoryRegion emiff_ram; +    MemoryRegion sdram; +    MemoryRegion sram; + +    struct omap_dma_port_if_s { +        uint32_t (*read[3])(struct omap_mpu_state_s *s, +                        hwaddr offset); +        void (*write[3])(struct omap_mpu_state_s *s, +                        hwaddr offset, uint32_t value); +        int (*addr_valid)(struct omap_mpu_state_s *s, +                        hwaddr addr); +    } port[__omap_dma_port_last]; + +    unsigned long sdram_size; +    unsigned long sram_size; + +    /* MPUI-TIPB peripherals */ +    struct omap_uart_s *uart[3]; + +    DeviceState *gpio; + +    struct omap_mcbsp_s *mcbsp1; +    struct omap_mcbsp_s *mcbsp3; + +    /* MPU public TIPB peripherals */ +    struct omap_32khz_timer_s *os_timer; + +    struct omap_mmc_s *mmc; + +    struct omap_mpuio_s *mpuio; + +    struct omap_uwire_s *microwire; + +    struct omap_pwl_s *pwl; +    struct omap_pwt_s *pwt; +    DeviceState *i2c[2]; + +    struct omap_rtc_s *rtc; + +    struct omap_mcbsp_s *mcbsp2; + +    struct omap_lpg_s *led[2]; + +    /* MPU private TIPB peripherals */ +    DeviceState *ih[2]; + +    struct soc_dma_s *dma; + +    struct omap_mpu_timer_s *timer[3]; +    struct omap_watchdog_timer_s *wdt; + +    struct omap_lcd_panel_s *lcd; + +    uint32_t ulpd_pm_regs[21]; +    int64_t ulpd_gauge_start; + +    uint32_t func_mux_ctrl[14]; +    uint32_t comp_mode_ctrl[1]; +    uint32_t pull_dwn_ctrl[4]; +    uint32_t gate_inh_ctrl[1]; +    uint32_t voltage_ctrl[1]; +    uint32_t test_dbg_ctrl[1]; +    uint32_t mod_conf_ctrl[1]; +    int compat1509; + +    uint32_t mpui_ctrl; + +    struct omap_tipb_bridge_s *private_tipb; +    struct omap_tipb_bridge_s *public_tipb; + +    uint32_t tcmi_regs[17]; + +    struct dpll_ctl_s *dpll[3]; + +    omap_clk clks; +    struct { +        int cold_start; +        int clocking_scheme; +        uint16_t arm_ckctl; +        uint16_t arm_idlect1; +        uint16_t arm_idlect2; +        uint16_t arm_ewupct; +        uint16_t arm_rstct1; +        uint16_t arm_rstct2; +        uint16_t arm_ckout1; +        int dpll1_mode; +        uint16_t dsp_idlect1; +        uint16_t dsp_idlect2; +        uint16_t dsp_rstct2; +    } clkm; + +    /* OMAP2-only peripherals */ +    struct omap_l4_s *l4; + +    struct omap_gp_timer_s *gptimer[12]; +    struct omap_synctimer_s *synctimer; + +    struct omap_prcm_s *prcm; +    struct omap_sdrc_s *sdrc; +    struct omap_gpmc_s *gpmc; +    struct omap_sysctl_s *sysc; + +    struct omap_mcspi_s *mcspi[2]; + +    struct omap_dss_s *dss; + +    struct omap_eac_s *eac; +}; + +/* omap1.c */ +struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *system_memory, +                unsigned long sdram_size, +                const char *core); + +/* omap2.c */ +struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sysmem, +                unsigned long sdram_size, +                const char *core); + +#define OMAP_FMT_plx "%#08" HWADDR_PRIx + +uint32_t omap_badwidth_read8(void *opaque, hwaddr addr); +void omap_badwidth_write8(void *opaque, hwaddr addr, +                uint32_t value); +uint32_t omap_badwidth_read16(void *opaque, hwaddr addr); +void omap_badwidth_write16(void *opaque, hwaddr addr, +                uint32_t value); +uint32_t omap_badwidth_read32(void *opaque, hwaddr addr); +void omap_badwidth_write32(void *opaque, hwaddr addr, +                uint32_t value); + +void omap_mpu_wakeup(void *opaque, int irq, int req); + +# define OMAP_BAD_REG(paddr)		\ +        fprintf(stderr, "%s: Bad register " OMAP_FMT_plx "\n",	\ +                        __FUNCTION__, paddr) +# define OMAP_RO_REG(paddr)		\ +        fprintf(stderr, "%s: Read-only register " OMAP_FMT_plx "\n",	\ +                        __FUNCTION__, paddr) + +/* OMAP-specific Linux bootloader tags for the ATAG_BOARD area +   (Board-specifc tags are not here)  */ +#define OMAP_TAG_CLOCK		0x4f01 +#define OMAP_TAG_MMC		0x4f02 +#define OMAP_TAG_SERIAL_CONSOLE	0x4f03 +#define OMAP_TAG_USB		0x4f04 +#define OMAP_TAG_LCD		0x4f05 +#define OMAP_TAG_GPIO_SWITCH	0x4f06 +#define OMAP_TAG_UART		0x4f07 +#define OMAP_TAG_FBMEM		0x4f08 +#define OMAP_TAG_STI_CONSOLE	0x4f09 +#define OMAP_TAG_CAMERA_SENSOR	0x4f0a +#define OMAP_TAG_PARTITION	0x4f0b +#define OMAP_TAG_TEA5761	0x4f10 +#define OMAP_TAG_TMP105		0x4f11 +#define OMAP_TAG_BOOT_REASON	0x4f80 +#define OMAP_TAG_FLASH_PART_STR	0x4f81 +#define OMAP_TAG_VERSION_STR	0x4f82 + +enum { +    OMAP_GPIOSW_TYPE_COVER	= 0 << 4, +    OMAP_GPIOSW_TYPE_CONNECTION	= 1 << 4, +    OMAP_GPIOSW_TYPE_ACTIVITY	= 2 << 4, +}; + +#define OMAP_GPIOSW_INVERTED	0x0001 +#define OMAP_GPIOSW_OUTPUT	0x0002 + +# define TCMI_VERBOSE			1 + +# ifdef TCMI_VERBOSE +#  define OMAP_8B_REG(paddr)		\ +        fprintf(stderr, "%s: 8-bit register " OMAP_FMT_plx "\n",	\ +                        __FUNCTION__, paddr) +#  define OMAP_16B_REG(paddr)		\ +        fprintf(stderr, "%s: 16-bit register " OMAP_FMT_plx "\n",	\ +                        __FUNCTION__, paddr) +#  define OMAP_32B_REG(paddr)		\ +        fprintf(stderr, "%s: 32-bit register " OMAP_FMT_plx "\n",	\ +                        __FUNCTION__, paddr) +# else +#  define OMAP_8B_REG(paddr) +#  define OMAP_16B_REG(paddr) +#  define OMAP_32B_REG(paddr) +# endif + +# define OMAP_MPUI_REG_MASK		0x000007ff + +#endif /* hw_omap_h */ diff --git a/include/hw/arm/primecell.h b/include/hw/arm/primecell.h new file mode 100644 index 00000000..7337c3b3 --- /dev/null +++ b/include/hw/arm/primecell.h @@ -0,0 +1,12 @@ +#ifndef PRIMECELL_H +#define PRIMECELL_H + +/* Declarations for ARM PrimeCell based periperals.  */ +/* Also includes some devices that are currently only used by the +   ARM boards.  */ + +/* arm_sysctl GPIO lines */ +#define ARM_SYSCTL_GPIO_MMC_WPROT 0 +#define ARM_SYSCTL_GPIO_MMC_CARDIN 1 + +#endif diff --git a/include/hw/arm/pxa.h b/include/hw/arm/pxa.h new file mode 100644 index 00000000..259b8524 --- /dev/null +++ b/include/hw/arm/pxa.h @@ -0,0 +1,191 @@ +/* + * Intel XScale PXA255/270 processor support. + * + * Copyright (c) 2006 Openedhand Ltd. + * Written by Andrzej Zaborowski <balrog@zabor.org> + * + * This code is licensed under the GNU GPL v2. + */ +#ifndef PXA_H +# define PXA_H			"pxa.h" + +#include "exec/memory.h" + +/* Interrupt numbers */ +# define PXA2XX_PIC_SSP3	0 +# define PXA2XX_PIC_USBH2	2 +# define PXA2XX_PIC_USBH1	3 +# define PXA2XX_PIC_KEYPAD	4 +# define PXA2XX_PIC_PWRI2C	6 +# define PXA25X_PIC_HWUART	7 +# define PXA27X_PIC_OST_4_11	7 +# define PXA2XX_PIC_GPIO_0	8 +# define PXA2XX_PIC_GPIO_1	9 +# define PXA2XX_PIC_GPIO_X	10 +# define PXA2XX_PIC_I2S 	13 +# define PXA26X_PIC_ASSP	15 +# define PXA25X_PIC_NSSP	16 +# define PXA27X_PIC_SSP2	16 +# define PXA2XX_PIC_LCD		17 +# define PXA2XX_PIC_I2C		18 +# define PXA2XX_PIC_ICP		19 +# define PXA2XX_PIC_STUART	20 +# define PXA2XX_PIC_BTUART	21 +# define PXA2XX_PIC_FFUART	22 +# define PXA2XX_PIC_MMC		23 +# define PXA2XX_PIC_SSP		24 +# define PXA2XX_PIC_DMA		25 +# define PXA2XX_PIC_OST_0	26 +# define PXA2XX_PIC_RTC1HZ	30 +# define PXA2XX_PIC_RTCALARM	31 + +/* DMA requests */ +# define PXA2XX_RX_RQ_I2S	2 +# define PXA2XX_TX_RQ_I2S	3 +# define PXA2XX_RX_RQ_BTUART	4 +# define PXA2XX_TX_RQ_BTUART	5 +# define PXA2XX_RX_RQ_FFUART	6 +# define PXA2XX_TX_RQ_FFUART	7 +# define PXA2XX_RX_RQ_SSP1	13 +# define PXA2XX_TX_RQ_SSP1	14 +# define PXA2XX_RX_RQ_SSP2	15 +# define PXA2XX_TX_RQ_SSP2	16 +# define PXA2XX_RX_RQ_ICP	17 +# define PXA2XX_TX_RQ_ICP	18 +# define PXA2XX_RX_RQ_STUART	19 +# define PXA2XX_TX_RQ_STUART	20 +# define PXA2XX_RX_RQ_MMCI	21 +# define PXA2XX_TX_RQ_MMCI	22 +# define PXA2XX_USB_RQ(x)	((x) + 24) +# define PXA2XX_RX_RQ_SSP3	66 +# define PXA2XX_TX_RQ_SSP3	67 + +# define PXA2XX_SDRAM_BASE	0xa0000000 +# define PXA2XX_INTERNAL_BASE	0x5c000000 +# define PXA2XX_INTERNAL_SIZE	0x40000 + +/* pxa2xx_pic.c */ +DeviceState *pxa2xx_pic_init(hwaddr base, ARMCPU *cpu); + +/* pxa2xx_gpio.c */ +DeviceState *pxa2xx_gpio_init(hwaddr base, +                              ARMCPU *cpu, DeviceState *pic, int lines); +void pxa2xx_gpio_read_notifier(DeviceState *dev, qemu_irq handler); + +/* pxa2xx_dma.c */ +DeviceState *pxa255_dma_init(hwaddr base, qemu_irq irq); +DeviceState *pxa27x_dma_init(hwaddr base, qemu_irq irq); + +/* pxa2xx_lcd.c */ +typedef struct PXA2xxLCDState PXA2xxLCDState; +PXA2xxLCDState *pxa2xx_lcdc_init(MemoryRegion *sysmem, +                hwaddr base, qemu_irq irq); +void pxa2xx_lcd_vsync_notifier(PXA2xxLCDState *s, qemu_irq handler); +void pxa2xx_lcdc_oritentation(void *opaque, int angle); + +/* pxa2xx_mmci.c */ +typedef struct PXA2xxMMCIState PXA2xxMMCIState; +PXA2xxMMCIState *pxa2xx_mmci_init(MemoryRegion *sysmem, +                hwaddr base, +                BlockBackend *blk, qemu_irq irq, +                qemu_irq rx_dma, qemu_irq tx_dma); +void pxa2xx_mmci_handlers(PXA2xxMMCIState *s, qemu_irq readonly, +                qemu_irq coverswitch); + +/* pxa2xx_pcmcia.c */ +typedef struct PXA2xxPCMCIAState PXA2xxPCMCIAState; +PXA2xxPCMCIAState *pxa2xx_pcmcia_init(MemoryRegion *sysmem, +                                      hwaddr base); +int pxa2xx_pcmcia_attach(void *opaque, PCMCIACardState *card); +int pxa2xx_pcmcia_detach(void *opaque); +void pxa2xx_pcmcia_set_irq_cb(void *opaque, qemu_irq irq, qemu_irq cd_irq); + +/* pxa2xx_keypad.c */ +struct  keymap { +    int8_t column; +    int8_t row; +}; +typedef struct PXA2xxKeyPadState PXA2xxKeyPadState; +PXA2xxKeyPadState *pxa27x_keypad_init(MemoryRegion *sysmem, +                                      hwaddr base, +                                      qemu_irq irq); +void pxa27x_register_keypad(PXA2xxKeyPadState *kp, +                            const struct keymap *map, int size); + +/* pxa2xx.c */ +typedef struct PXA2xxI2CState PXA2xxI2CState; +PXA2xxI2CState *pxa2xx_i2c_init(hwaddr base, +                qemu_irq irq, uint32_t page_size); +I2CBus *pxa2xx_i2c_bus(PXA2xxI2CState *s); + +typedef struct PXA2xxI2SState PXA2xxI2SState; +typedef struct PXA2xxFIrState PXA2xxFIrState; + +typedef struct { +    ARMCPU *cpu; +    DeviceState *pic; +    qemu_irq reset; +    MemoryRegion sdram; +    MemoryRegion internal; +    MemoryRegion cm_iomem; +    MemoryRegion mm_iomem; +    MemoryRegion pm_iomem; +    DeviceState *dma; +    DeviceState *gpio; +    PXA2xxLCDState *lcd; +    SSIBus **ssp; +    PXA2xxI2CState *i2c[2]; +    PXA2xxMMCIState *mmc; +    PXA2xxPCMCIAState *pcmcia[2]; +    PXA2xxI2SState *i2s; +    PXA2xxFIrState *fir; +    PXA2xxKeyPadState *kp; + +    /* Power management */ +    hwaddr pm_base; +    uint32_t pm_regs[0x40]; + +    /* Clock management */ +    hwaddr cm_base; +    uint32_t cm_regs[4]; +    uint32_t clkcfg; + +    /* Memory management */ +    hwaddr mm_base; +    uint32_t mm_regs[0x1a]; + +    /* Performance monitoring */ +    uint32_t pmnc; +} PXA2xxState; + +struct PXA2xxI2SState { +    MemoryRegion iomem; +    qemu_irq irq; +    qemu_irq rx_dma; +    qemu_irq tx_dma; +    void (*data_req)(void *, int, int); + +    uint32_t control[2]; +    uint32_t status; +    uint32_t mask; +    uint32_t clk; + +    int enable; +    int rx_len; +    int tx_len; +    void (*codec_out)(void *, uint32_t); +    uint32_t (*codec_in)(void *); +    void *opaque; + +    int fifo_len; +    uint32_t fifo[16]; +}; + +# define PA_FMT			"0x%08lx" +# define REG_FMT		"0x" TARGET_FMT_plx + +PXA2xxState *pxa270_init(MemoryRegion *address_space, unsigned int sdram_size, +                         const char *revision); +PXA2xxState *pxa255_init(MemoryRegion *address_space, unsigned int sdram_size); + +#endif	/* PXA_H */ diff --git a/include/hw/arm/sharpsl.h b/include/hw/arm/sharpsl.h new file mode 100644 index 00000000..13981a6d --- /dev/null +++ b/include/hw/arm/sharpsl.h @@ -0,0 +1,17 @@ +/* + * Common declarations for the Zaurii. + * + * This file is licensed under the GNU GPL. + */ +#ifndef QEMU_SHARPSL_H +#define QEMU_SHARPSL_H + +#define zaurus_printf(format, ...)	\ +    fprintf(stderr, "%s: " format, __FUNCTION__, ##__VA_ARGS__) + +/* zaurus.c */ + +#define SL_PXA_PARAM_BASE	0xa0000a00 +void sl_bootparam_write(hwaddr ptr); + +#endif diff --git a/include/hw/arm/soc_dma.h b/include/hw/arm/soc_dma.h new file mode 100644 index 00000000..7379731a --- /dev/null +++ b/include/hw/arm/soc_dma.h @@ -0,0 +1,116 @@ +/* + * On-chip DMA controller framework. + * + * Copyright (C) 2008 Nokia Corporation + * Written by Andrzej Zaborowski <andrew@openedhand.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 or + * (at your option) version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef HW_SOC_DMA_H +#define HW_SOC_DMA_H 1 + + +#include "exec/memory.h" +#include "hw/irq.h" + +struct soc_dma_s; +struct soc_dma_ch_s; +typedef void (*soc_dma_io_t)(void *opaque, uint8_t *buf, int len); +typedef void (*soc_dma_transfer_t)(struct soc_dma_ch_s *ch); + +enum soc_dma_port_type { +    soc_dma_port_mem, +    soc_dma_port_fifo, +    soc_dma_port_other, +}; + +enum soc_dma_access_type { +    soc_dma_access_const, +    soc_dma_access_linear, +    soc_dma_access_other, +}; + +struct soc_dma_ch_s { +    /* Private */ +    struct soc_dma_s *dma; +    int num; +    QEMUTimer *timer; + +    /* Set by soc_dma.c */ +    int enable; +    int update; + +    /* This should be set by dma->setup_fn().  */ +    int bytes; +    /* Initialised by the DMA module, call soc_dma_ch_update after writing.  */ +    enum soc_dma_access_type type[2]; +    hwaddr vaddr[2];	/* Updated by .transfer_fn().  */ +    /* Private */ +    void *paddr[2]; +    soc_dma_io_t io_fn[2]; +    void *io_opaque[2]; + +    int running; +    soc_dma_transfer_t transfer_fn; + +    /* Set and used by the DMA module.  */ +    void *opaque; +}; + +struct soc_dma_s { +    /* Following fields are set by the SoC DMA module and can be used +     * by anybody.  */ +    uint64_t drqbmp;	/* Is zeroed by soc_dma_reset() */ +    qemu_irq *drq; +    void *opaque; +    int64_t freq; +    soc_dma_transfer_t transfer_fn; +    soc_dma_transfer_t setup_fn; +    /* Set by soc_dma_init() for use by the DMA module.  */ +    struct soc_dma_ch_s *ch; +}; + +/* Call to activate or stop a DMA channel.  */ +void soc_dma_set_request(struct soc_dma_ch_s *ch, int level); +/* Call after every write to one of the following fields and before + * calling soc_dma_set_request(ch, 1): + *   ch->type[0...1], + *   ch->vaddr[0...1], + *   ch->paddr[0...1], + * or after a soc_dma_port_add_fifo() or soc_dma_port_add_mem().  */ +void soc_dma_ch_update(struct soc_dma_ch_s *ch); + +/* The SoC should call this when the DMA module is being reset.  */ +void soc_dma_reset(struct soc_dma_s *s); +struct soc_dma_s *soc_dma_init(int n); + +void soc_dma_port_add_fifo(struct soc_dma_s *dma, hwaddr virt_base, +                soc_dma_io_t fn, void *opaque, int out); +void soc_dma_port_add_mem(struct soc_dma_s *dma, uint8_t *phys_base, +                hwaddr virt_base, size_t size); + +static inline void soc_dma_port_add_fifo_in(struct soc_dma_s *dma, +                hwaddr virt_base, soc_dma_io_t fn, void *opaque) +{ +    return soc_dma_port_add_fifo(dma, virt_base, fn, opaque, 0); +} + +static inline void soc_dma_port_add_fifo_out(struct soc_dma_s *dma, +                hwaddr virt_base, soc_dma_io_t fn, void *opaque) +{ +    return soc_dma_port_add_fifo(dma, virt_base, fn, opaque, 1); +} + +#endif diff --git a/include/hw/arm/stm32f205_soc.h b/include/hw/arm/stm32f205_soc.h new file mode 100644 index 00000000..0390eff8 --- /dev/null +++ b/include/hw/arm/stm32f205_soc.h @@ -0,0 +1,57 @@ +/* + * STM32F205 SoC + * + * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me> + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * 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 OTHER + * 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. + */ + +#ifndef HW_ARM_STM32F205SOC_H +#define HW_ARM_STM32F205SOC_H + +#include "hw/misc/stm32f2xx_syscfg.h" +#include "hw/timer/stm32f2xx_timer.h" +#include "hw/char/stm32f2xx_usart.h" + +#define TYPE_STM32F205_SOC "stm32f205-soc" +#define STM32F205_SOC(obj) \ +    OBJECT_CHECK(STM32F205State, (obj), TYPE_STM32F205_SOC) + +#define STM_NUM_USARTS 6 +#define STM_NUM_TIMERS 4 + +#define FLASH_BASE_ADDRESS 0x08000000 +#define FLASH_SIZE (1024 * 1024) +#define SRAM_BASE_ADDRESS 0x20000000 +#define SRAM_SIZE (128 * 1024) + +typedef struct STM32F205State { +    /*< private >*/ +    SysBusDevice parent_obj; +    /*< public >*/ + +    char *kernel_filename; +    char *cpu_model; + +    STM32F2XXSyscfgState syscfg; +    STM32F2XXUsartState usart[STM_NUM_USARTS]; +    STM32F2XXTimerState timer[STM_NUM_TIMERS]; +} STM32F205State; + +#endif diff --git a/include/hw/arm/sysbus-fdt.h b/include/hw/arm/sysbus-fdt.h new file mode 100644 index 00000000..e15bb818 --- /dev/null +++ b/include/hw/arm/sysbus-fdt.h @@ -0,0 +1,60 @@ +/* + * Dynamic sysbus device tree node generation API + * + * Copyright Linaro Limited, 2014 + * + * Authors: + *  Alex Graf <agraf@suse.de> + *  Eric Auger <eric.auger@linaro.org> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program.  If not, see <http://www.gnu.org/licenses/>. + * + */ + +#ifndef HW_ARM_SYSBUS_FDT_H +#define HW_ARM_SYSBUS_FDT_H + +#include "hw/arm/arm.h" +#include "qemu-common.h" +#include "hw/sysbus.h" + +/* + * struct that contains dimensioning parameters of the platform bus + */ +typedef struct { +    hwaddr platform_bus_base; /* start address of the bus */ +    hwaddr platform_bus_size; /* size of the bus */ +    int platform_bus_first_irq; /* first hwirq assigned to the bus */ +    int platform_bus_num_irqs; /* number of hwirq assigned to the bus */ +} ARMPlatformBusSystemParams; + +/* + * struct that contains all relevant info to build the fdt nodes of + * platform bus and attached dynamic sysbus devices + * in the future might be augmented with additional info + * such as PHY, CLK handles ... + */ +typedef struct { +    const ARMPlatformBusSystemParams *system_params; +    struct arm_boot_info *binfo; +    const char *intc; /* parent interrupt controller name */ +} ARMPlatformBusFDTParams; + +/** + * arm_register_platform_bus_fdt_creator - register a machine init done + * notifier that creates the device tree nodes of the platform bus and + * associated dynamic sysbus devices + */ +void arm_register_platform_bus_fdt_creator(ARMPlatformBusFDTParams *fdt_params); + +#endif diff --git a/include/hw/arm/virt-acpi-build.h b/include/hw/arm/virt-acpi-build.h new file mode 100644 index 00000000..04f174d5 --- /dev/null +++ b/include/hw/arm/virt-acpi-build.h @@ -0,0 +1,44 @@ +/* + * + * Copyright (c) 2015 HUAWEI TECHNOLOGIES CO.,LTD. + * + * Author: Shannon Zhao <zhaoshenglong@huawei.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program.  If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef QEMU_VIRT_ACPI_BUILD_H +#define QEMU_VIRT_ACPI_BUILD_H + +#include "qemu-common.h" +#include "hw/arm/virt.h" + +#define VIRT_ACPI_CPU_ID_LIMIT 8 +#define ACPI_GICC_ENABLED 1 + +typedef struct VirtGuestInfo { +    int smp_cpus; +    FWCfgState *fw_cfg; +    const MemMapEntry *memmap; +    const int *irqmap; +} VirtGuestInfo; + + +typedef struct VirtGuestInfoState { +    VirtGuestInfo info; +    Notifier machine_done; +} VirtGuestInfoState; + +void virt_acpi_setup(VirtGuestInfo *guest_info); + +#endif diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h new file mode 100644 index 00000000..d22fd8e5 --- /dev/null +++ b/include/hw/arm/virt.h @@ -0,0 +1,67 @@ +/* + * + * Copyright (c) 2015 Linaro Limited + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program.  If not, see <http://www.gnu.org/licenses/>. + * + * Emulate a virtual board which works by passing Linux all the information + * it needs about what devices are present via the device tree. + * There are some restrictions about what we can do here: + *  + we can only present devices whose Linux drivers will work based + *    purely on the device tree with no platform data at all + *  + we want to present a very stripped-down minimalist platform, + *    both because this reduces the security attack surface from the guest + *    and also because it reduces our exposure to being broken when + *    the kernel updates its device tree bindings and requires further + *    information in a device binding that we aren't providing. + * This is essentially the same approach kvmtool uses. + */ + +#ifndef QEMU_ARM_VIRT_H +#define QEMU_ARM_VIRT_H + +#include "qemu-common.h" + +#define NUM_GICV2M_SPIS       64 +#define NUM_VIRTIO_TRANSPORTS 32 + +#define ARCH_TIMER_VIRT_IRQ   11 +#define ARCH_TIMER_S_EL1_IRQ  13 +#define ARCH_TIMER_NS_EL1_IRQ 14 +#define ARCH_TIMER_NS_EL2_IRQ 10 + +enum { +    VIRT_FLASH, +    VIRT_MEM, +    VIRT_CPUPERIPHS, +    VIRT_GIC_DIST, +    VIRT_GIC_CPU, +    VIRT_UART, +    VIRT_MMIO, +    VIRT_RTC, +    VIRT_FW_CFG, +    VIRT_PCIE, +    VIRT_PCIE_MMIO, +    VIRT_PCIE_PIO, +    VIRT_PCIE_ECAM, +    VIRT_GIC_V2M, +    VIRT_PLATFORM_BUS, +}; + +typedef struct MemMapEntry { +    hwaddr base; +    hwaddr size; +} MemMapEntry; + + +#endif diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h new file mode 100644 index 00000000..c379632f --- /dev/null +++ b/include/hw/arm/xlnx-zynqmp.h @@ -0,0 +1,63 @@ +/* + * Xilinx Zynq MPSoC emulation + * + * Copyright (C) 2015 Xilinx Inc + * Written by Peter Crosthwaite <peter.crosthwaite@xilinx.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef XLNX_ZYNQMP_H + +#include "qemu-common.h" +#include "hw/arm/arm.h" +#include "hw/intc/arm_gic.h" +#include "hw/net/cadence_gem.h" +#include "hw/char/cadence_uart.h" + +#define TYPE_XLNX_ZYNQMP "xlnx,zynqmp" +#define XLNX_ZYNQMP(obj) OBJECT_CHECK(XlnxZynqMPState, (obj), \ +                                       TYPE_XLNX_ZYNQMP) + +#define XLNX_ZYNQMP_NUM_APU_CPUS 4 +#define XLNX_ZYNQMP_NUM_RPU_CPUS 2 +#define XLNX_ZYNQMP_NUM_GEMS 4 +#define XLNX_ZYNQMP_NUM_UARTS 2 + +#define XLNX_ZYNQMP_GIC_REGIONS 2 + +/* ZynqMP maps the ARM GIC regions (GICC, GICD ...) at consecutive 64k offsets + * and under-decodes the 64k region. This mirrors the 4k regions to every 4k + * aligned address in the 64k region. To implement each GIC region needs a + * number of memory region aliases. + */ + +#define XLNX_ZYNQMP_GIC_REGION_SIZE 0x4000 +#define XLNX_ZYNQMP_GIC_ALIASES     (0x10000 / XLNX_ZYNQMP_GIC_REGION_SIZE - 1) + +typedef struct XlnxZynqMPState { +    /*< private >*/ +    DeviceState parent_obj; + +    /*< public >*/ +    ARMCPU apu_cpu[XLNX_ZYNQMP_NUM_APU_CPUS]; +    ARMCPU rpu_cpu[XLNX_ZYNQMP_NUM_RPU_CPUS]; +    GICState gic; +    MemoryRegion gic_mr[XLNX_ZYNQMP_GIC_REGIONS][XLNX_ZYNQMP_GIC_ALIASES]; +    CadenceGEMState gem[XLNX_ZYNQMP_NUM_GEMS]; +    CadenceUARTState uart[XLNX_ZYNQMP_NUM_UARTS]; + +    char *boot_cpu; +    ARMCPU *boot_cpu_ptr; +}  XlnxZynqMPState; + +#define XLNX_ZYNQMP_H +#endif diff --git a/include/hw/audio/audio.h b/include/hw/audio/audio.h new file mode 100644 index 00000000..b28abdd3 --- /dev/null +++ b/include/hw/audio/audio.h @@ -0,0 +1,10 @@ +#ifndef HW_AUDIODEV_H +#define HW_AUDIODEV_H 1 + +void isa_register_soundhw(const char *name, const char *descr, +                          int (*init_isa)(ISABus *bus)); + +void pci_register_soundhw(const char *name, const char *descr, +                          int (*init_pci)(PCIBus *bus)); + +#endif diff --git a/include/hw/audio/pcspk.h b/include/hw/audio/pcspk.h new file mode 100644 index 00000000..ef95dd13 --- /dev/null +++ b/include/hw/audio/pcspk.h @@ -0,0 +1,47 @@ +/* + * QEMU PC speaker emulation + * + * Copyright (c) 2006 Joachim Henke + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * 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 OTHER + * 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. + */ + +#ifndef HW_PCSPK_H +#define HW_PCSPK_H + +#include "hw/hw.h" +#include "hw/isa/isa.h" + +#define TYPE_PC_SPEAKER "isa-pcspk" + +static inline ISADevice *pcspk_init(ISABus *bus, ISADevice *pit) +{ +    DeviceState *dev; +    ISADevice *isadev; + +    isadev = isa_create(bus, TYPE_PC_SPEAKER); +    dev = DEVICE(isadev); +    qdev_prop_set_uint32(dev, "iobase", 0x61); +    qdev_prop_set_ptr(dev, "pit", pit); +    qdev_init_nofail(dev); + +    return isadev; +} + +#endif /* !HW_PCSPK_H */ diff --git a/include/hw/block/block.h b/include/hw/block/block.h new file mode 100644 index 00000000..8d7c4b41 --- /dev/null +++ b/include/hw/block/block.h @@ -0,0 +1,75 @@ +/* + * Common code for block device models + * + * Copyright (C) 2012 Red Hat, Inc. + * Copyright (c) 2003-2008 Fabrice Bellard + * + * This work is licensed under the terms of the GNU GPL, version 2 or + * later.  See the COPYING file in the top-level directory. + */ + +#ifndef HW_BLOCK_COMMON_H +#define HW_BLOCK_COMMON_H + +#include "qemu-common.h" +#include "qapi/error.h" + +/* Configuration */ + +typedef struct BlockConf { +    BlockBackend *blk; +    uint16_t physical_block_size; +    uint16_t logical_block_size; +    uint16_t min_io_size; +    uint32_t opt_io_size; +    int32_t bootindex; +    uint32_t discard_granularity; +    /* geometry, not all devices use this */ +    uint32_t cyls, heads, secs; +} BlockConf; + +static inline unsigned int get_physical_block_exp(BlockConf *conf) +{ +    unsigned int exp = 0, size; + +    for (size = conf->physical_block_size; +        size > conf->logical_block_size; +        size >>= 1) { +        exp++; +    } + +    return exp; +} + +#define DEFINE_BLOCK_PROPERTIES(_state, _conf)                          \ +    DEFINE_PROP_DRIVE("drive", _state, _conf.blk),                      \ +    DEFINE_PROP_BLOCKSIZE("logical_block_size", _state,                 \ +                          _conf.logical_block_size),                    \ +    DEFINE_PROP_BLOCKSIZE("physical_block_size", _state,                \ +                          _conf.physical_block_size),                   \ +    DEFINE_PROP_UINT16("min_io_size", _state, _conf.min_io_size, 0),  \ +    DEFINE_PROP_UINT32("opt_io_size", _state, _conf.opt_io_size, 0),    \ +    DEFINE_PROP_UINT32("discard_granularity", _state, \ +                       _conf.discard_granularity, -1) + +#define DEFINE_BLOCK_CHS_PROPERTIES(_state, _conf)      \ +    DEFINE_PROP_UINT32("cyls", _state, _conf.cyls, 0),  \ +    DEFINE_PROP_UINT32("heads", _state, _conf.heads, 0), \ +    DEFINE_PROP_UINT32("secs", _state, _conf.secs, 0) + +/* Configuration helpers */ + +void blkconf_serial(BlockConf *conf, char **serial); +void blkconf_geometry(BlockConf *conf, int *trans, +                      unsigned cyls_max, unsigned heads_max, unsigned secs_max, +                      Error **errp); +void blkconf_blocksizes(BlockConf *conf); + +/* Hard disk geometry */ + +void hd_geometry_guess(BlockBackend *blk, +                       uint32_t *pcyls, uint32_t *pheads, uint32_t *psecs, +                       int *ptrans); +int hd_bios_chs_auto_trans(uint32_t cyls, uint32_t heads, uint32_t secs); + +#endif diff --git a/include/hw/block/fdc.h b/include/hw/block/fdc.h new file mode 100644 index 00000000..d48b2f86 --- /dev/null +++ b/include/hw/block/fdc.h @@ -0,0 +1,26 @@ +#ifndef HW_FDC_H +#define HW_FDC_H + +#include "qemu-common.h" + +/* fdc.c */ +#define MAX_FD 2 + +typedef enum FDriveType { +    FDRIVE_DRV_144  = 0x00,   /* 1.44 MB 3"5 drive      */ +    FDRIVE_DRV_288  = 0x01,   /* 2.88 MB 3"5 drive      */ +    FDRIVE_DRV_120  = 0x02,   /* 1.2  MB 5"25 drive     */ +    FDRIVE_DRV_NONE = 0x03,   /* No drive connected     */ +} FDriveType; + +#define TYPE_ISA_FDC "isa-fdc" + +ISADevice *fdctrl_init_isa(ISABus *bus, DriveInfo **fds); +void fdctrl_init_sysbus(qemu_irq irq, int dma_chann, +                        hwaddr mmio_base, DriveInfo **fds); +void sun4m_fdctrl_init(qemu_irq irq, hwaddr io_base, +                       DriveInfo **fds, qemu_irq *fdc_tc); + +FDriveType isa_fdc_get_drive_type(ISADevice *fdc, int i); + +#endif diff --git a/include/hw/block/flash.h b/include/hw/block/flash.h new file mode 100644 index 00000000..50ccbbcf --- /dev/null +++ b/include/hw/block/flash.h @@ -0,0 +1,64 @@ +#ifndef HW_FLASH_H +#define HW_FLASH_H 1 + +/* NOR flash devices */ + +#include "exec/memory.h" + +typedef struct pflash_t pflash_t; + +/* pflash_cfi01.c */ +pflash_t *pflash_cfi01_register(hwaddr base, +                                DeviceState *qdev, const char *name, +                                hwaddr size, +                                BlockBackend *blk, +                                uint32_t sector_len, int nb_blocs, int width, +                                uint16_t id0, uint16_t id1, +                                uint16_t id2, uint16_t id3, int be); + +/* pflash_cfi02.c */ +pflash_t *pflash_cfi02_register(hwaddr base, +                                DeviceState *qdev, const char *name, +                                hwaddr size, +                                BlockBackend *blk, uint32_t sector_len, +                                int nb_blocs, int nb_mappings, int width, +                                uint16_t id0, uint16_t id1, +                                uint16_t id2, uint16_t id3, +                                uint16_t unlock_addr0, uint16_t unlock_addr1, +                                int be); + +MemoryRegion *pflash_cfi01_get_memory(pflash_t *fl); + +/* nand.c */ +DeviceState *nand_init(BlockBackend *blk, int manf_id, int chip_id); +void nand_setpins(DeviceState *dev, uint8_t cle, uint8_t ale, +                  uint8_t ce, uint8_t wp, uint8_t gnd); +void nand_getpins(DeviceState *dev, int *rb); +void nand_setio(DeviceState *dev, uint32_t value); +uint32_t nand_getio(DeviceState *dev); +uint32_t nand_getbuswidth(DeviceState *dev); + +#define NAND_MFR_TOSHIBA	0x98 +#define NAND_MFR_SAMSUNG	0xec +#define NAND_MFR_FUJITSU	0x04 +#define NAND_MFR_NATIONAL	0x8f +#define NAND_MFR_RENESAS	0x07 +#define NAND_MFR_STMICRO	0x20 +#define NAND_MFR_HYNIX		0xad +#define NAND_MFR_MICRON		0x2c + +/* onenand.c */ +void *onenand_raw_otp(DeviceState *onenand_device); + +/* ecc.c */ +typedef struct { +    uint8_t cp;		/* Column parity */ +    uint16_t lp[2];	/* Line parity */ +    uint16_t count; +} ECCState; + +uint8_t ecc_digest(ECCState *s, uint8_t sample); +void ecc_reset(ECCState *s); +extern VMStateDescription vmstate_ecc_state; + +#endif diff --git a/include/hw/boards.h b/include/hw/boards.h new file mode 100644 index 00000000..2aec9cbb --- /dev/null +++ b/include/hw/boards.h @@ -0,0 +1,154 @@ +/* Declarations for use by board files for creating devices.  */ + +#ifndef HW_BOARDS_H +#define HW_BOARDS_H + +#include "qemu/typedefs.h" +#include "sysemu/blockdev.h" +#include "sysemu/accel.h" +#include "hw/qdev.h" +#include "qom/object.h" + + +typedef void QEMUMachineInitFunc(MachineState *ms); + +typedef void QEMUMachineResetFunc(void); + +typedef void QEMUMachineHotAddCPUFunc(const int64_t id, Error **errp); + +typedef int QEMUMachineGetKvmtypeFunc(const char *arg); + +struct QEMUMachine { +    const char *name; +    const char *desc; +    QEMUMachineInitFunc *init; +    QEMUMachineGetKvmtypeFunc *kvm_type; +    BlockInterfaceType block_default_type; +    int max_cpus; +    unsigned int +        no_sdcard:1, +        has_dynamic_sysbus:1; +    int is_default; +    const char *default_machine_opts; +    const char *default_boot_order; +}; + +void memory_region_allocate_system_memory(MemoryRegion *mr, Object *owner, +                                          const char *name, +                                          uint64_t ram_size); + +int qemu_register_machine(QEMUMachine *m); + +#define TYPE_MACHINE_SUFFIX "-machine" +#define TYPE_MACHINE "machine" +#undef MACHINE  /* BSD defines it and QEMU does not use it */ +#define MACHINE(obj) \ +    OBJECT_CHECK(MachineState, (obj), TYPE_MACHINE) +#define MACHINE_GET_CLASS(obj) \ +    OBJECT_GET_CLASS(MachineClass, (obj), TYPE_MACHINE) +#define MACHINE_CLASS(klass) \ +    OBJECT_CLASS_CHECK(MachineClass, (klass), TYPE_MACHINE) + +MachineClass *find_default_machine(void); +extern MachineState *current_machine; + +bool machine_usb(MachineState *machine); +bool machine_iommu(MachineState *machine); +bool machine_kernel_irqchip_allowed(MachineState *machine); +bool machine_kernel_irqchip_required(MachineState *machine); +int machine_kvm_shadow_mem(MachineState *machine); +int machine_phandle_start(MachineState *machine); +bool machine_dump_guest_core(MachineState *machine); +bool machine_mem_merge(MachineState *machine); + +/** + * MachineClass: + * @qemu_machine: #QEMUMachine + * @get_hotplug_handler: this function is called during bus-less + *    device hotplug. If defined it returns pointer to an instance + *    of HotplugHandler object, which handles hotplug operation + *    for a given @dev. It may return NULL if @dev doesn't require + *    any actions to be performed by hotplug handler. + * @cpu_index_to_socket_id: + *    used to provide @cpu_index to socket number mapping, allowing + *    a machine to group CPU threads belonging to the same socket/package + *    Returns: socket number given cpu_index belongs to. + */ +struct MachineClass { +    /*< private >*/ +    ObjectClass parent_class; +    /*< public >*/ + +    const char *family; /* NULL iff @name identifies a standalone machtype */ +    const char *name; +    const char *alias; +    const char *desc; + +    void (*init)(MachineState *state); +    void (*reset)(void); +    void (*hot_add_cpu)(const int64_t id, Error **errp); +    int (*kvm_type)(const char *arg); + +    BlockInterfaceType block_default_type; +    int units_per_default_bus; +    int max_cpus; +    unsigned int no_serial:1, +        no_parallel:1, +        use_virtcon:1, +        use_sclp:1, +        no_floppy:1, +        no_cdrom:1, +        no_sdcard:1, +        has_dynamic_sysbus:1, +        no_tco:1; +    int is_default; +    const char *default_machine_opts; +    const char *default_boot_order; +    const char *default_display; +    GlobalProperty *compat_props; +    const char *hw_version; +    ram_addr_t default_ram_size; + +    HotplugHandler *(*get_hotplug_handler)(MachineState *machine, +                                           DeviceState *dev); +    unsigned (*cpu_index_to_socket_id)(unsigned cpu_index); +}; + +/** + * MachineState: + */ +struct MachineState { +    /*< private >*/ +    Object parent_obj; +    Notifier sysbus_notifier; + +    /*< public >*/ + +    char *accel; +    bool kernel_irqchip_allowed; +    bool kernel_irqchip_required; +    int kvm_shadow_mem; +    char *dtb; +    char *dumpdtb; +    int phandle_start; +    char *dt_compatible; +    bool dump_guest_core; +    bool mem_merge; +    bool usb; +    bool usb_disabled; +    char *firmware; +    bool iommu; +    bool suppress_vmdesc; + +    ram_addr_t ram_size; +    ram_addr_t maxram_size; +    uint64_t   ram_slots; +    const char *boot_order; +    char *kernel_filename; +    char *kernel_cmdline; +    char *initrd_filename; +    const char *cpu_model; +    AccelState *accelerator; +}; + +#endif diff --git a/include/hw/bt.h b/include/hw/bt.h new file mode 100644 index 00000000..cb2a7e65 --- /dev/null +++ b/include/hw/bt.h @@ -0,0 +1,2193 @@ +/* + * QEMU Bluetooth HCI helpers. + * + * Copyright (C) 2007 OpenMoko, Inc. + * Written by Andrzej Zaborowski <andrew@openedhand.com> + * + * Useful definitions taken from BlueZ project's headers. + * Copyright (C) 2000-2001  Qualcomm Incorporated + * Copyright (C) 2002-2003  Maxim Krasnyansky <maxk@qualcomm.com> + * Copyright (C) 2002-2006  Marcel Holtmann <marcel@holtmann.org> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef HW_BT_H +#define HW_BT_H 1 + +#include "hw/irq.h" + +/* BD Address */ +typedef struct { +    uint8_t b[6]; +} QEMU_PACKED bdaddr_t; + +#define BDADDR_ANY	(&(bdaddr_t) {{0, 0, 0, 0, 0, 0}}) +#define BDADDR_ALL	(&(bdaddr_t) {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}) +#define BDADDR_LOCAL	(&(bdaddr_t) {{0, 0, 0, 0xff, 0xff, 0xff}}) + +/* Copy, swap, convert BD Address */ +static inline int bacmp(const bdaddr_t *ba1, const bdaddr_t *ba2) +{ +    return memcmp(ba1, ba2, sizeof(bdaddr_t)); +} +static inline void bacpy(bdaddr_t *dst, const bdaddr_t *src) +{ +    memcpy(dst, src, sizeof(bdaddr_t)); +} + +#define BAINIT(orig)	{ .b = {		\ +    (orig)->b[0], (orig)->b[1], (orig)->b[2],	\ +    (orig)->b[3], (orig)->b[4], (orig)->b[5],	\ +}, } + +/* The twisted structures of a bluetooth environment */ +struct bt_device_s; +struct bt_scatternet_s; +struct bt_piconet_s; +struct bt_link_s; + +struct bt_scatternet_s { +    struct bt_device_s *slave; +}; + +struct bt_link_s { +    struct bt_device_s *slave, *host; +    uint16_t handle;		/* Master (host) side handle */ +    uint16_t acl_interval; +    enum { +        acl_active, +        acl_hold, +        acl_sniff, +        acl_parked, +    } acl_mode; +}; + +struct bt_device_s { +    int lt_addr; +    bdaddr_t bd_addr; +    int mtu; +    int setup; +    struct bt_scatternet_s *net; + +    uint8_t key[16]; +    int key_present; +    uint8_t class[3]; + +    uint8_t reject_reason; + +    uint64_t lmp_caps; +    const char *lmp_name; +    void (*lmp_connection_request)(struct bt_link_s *link); +    void (*lmp_connection_complete)(struct bt_link_s *link); +    void (*lmp_disconnect_master)(struct bt_link_s *link); +    void (*lmp_disconnect_slave)(struct bt_link_s *link); +    void (*lmp_acl_data)(struct bt_link_s *link, const uint8_t *data, +                    int start, int len); +    void (*lmp_acl_resp)(struct bt_link_s *link, const uint8_t *data, +                    int start, int len); +    void (*lmp_mode_change)(struct bt_link_s *link); + +    void (*handle_destroy)(struct bt_device_s *device); +    struct bt_device_s *next;	/* Next in the piconet/scatternet */ + +    int inquiry_scan; +    int page_scan; + +    uint16_t clkoff;	/* Note: Always little-endian */ +}; + +extern struct HCIInfo null_hci; +/* bt.c */ +void bt_device_init(struct bt_device_s *dev, struct bt_scatternet_s *net); +void bt_device_done(struct bt_device_s *dev); +struct bt_scatternet_s *qemu_find_bt_vlan(int id); + +/* bt-hci.c */ +struct HCIInfo *bt_new_hci(struct bt_scatternet_s *net); +struct HCIInfo *hci_init(const char *str); + +/* bt-vhci.c */ +void bt_vhci_init(struct HCIInfo *info); + +/* bt-hci-csr.c */ +enum { +    csrhci_pin_reset, +    csrhci_pin_wakeup, +    __csrhci_pins, +}; +qemu_irq *csrhci_pins_get(CharDriverState *chr); +CharDriverState *uart_hci_init(qemu_irq wakeup); + +/* bt-l2cap.c */ +struct bt_l2cap_device_s; +struct bt_l2cap_conn_params_s; +struct bt_l2cap_psm_s; +void bt_l2cap_device_init(struct bt_l2cap_device_s *dev, +                struct bt_scatternet_s *net); +void bt_l2cap_device_done(struct bt_l2cap_device_s *dev); +void bt_l2cap_psm_register(struct bt_l2cap_device_s *dev, int psm, +                int min_mtu, int (*new_channel)(struct bt_l2cap_device_s *dev, +                        struct bt_l2cap_conn_params_s *params)); + +struct bt_l2cap_device_s { +    struct bt_device_s device; +    struct bt_l2cap_psm_s *first_psm; +}; + +struct bt_l2cap_conn_params_s { +    /* Input */ +    uint8_t *(*sdu_out)(struct bt_l2cap_conn_params_s *chan, int len); +    void (*sdu_submit)(struct bt_l2cap_conn_params_s *chan); +    int remote_mtu; +    /* Output */ +    void *opaque; +    void (*sdu_in)(void *opaque, const uint8_t *data, int len); +    void (*close)(void *opaque); +}; + +enum bt_l2cap_psm_predef { +    BT_PSM_SDP		= 0x0001, +    BT_PSM_RFCOMM	= 0x0003, +    BT_PSM_TELEPHONY	= 0x0005, +    BT_PSM_TCS		= 0x0007, +    BT_PSM_BNEP		= 0x000f, +    BT_PSM_HID_CTRL	= 0x0011, +    BT_PSM_HID_INTR	= 0x0013, +    BT_PSM_UPNP		= 0x0015, +    BT_PSM_AVCTP	= 0x0017, +    BT_PSM_AVDTP	= 0x0019, +}; + +/* bt-sdp.c */ +void bt_l2cap_sdp_init(struct bt_l2cap_device_s *dev); + +/* bt-hid.c */ +struct bt_device_s *bt_mouse_init(struct bt_scatternet_s *net); +struct bt_device_s *bt_tablet_init(struct bt_scatternet_s *net); +struct bt_device_s *bt_keyboard_init(struct bt_scatternet_s *net); + +/* Link Management Protocol layer defines */ + +#define LLID_ACLU_CONT		0x1 +#define LLID_ACLU_START		0x2 +#define LLID_ACLC		0x3 + +enum lmp_pdu_type { +    LMP_NAME_REQ		= 0x0001, +    LMP_NAME_RES		= 0x0002, +    LMP_ACCEPTED		= 0x0003, +    LMP_NOT_ACCEPTED		= 0x0004, +    LMP_CLKOFFSET_REQ		= 0x0005, +    LMP_CLKOFFSET_RES		= 0x0006, +    LMP_DETACH			= 0x0007, +    LMP_IN_RAND			= 0x0008, +    LMP_COMB_KEY		= 0x0009, +    LMP_UNIT_KEY		= 0x000a, +    LMP_AU_RAND			= 0x000b, +    LMP_SRES			= 0x000c, +    LMP_TEMP_RAND		= 0x000d, +    LMP_TEMP_KEY		= 0x000e, +    LMP_CRYPT_MODE_REQ		= 0x000f, +    LMP_CRYPT_KEY_SIZE_REQ	= 0x0010, +    LMP_START_ENCRYPT_REQ	= 0x0011, +    LMP_STOP_ENCRYPT_REQ	= 0x0012, +    LMP_SWITCH_REQ		= 0x0013, +    LMP_HOLD			= 0x0014, +    LMP_HOLD_REQ		= 0x0015, +    LMP_SNIFF_REQ		= 0x0017, +    LMP_UNSNIFF_REQ		= 0x0018, +    LMP_LMP_PARK_REQ		= 0x0019, +    LMP_SET_BCAST_SCAN_WND	= 0x001b, +    LMP_MODIFY_BEACON		= 0x001c, +    LMP_UNPARK_BD_ADDR_REQ	= 0x001d, +    LMP_UNPARK_PM_ADDR_REQ	= 0x001e, +    LMP_INCR_POWER_REQ		= 0x001f, +    LMP_DECR_POWER_REQ		= 0x0020, +    LMP_MAX_POWER		= 0x0021, +    LMP_MIN_POWER		= 0x0022, +    LMP_AUTO_RATE		= 0x0023, +    LMP_PREFERRED_RATE		= 0x0024, +    LMP_VERSION_REQ		= 0x0025, +    LMP_VERSION_RES		= 0x0026, +    LMP_FEATURES_REQ		= 0x0027, +    LMP_FEATURES_RES		= 0x0028, +    LMP_QUALITY_OF_SERVICE	= 0x0029, +    LMP_QOS_REQ			= 0x002a, +    LMP_RM_SCO_LINK_REQ		= 0x002b, +    LMP_SCO_LINK_REQ		= 0x002c, +    LMP_MAX_SLOT		= 0x002d, +    LMP_MAX_SLOT_REQ		= 0x002e, +    LMP_TIMING_ACCURACY_REQ	= 0x002f, +    LMP_TIMING_ACCURACY_RES	= 0x0030, +    LMP_SETUP_COMPLETE		= 0x0031, +    LMP_USE_SEMIPERM_KEY	= 0x0032, +    LMP_HOST_CONNECTION_REQ	= 0x0033, +    LMP_SLOT_OFFSET		= 0x0034, +    LMP_PAGE_MODE_REQ		= 0x0035, +    LMP_PAGE_SCAN_MODE_REQ	= 0x0036, +    LMP_SUPERVISION_TIMEOUT	= 0x0037, +    LMP_TEST_ACTIVATE		= 0x0038, +    LMP_TEST_CONTROL		= 0x0039, +    LMP_CRYPT_KEY_MASK_REQ	= 0x003a, +    LMP_CRYPT_KEY_MASK_RES	= 0x003b, +    LMP_SET_AFH			= 0x003c, +    LMP_ACCEPTED_EXT		= 0x7f01, +    LMP_NOT_ACCEPTED_EXT	= 0x7f02, +    LMP_FEATURES_REQ_EXT	= 0x7f03, +    LMP_FEATURES_RES_EXT	= 0x7f04, +    LMP_PACKET_TYPE_TBL_REQ	= 0x7f0b, +    LMP_ESCO_LINK_REQ		= 0x7f0c, +    LMP_RM_ESCO_LINK_REQ	= 0x7f0d, +    LMP_CHANNEL_CLASS_REQ	= 0x7f10, +    LMP_CHANNEL_CLASS		= 0x7f11, +}; + +/* Host Controller Interface layer defines */ + +enum hci_packet_type { +    HCI_COMMAND_PKT		= 0x01, +    HCI_ACLDATA_PKT		= 0x02, +    HCI_SCODATA_PKT		= 0x03, +    HCI_EVENT_PKT		= 0x04, +    HCI_VENDOR_PKT		= 0xff, +}; + +enum bt_packet_type { +    HCI_2DH1	= 1 << 1, +    HCI_3DH1	= 1 << 2, +    HCI_DM1	= 1 << 3, +    HCI_DH1	= 1 << 4, +    HCI_2DH3	= 1 << 8, +    HCI_3DH3	= 1 << 9, +    HCI_DM3	= 1 << 10, +    HCI_DH3	= 1 << 11, +    HCI_2DH5	= 1 << 12, +    HCI_3DH5	= 1 << 13, +    HCI_DM5	= 1 << 14, +    HCI_DH5	= 1 << 15, +}; + +enum sco_packet_type { +    HCI_HV1	= 1 << 5, +    HCI_HV2	= 1 << 6, +    HCI_HV3	= 1 << 7, +}; + +enum ev_packet_type { +    HCI_EV3	= 1 << 3, +    HCI_EV4	= 1 << 4, +    HCI_EV5	= 1 << 5, +    HCI_2EV3	= 1 << 6, +    HCI_3EV3	= 1 << 7, +    HCI_2EV5	= 1 << 8, +    HCI_3EV5	= 1 << 9, +}; + +enum hci_error_code { +    HCI_SUCCESS				= 0x00, +    HCI_UNKNOWN_COMMAND			= 0x01, +    HCI_NO_CONNECTION			= 0x02, +    HCI_HARDWARE_FAILURE		= 0x03, +    HCI_PAGE_TIMEOUT			= 0x04, +    HCI_AUTHENTICATION_FAILURE		= 0x05, +    HCI_PIN_OR_KEY_MISSING		= 0x06, +    HCI_MEMORY_FULL			= 0x07, +    HCI_CONNECTION_TIMEOUT		= 0x08, +    HCI_MAX_NUMBER_OF_CONNECTIONS	= 0x09, +    HCI_MAX_NUMBER_OF_SCO_CONNECTIONS	= 0x0a, +    HCI_ACL_CONNECTION_EXISTS		= 0x0b, +    HCI_COMMAND_DISALLOWED		= 0x0c, +    HCI_REJECTED_LIMITED_RESOURCES	= 0x0d, +    HCI_REJECTED_SECURITY		= 0x0e, +    HCI_REJECTED_PERSONAL		= 0x0f, +    HCI_HOST_TIMEOUT			= 0x10, +    HCI_UNSUPPORTED_FEATURE		= 0x11, +    HCI_INVALID_PARAMETERS		= 0x12, +    HCI_OE_USER_ENDED_CONNECTION	= 0x13, +    HCI_OE_LOW_RESOURCES		= 0x14, +    HCI_OE_POWER_OFF			= 0x15, +    HCI_CONNECTION_TERMINATED		= 0x16, +    HCI_REPEATED_ATTEMPTS		= 0x17, +    HCI_PAIRING_NOT_ALLOWED		= 0x18, +    HCI_UNKNOWN_LMP_PDU			= 0x19, +    HCI_UNSUPPORTED_REMOTE_FEATURE	= 0x1a, +    HCI_SCO_OFFSET_REJECTED		= 0x1b, +    HCI_SCO_INTERVAL_REJECTED		= 0x1c, +    HCI_AIR_MODE_REJECTED		= 0x1d, +    HCI_INVALID_LMP_PARAMETERS		= 0x1e, +    HCI_UNSPECIFIED_ERROR		= 0x1f, +    HCI_UNSUPPORTED_LMP_PARAMETER_VALUE	= 0x20, +    HCI_ROLE_CHANGE_NOT_ALLOWED		= 0x21, +    HCI_LMP_RESPONSE_TIMEOUT		= 0x22, +    HCI_LMP_ERROR_TRANSACTION_COLLISION	= 0x23, +    HCI_LMP_PDU_NOT_ALLOWED		= 0x24, +    HCI_ENCRYPTION_MODE_NOT_ACCEPTED	= 0x25, +    HCI_UNIT_LINK_KEY_USED		= 0x26, +    HCI_QOS_NOT_SUPPORTED		= 0x27, +    HCI_INSTANT_PASSED			= 0x28, +    HCI_PAIRING_NOT_SUPPORTED		= 0x29, +    HCI_TRANSACTION_COLLISION		= 0x2a, +    HCI_QOS_UNACCEPTABLE_PARAMETER	= 0x2c, +    HCI_QOS_REJECTED			= 0x2d, +    HCI_CLASSIFICATION_NOT_SUPPORTED	= 0x2e, +    HCI_INSUFFICIENT_SECURITY		= 0x2f, +    HCI_PARAMETER_OUT_OF_RANGE		= 0x30, +    HCI_ROLE_SWITCH_PENDING		= 0x32, +    HCI_SLOT_VIOLATION			= 0x34, +    HCI_ROLE_SWITCH_FAILED		= 0x35, +}; + +enum acl_flag_bits { +    ACL_CONT		= 1 << 0, +    ACL_START		= 1 << 1, +    ACL_ACTIVE_BCAST	= 1 << 2, +    ACL_PICO_BCAST	= 1 << 3, +}; + +enum baseband_link_type { +    SCO_LINK		= 0x00, +    ACL_LINK		= 0x01, +}; + +enum lmp_feature_bits0 { +    LMP_3SLOT		= 1 << 0, +    LMP_5SLOT		= 1 << 1, +    LMP_ENCRYPT		= 1 << 2, +    LMP_SOFFSET		= 1 << 3, +    LMP_TACCURACY	= 1 << 4, +    LMP_RSWITCH		= 1 << 5, +    LMP_HOLD_MODE	= 1 << 6, +    LMP_SNIFF_MODE	= 1 << 7, +}; + +enum lmp_feature_bits1 { +    LMP_PARK		= 1 << 0, +    LMP_RSSI		= 1 << 1, +    LMP_QUALITY		= 1 << 2, +    LMP_SCO		= 1 << 3, +    LMP_HV2		= 1 << 4, +    LMP_HV3		= 1 << 5, +    LMP_ULAW		= 1 << 6, +    LMP_ALAW		= 1 << 7, +}; + +enum lmp_feature_bits2 { +    LMP_CVSD		= 1 << 0, +    LMP_PSCHEME		= 1 << 1, +    LMP_PCONTROL	= 1 << 2, +    LMP_TRSP_SCO	= 1 << 3, +    LMP_BCAST_ENC	= 1 << 7, +}; + +enum lmp_feature_bits3 { +    LMP_EDR_ACL_2M	= 1 << 1, +    LMP_EDR_ACL_3M	= 1 << 2, +    LMP_ENH_ISCAN	= 1 << 3, +    LMP_ILACE_ISCAN	= 1 << 4, +    LMP_ILACE_PSCAN	= 1 << 5, +    LMP_RSSI_INQ	= 1 << 6, +    LMP_ESCO		= 1 << 7, +}; + +enum lmp_feature_bits4 { +    LMP_EV4		= 1 << 0, +    LMP_EV5		= 1 << 1, +    LMP_AFH_CAP_SLV	= 1 << 3, +    LMP_AFH_CLS_SLV	= 1 << 4, +    LMP_EDR_3SLOT	= 1 << 7, +}; + +enum lmp_feature_bits5 { +    LMP_EDR_5SLOT	= 1 << 0, +    LMP_SNIFF_SUBR	= 1 << 1, +    LMP_AFH_CAP_MST	= 1 << 3, +    LMP_AFH_CLS_MST	= 1 << 4, +    LMP_EDR_ESCO_2M	= 1 << 5, +    LMP_EDR_ESCO_3M	= 1 << 6, +    LMP_EDR_3S_ESCO	= 1 << 7, +}; + +enum lmp_feature_bits6 { +    LMP_EXT_INQ		= 1 << 0, +}; + +enum lmp_feature_bits7 { +    LMP_EXT_FEAT	= 1 << 7, +}; + +enum hci_link_policy { +    HCI_LP_RSWITCH	= 1 << 0, +    HCI_LP_HOLD		= 1 << 1, +    HCI_LP_SNIFF	= 1 << 2, +    HCI_LP_PARK		= 1 << 3, +}; + +enum hci_link_mode { +    HCI_LM_ACCEPT	= 1 << 15, +    HCI_LM_MASTER	= 1 << 0, +    HCI_LM_AUTH		= 1 << 1, +    HCI_LM_ENCRYPT	= 1 << 2, +    HCI_LM_TRUSTED	= 1 << 3, +    HCI_LM_RELIABLE	= 1 << 4, +    HCI_LM_SECURE	= 1 << 5, +}; + +/* HCI Commands */ + +/* Link Control */ +#define OGF_LINK_CTL		0x01 + +#define OCF_INQUIRY			0x0001 +typedef struct { +    uint8_t	lap[3]; +    uint8_t	length;		/* 1.28s units */ +    uint8_t	num_rsp; +} QEMU_PACKED inquiry_cp; +#define INQUIRY_CP_SIZE 5 + +typedef struct { +    uint8_t		status; +    bdaddr_t	bdaddr; +} QEMU_PACKED status_bdaddr_rp; +#define STATUS_BDADDR_RP_SIZE 7 + +#define OCF_INQUIRY_CANCEL		0x0002 + +#define OCF_PERIODIC_INQUIRY		0x0003 +typedef struct { +    uint16_t	max_period;	/* 1.28s units */ +    uint16_t	min_period;	/* 1.28s units */ +    uint8_t	lap[3]; +    uint8_t	length;		/* 1.28s units */ +    uint8_t	num_rsp; +} QEMU_PACKED periodic_inquiry_cp; +#define PERIODIC_INQUIRY_CP_SIZE 9 + +#define OCF_EXIT_PERIODIC_INQUIRY	0x0004 + +#define OCF_CREATE_CONN			0x0005 +typedef struct { +    bdaddr_t	bdaddr; +    uint16_t	pkt_type; +    uint8_t	pscan_rep_mode; +    uint8_t	pscan_mode; +    uint16_t	clock_offset; +    uint8_t	role_switch; +} QEMU_PACKED create_conn_cp; +#define CREATE_CONN_CP_SIZE 13 + +#define OCF_DISCONNECT			0x0006 +typedef struct { +    uint16_t	handle; +    uint8_t	reason; +} QEMU_PACKED disconnect_cp; +#define DISCONNECT_CP_SIZE 3 + +#define OCF_ADD_SCO			0x0007 +typedef struct { +    uint16_t	handle; +    uint16_t	pkt_type; +} QEMU_PACKED add_sco_cp; +#define ADD_SCO_CP_SIZE 4 + +#define OCF_CREATE_CONN_CANCEL		0x0008 +typedef struct { +    uint8_t	status; +    bdaddr_t	bdaddr; +} QEMU_PACKED create_conn_cancel_cp; +#define CREATE_CONN_CANCEL_CP_SIZE 6 + +typedef struct { +    uint8_t	status; +    bdaddr_t	bdaddr; +} QEMU_PACKED create_conn_cancel_rp; +#define CREATE_CONN_CANCEL_RP_SIZE 7 + +#define OCF_ACCEPT_CONN_REQ		0x0009 +typedef struct { +    bdaddr_t	bdaddr; +    uint8_t	role; +} QEMU_PACKED accept_conn_req_cp; +#define ACCEPT_CONN_REQ_CP_SIZE	7 + +#define OCF_REJECT_CONN_REQ		0x000A +typedef struct { +    bdaddr_t	bdaddr; +    uint8_t	reason; +} QEMU_PACKED reject_conn_req_cp; +#define REJECT_CONN_REQ_CP_SIZE	7 + +#define OCF_LINK_KEY_REPLY		0x000B +typedef struct { +    bdaddr_t	bdaddr; +    uint8_t	link_key[16]; +} QEMU_PACKED link_key_reply_cp; +#define LINK_KEY_REPLY_CP_SIZE 22 + +#define OCF_LINK_KEY_NEG_REPLY		0x000C + +#define OCF_PIN_CODE_REPLY		0x000D +typedef struct { +    bdaddr_t	bdaddr; +    uint8_t	pin_len; +    uint8_t	pin_code[16]; +} QEMU_PACKED pin_code_reply_cp; +#define PIN_CODE_REPLY_CP_SIZE 23 + +#define OCF_PIN_CODE_NEG_REPLY		0x000E + +#define OCF_SET_CONN_PTYPE		0x000F +typedef struct { +    uint16_t	 handle; +    uint16_t	 pkt_type; +} QEMU_PACKED set_conn_ptype_cp; +#define SET_CONN_PTYPE_CP_SIZE 4 + +#define OCF_AUTH_REQUESTED		0x0011 +typedef struct { +    uint16_t	 handle; +} QEMU_PACKED auth_requested_cp; +#define AUTH_REQUESTED_CP_SIZE 2 + +#define OCF_SET_CONN_ENCRYPT		0x0013 +typedef struct { +    uint16_t	handle; +    uint8_t	encrypt; +} QEMU_PACKED set_conn_encrypt_cp; +#define SET_CONN_ENCRYPT_CP_SIZE 3 + +#define OCF_CHANGE_CONN_LINK_KEY	0x0015 +typedef struct { +    uint16_t	handle; +} QEMU_PACKED change_conn_link_key_cp; +#define CHANGE_CONN_LINK_KEY_CP_SIZE 2 + +#define OCF_MASTER_LINK_KEY		0x0017 +typedef struct { +    uint8_t	key_flag; +} QEMU_PACKED master_link_key_cp; +#define MASTER_LINK_KEY_CP_SIZE 1 + +#define OCF_REMOTE_NAME_REQ		0x0019 +typedef struct { +    bdaddr_t	bdaddr; +    uint8_t	pscan_rep_mode; +    uint8_t	pscan_mode; +    uint16_t	clock_offset; +} QEMU_PACKED remote_name_req_cp; +#define REMOTE_NAME_REQ_CP_SIZE 10 + +#define OCF_REMOTE_NAME_REQ_CANCEL	0x001A +typedef struct { +    bdaddr_t	bdaddr; +} QEMU_PACKED remote_name_req_cancel_cp; +#define REMOTE_NAME_REQ_CANCEL_CP_SIZE 6 + +typedef struct { +    uint8_t		status; +    bdaddr_t	bdaddr; +} QEMU_PACKED remote_name_req_cancel_rp; +#define REMOTE_NAME_REQ_CANCEL_RP_SIZE 7 + +#define OCF_READ_REMOTE_FEATURES	0x001B +typedef struct { +    uint16_t	handle; +} QEMU_PACKED read_remote_features_cp; +#define READ_REMOTE_FEATURES_CP_SIZE 2 + +#define OCF_READ_REMOTE_EXT_FEATURES	0x001C +typedef struct { +    uint16_t	handle; +    uint8_t	page_num; +} QEMU_PACKED read_remote_ext_features_cp; +#define READ_REMOTE_EXT_FEATURES_CP_SIZE 3 + +#define OCF_READ_REMOTE_VERSION		0x001D +typedef struct { +    uint16_t	handle; +} QEMU_PACKED read_remote_version_cp; +#define READ_REMOTE_VERSION_CP_SIZE 2 + +#define OCF_READ_CLOCK_OFFSET		0x001F +typedef struct { +    uint16_t	handle; +} QEMU_PACKED read_clock_offset_cp; +#define READ_CLOCK_OFFSET_CP_SIZE 2 + +#define OCF_READ_LMP_HANDLE		0x0020 +typedef struct { +    uint16_t	handle; +} QEMU_PACKED read_lmp_handle_cp; +#define READ_LMP_HANDLE_CP_SIZE 2 + +typedef struct { +    uint8_t	status; +    uint16_t	handle; +    uint8_t	lmp_handle; +    uint32_t	reserved; +} QEMU_PACKED read_lmp_handle_rp; +#define READ_LMP_HANDLE_RP_SIZE 8 + +#define OCF_SETUP_SYNC_CONN		0x0028 +typedef struct { +    uint16_t	handle; +    uint32_t	tx_bandwidth; +    uint32_t	rx_bandwidth; +    uint16_t	max_latency; +    uint16_t	voice_setting; +    uint8_t	retrans_effort; +    uint16_t	pkt_type; +} QEMU_PACKED setup_sync_conn_cp; +#define SETUP_SYNC_CONN_CP_SIZE 17 + +#define OCF_ACCEPT_SYNC_CONN_REQ	0x0029 +typedef struct { +    bdaddr_t	bdaddr; +    uint32_t	tx_bandwidth; +    uint32_t	rx_bandwidth; +    uint16_t	max_latency; +    uint16_t	voice_setting; +    uint8_t	retrans_effort; +    uint16_t	pkt_type; +} QEMU_PACKED accept_sync_conn_req_cp; +#define ACCEPT_SYNC_CONN_REQ_CP_SIZE 21 + +#define OCF_REJECT_SYNC_CONN_REQ	0x002A +typedef struct { +    bdaddr_t	bdaddr; +    uint8_t	reason; +} QEMU_PACKED reject_sync_conn_req_cp; +#define REJECT_SYNC_CONN_REQ_CP_SIZE 7 + +/* Link Policy */ +#define OGF_LINK_POLICY		0x02 + +#define OCF_HOLD_MODE			0x0001 +typedef struct { +    uint16_t	handle; +    uint16_t	max_interval; +    uint16_t	min_interval; +} QEMU_PACKED hold_mode_cp; +#define HOLD_MODE_CP_SIZE 6 + +#define OCF_SNIFF_MODE			0x0003 +typedef struct { +    uint16_t	handle; +    uint16_t	max_interval; +    uint16_t	min_interval; +    uint16_t	attempt; +    uint16_t	timeout; +} QEMU_PACKED sniff_mode_cp; +#define SNIFF_MODE_CP_SIZE 10 + +#define OCF_EXIT_SNIFF_MODE		0x0004 +typedef struct { +    uint16_t	handle; +} QEMU_PACKED exit_sniff_mode_cp; +#define EXIT_SNIFF_MODE_CP_SIZE 2 + +#define OCF_PARK_MODE			0x0005 +typedef struct { +    uint16_t	handle; +    uint16_t	max_interval; +    uint16_t	min_interval; +} QEMU_PACKED park_mode_cp; +#define PARK_MODE_CP_SIZE 6 + +#define OCF_EXIT_PARK_MODE		0x0006 +typedef struct { +    uint16_t	handle; +} QEMU_PACKED exit_park_mode_cp; +#define EXIT_PARK_MODE_CP_SIZE 2 + +#define OCF_QOS_SETUP			0x0007 +typedef struct { +    uint8_t	service_type;		/* 1 = best effort */ +    uint32_t	token_rate;		/* Byte per seconds */ +    uint32_t	peak_bandwidth;		/* Byte per seconds */ +    uint32_t	latency;		/* Microseconds */ +    uint32_t	delay_variation;	/* Microseconds */ +} QEMU_PACKED hci_qos; +#define HCI_QOS_CP_SIZE 17 +typedef struct { +    uint16_t 	handle; +    uint8_t 	flags;			/* Reserved */ +    hci_qos 	qos; +} QEMU_PACKED qos_setup_cp; +#define QOS_SETUP_CP_SIZE (3 + HCI_QOS_CP_SIZE) + +#define OCF_ROLE_DISCOVERY		0x0009 +typedef struct { +    uint16_t	handle; +} QEMU_PACKED role_discovery_cp; +#define ROLE_DISCOVERY_CP_SIZE 2 +typedef struct { +    uint8_t	status; +    uint16_t	handle; +    uint8_t	role; +} QEMU_PACKED role_discovery_rp; +#define ROLE_DISCOVERY_RP_SIZE 4 + +#define OCF_SWITCH_ROLE			0x000B +typedef struct { +    bdaddr_t	bdaddr; +    uint8_t	role; +} QEMU_PACKED switch_role_cp; +#define SWITCH_ROLE_CP_SIZE 7 + +#define OCF_READ_LINK_POLICY		0x000C +typedef struct { +    uint16_t	handle; +} QEMU_PACKED read_link_policy_cp; +#define READ_LINK_POLICY_CP_SIZE 2 +typedef struct { +    uint8_t 	status; +    uint16_t	handle; +    uint16_t	policy; +} QEMU_PACKED read_link_policy_rp; +#define READ_LINK_POLICY_RP_SIZE 5 + +#define OCF_WRITE_LINK_POLICY		0x000D +typedef struct { +    uint16_t	handle; +    uint16_t	policy; +} QEMU_PACKED write_link_policy_cp; +#define WRITE_LINK_POLICY_CP_SIZE 4 +typedef struct { +    uint8_t 	status; +    uint16_t	handle; +} QEMU_PACKED write_link_policy_rp; +#define WRITE_LINK_POLICY_RP_SIZE 3 + +#define OCF_READ_DEFAULT_LINK_POLICY	0x000E + +#define OCF_WRITE_DEFAULT_LINK_POLICY	0x000F + +#define OCF_FLOW_SPECIFICATION		0x0010 + +#define OCF_SNIFF_SUBRATE		0x0011 +typedef struct { +    uint16_t	handle; +    uint16_t	max_remote_latency; +    uint16_t	max_local_latency; +    uint16_t	min_remote_timeout; +    uint16_t	min_local_timeout; +} QEMU_PACKED sniff_subrate_cp; +#define SNIFF_SUBRATE_CP_SIZE 10 + +/* Host Controller and Baseband */ +#define OGF_HOST_CTL		0x03 + +#define OCF_SET_EVENT_MASK		0x0001 +typedef struct { +    uint8_t	mask[8]; +} QEMU_PACKED set_event_mask_cp; +#define SET_EVENT_MASK_CP_SIZE 8 + +#define OCF_RESET			0x0003 + +#define OCF_SET_EVENT_FLT		0x0005 +typedef struct { +    uint8_t	flt_type; +    uint8_t	cond_type; +    uint8_t	condition[0]; +} QEMU_PACKED set_event_flt_cp; +#define SET_EVENT_FLT_CP_SIZE 2 + +enum bt_filter_type { +    FLT_CLEAR_ALL		= 0x00, +    FLT_INQ_RESULT		= 0x01, +    FLT_CONN_SETUP		= 0x02, +}; +enum inq_result_cond_type { +    INQ_RESULT_RETURN_ALL	= 0x00, +    INQ_RESULT_RETURN_CLASS	= 0x01, +    INQ_RESULT_RETURN_BDADDR	= 0x02, +}; +enum conn_setup_cond_type { +    CONN_SETUP_ALLOW_ALL	= 0x00, +    CONN_SETUP_ALLOW_CLASS	= 0x01, +    CONN_SETUP_ALLOW_BDADDR	= 0x02, +}; +enum conn_setup_cond { +    CONN_SETUP_AUTO_OFF		= 0x01, +    CONN_SETUP_AUTO_ON		= 0x02, +}; + +#define OCF_FLUSH			0x0008 +typedef struct { +    uint16_t	handle; +} QEMU_PACKED flush_cp; +#define FLUSH_CP_SIZE 2 + +typedef struct { +    uint8_t	status; +    uint16_t	handle; +} QEMU_PACKED flush_rp; +#define FLUSH_RP_SIZE 3 + +#define OCF_READ_PIN_TYPE		0x0009 +typedef struct { +    uint8_t	status; +    uint8_t	pin_type; +} QEMU_PACKED read_pin_type_rp; +#define READ_PIN_TYPE_RP_SIZE 2 + +#define OCF_WRITE_PIN_TYPE		0x000A +typedef struct { +    uint8_t	pin_type; +} QEMU_PACKED write_pin_type_cp; +#define WRITE_PIN_TYPE_CP_SIZE 1 + +#define OCF_CREATE_NEW_UNIT_KEY		0x000B + +#define OCF_READ_STORED_LINK_KEY	0x000D +typedef struct { +    bdaddr_t	bdaddr; +    uint8_t	read_all; +} QEMU_PACKED read_stored_link_key_cp; +#define READ_STORED_LINK_KEY_CP_SIZE 7 +typedef struct { +    uint8_t	status; +    uint16_t	max_keys; +    uint16_t	num_keys; +} QEMU_PACKED read_stored_link_key_rp; +#define READ_STORED_LINK_KEY_RP_SIZE 5 + +#define OCF_WRITE_STORED_LINK_KEY	0x0011 +typedef struct { +    uint8_t	num_keys; +    /* variable length part */ +} QEMU_PACKED write_stored_link_key_cp; +#define WRITE_STORED_LINK_KEY_CP_SIZE 1 +typedef struct { +    uint8_t	status; +    uint8_t	num_keys; +} QEMU_PACKED write_stored_link_key_rp; +#define READ_WRITE_LINK_KEY_RP_SIZE 2 + +#define OCF_DELETE_STORED_LINK_KEY	0x0012 +typedef struct { +    bdaddr_t	bdaddr; +    uint8_t	delete_all; +} QEMU_PACKED delete_stored_link_key_cp; +#define DELETE_STORED_LINK_KEY_CP_SIZE 7 +typedef struct { +    uint8_t	status; +    uint16_t	num_keys; +} QEMU_PACKED delete_stored_link_key_rp; +#define DELETE_STORED_LINK_KEY_RP_SIZE 3 + +#define OCF_CHANGE_LOCAL_NAME		0x0013 +typedef struct { +    char	name[248]; +} QEMU_PACKED change_local_name_cp; +#define CHANGE_LOCAL_NAME_CP_SIZE 248  + +#define OCF_READ_LOCAL_NAME		0x0014 +typedef struct { +    uint8_t	status; +    char	name[248]; +} QEMU_PACKED read_local_name_rp; +#define READ_LOCAL_NAME_RP_SIZE 249  + +#define OCF_READ_CONN_ACCEPT_TIMEOUT	0x0015 +typedef struct { +    uint8_t	status; +    uint16_t	timeout; +} QEMU_PACKED read_conn_accept_timeout_rp; +#define READ_CONN_ACCEPT_TIMEOUT_RP_SIZE 3 + +#define OCF_WRITE_CONN_ACCEPT_TIMEOUT	0x0016 +typedef struct { +    uint16_t	timeout; +} QEMU_PACKED write_conn_accept_timeout_cp; +#define WRITE_CONN_ACCEPT_TIMEOUT_CP_SIZE 2 + +#define OCF_READ_PAGE_TIMEOUT		0x0017 +typedef struct { +    uint8_t	status; +    uint16_t	timeout; +} QEMU_PACKED read_page_timeout_rp; +#define READ_PAGE_TIMEOUT_RP_SIZE 3 + +#define OCF_WRITE_PAGE_TIMEOUT		0x0018 +typedef struct { +    uint16_t	timeout; +} QEMU_PACKED write_page_timeout_cp; +#define WRITE_PAGE_TIMEOUT_CP_SIZE 2 + +#define OCF_READ_SCAN_ENABLE		0x0019 +typedef struct { +    uint8_t	status; +    uint8_t	enable; +} QEMU_PACKED read_scan_enable_rp; +#define READ_SCAN_ENABLE_RP_SIZE 2 + +#define OCF_WRITE_SCAN_ENABLE		0x001A +typedef struct { +    uint8_t	scan_enable; +} QEMU_PACKED write_scan_enable_cp; +#define WRITE_SCAN_ENABLE_CP_SIZE 1 + +enum scan_enable_bits { +    SCAN_DISABLED		= 0, +    SCAN_INQUIRY		= 1 << 0, +    SCAN_PAGE			= 1 << 1, +}; + +#define OCF_READ_PAGE_ACTIVITY		0x001B +typedef struct { +    uint8_t	status; +    uint16_t	interval; +    uint16_t	window; +} QEMU_PACKED read_page_activity_rp; +#define READ_PAGE_ACTIVITY_RP_SIZE 5 + +#define OCF_WRITE_PAGE_ACTIVITY		0x001C +typedef struct { +    uint16_t	interval; +    uint16_t	window; +} QEMU_PACKED write_page_activity_cp; +#define WRITE_PAGE_ACTIVITY_CP_SIZE 4 + +#define OCF_READ_INQ_ACTIVITY		0x001D +typedef struct { +    uint8_t	status; +    uint16_t	interval; +    uint16_t	window; +} QEMU_PACKED read_inq_activity_rp; +#define READ_INQ_ACTIVITY_RP_SIZE 5 + +#define OCF_WRITE_INQ_ACTIVITY		0x001E +typedef struct { +    uint16_t	interval; +    uint16_t	window; +} QEMU_PACKED write_inq_activity_cp; +#define WRITE_INQ_ACTIVITY_CP_SIZE 4 + +#define OCF_READ_AUTH_ENABLE		0x001F + +#define OCF_WRITE_AUTH_ENABLE		0x0020 + +#define AUTH_DISABLED		0x00 +#define AUTH_ENABLED		0x01 + +#define OCF_READ_ENCRYPT_MODE		0x0021 + +#define OCF_WRITE_ENCRYPT_MODE		0x0022 + +#define ENCRYPT_DISABLED	0x00 +#define ENCRYPT_P2P		0x01 +#define ENCRYPT_BOTH		0x02 + +#define OCF_READ_CLASS_OF_DEV		0x0023 +typedef struct { +    uint8_t	status; +    uint8_t	dev_class[3]; +} QEMU_PACKED read_class_of_dev_rp; +#define READ_CLASS_OF_DEV_RP_SIZE 4  + +#define OCF_WRITE_CLASS_OF_DEV		0x0024 +typedef struct { +    uint8_t	dev_class[3]; +} QEMU_PACKED write_class_of_dev_cp; +#define WRITE_CLASS_OF_DEV_CP_SIZE 3 + +#define OCF_READ_VOICE_SETTING		0x0025 +typedef struct { +    uint8_t	status; +    uint16_t	voice_setting; +} QEMU_PACKED read_voice_setting_rp; +#define READ_VOICE_SETTING_RP_SIZE 3 + +#define OCF_WRITE_VOICE_SETTING		0x0026 +typedef struct { +    uint16_t	voice_setting; +} QEMU_PACKED write_voice_setting_cp; +#define WRITE_VOICE_SETTING_CP_SIZE 2 + +#define OCF_READ_AUTOMATIC_FLUSH_TIMEOUT	0x0027 + +#define OCF_WRITE_AUTOMATIC_FLUSH_TIMEOUT	0x0028 + +#define OCF_READ_NUM_BROADCAST_RETRANS	0x0029 + +#define OCF_WRITE_NUM_BROADCAST_RETRANS	0x002A + +#define OCF_READ_HOLD_MODE_ACTIVITY	0x002B + +#define OCF_WRITE_HOLD_MODE_ACTIVITY	0x002C + +#define OCF_READ_TRANSMIT_POWER_LEVEL	0x002D +typedef struct { +    uint16_t	handle; +    uint8_t	type; +} QEMU_PACKED read_transmit_power_level_cp; +#define READ_TRANSMIT_POWER_LEVEL_CP_SIZE 3 +typedef struct { +    uint8_t	status; +    uint16_t	handle; +    int8_t	level; +} QEMU_PACKED read_transmit_power_level_rp; +#define READ_TRANSMIT_POWER_LEVEL_RP_SIZE 4 + +#define OCF_HOST_BUFFER_SIZE		0x0033 +typedef struct { +    uint16_t	acl_mtu; +    uint8_t	sco_mtu; +    uint16_t	acl_max_pkt; +    uint16_t	sco_max_pkt; +} QEMU_PACKED host_buffer_size_cp; +#define HOST_BUFFER_SIZE_CP_SIZE 7 + +#define OCF_HOST_NUMBER_OF_COMPLETED_PACKETS	0x0035 + +#define OCF_READ_LINK_SUPERVISION_TIMEOUT	0x0036 +typedef struct { +    uint8_t	status; +    uint16_t	handle; +    uint16_t	link_sup_to; +} QEMU_PACKED read_link_supervision_timeout_rp; +#define READ_LINK_SUPERVISION_TIMEOUT_RP_SIZE 5 + +#define OCF_WRITE_LINK_SUPERVISION_TIMEOUT	0x0037 +typedef struct { +    uint16_t	handle; +    uint16_t	link_sup_to; +} QEMU_PACKED write_link_supervision_timeout_cp; +#define WRITE_LINK_SUPERVISION_TIMEOUT_CP_SIZE 4 +typedef struct { +    uint8_t	status; +    uint16_t	handle; +} QEMU_PACKED write_link_supervision_timeout_rp; +#define WRITE_LINK_SUPERVISION_TIMEOUT_RP_SIZE 3 + +#define OCF_READ_NUM_SUPPORTED_IAC	0x0038 + +#define MAX_IAC_LAP 0x40 +#define OCF_READ_CURRENT_IAC_LAP	0x0039 +typedef struct { +    uint8_t	status; +    uint8_t	num_current_iac; +    uint8_t	lap[MAX_IAC_LAP][3]; +} QEMU_PACKED read_current_iac_lap_rp; +#define READ_CURRENT_IAC_LAP_RP_SIZE 2+3*MAX_IAC_LAP + +#define OCF_WRITE_CURRENT_IAC_LAP	0x003A +typedef struct { +    uint8_t	num_current_iac; +    uint8_t	lap[MAX_IAC_LAP][3]; +} QEMU_PACKED write_current_iac_lap_cp; +#define WRITE_CURRENT_IAC_LAP_CP_SIZE 1+3*MAX_IAC_LAP + +#define OCF_READ_PAGE_SCAN_PERIOD_MODE	0x003B + +#define OCF_WRITE_PAGE_SCAN_PERIOD_MODE	0x003C + +#define OCF_READ_PAGE_SCAN_MODE		0x003D + +#define OCF_WRITE_PAGE_SCAN_MODE	0x003E + +#define OCF_SET_AFH_CLASSIFICATION	0x003F +typedef struct { +    uint8_t	map[10]; +} QEMU_PACKED set_afh_classification_cp; +#define SET_AFH_CLASSIFICATION_CP_SIZE 10 +typedef struct { +    uint8_t	status; +} QEMU_PACKED set_afh_classification_rp; +#define SET_AFH_CLASSIFICATION_RP_SIZE 1 + +#define OCF_READ_INQUIRY_SCAN_TYPE	0x0042 +typedef struct { +    uint8_t	status; +    uint8_t	type; +} QEMU_PACKED read_inquiry_scan_type_rp; +#define READ_INQUIRY_SCAN_TYPE_RP_SIZE 2 + +#define OCF_WRITE_INQUIRY_SCAN_TYPE	0x0043 +typedef struct { +    uint8_t	type; +} QEMU_PACKED write_inquiry_scan_type_cp; +#define WRITE_INQUIRY_SCAN_TYPE_CP_SIZE 1 +typedef struct { +    uint8_t	status; +} QEMU_PACKED write_inquiry_scan_type_rp; +#define WRITE_INQUIRY_SCAN_TYPE_RP_SIZE 1 + +#define OCF_READ_INQUIRY_MODE		0x0044 +typedef struct { +    uint8_t	status; +    uint8_t	mode; +} QEMU_PACKED read_inquiry_mode_rp; +#define READ_INQUIRY_MODE_RP_SIZE 2 + +#define OCF_WRITE_INQUIRY_MODE		0x0045 +typedef struct { +    uint8_t	mode; +} QEMU_PACKED write_inquiry_mode_cp; +#define WRITE_INQUIRY_MODE_CP_SIZE 1 +typedef struct { +    uint8_t	status; +} QEMU_PACKED write_inquiry_mode_rp; +#define WRITE_INQUIRY_MODE_RP_SIZE 1 + +#define OCF_READ_PAGE_SCAN_TYPE		0x0046 + +#define OCF_WRITE_PAGE_SCAN_TYPE	0x0047 + +#define OCF_READ_AFH_MODE		0x0048 +typedef struct { +    uint8_t	status; +    uint8_t	mode; +} QEMU_PACKED read_afh_mode_rp; +#define READ_AFH_MODE_RP_SIZE 2 + +#define OCF_WRITE_AFH_MODE		0x0049 +typedef struct { +    uint8_t	mode; +} QEMU_PACKED write_afh_mode_cp; +#define WRITE_AFH_MODE_CP_SIZE 1 +typedef struct { +    uint8_t	status; +} QEMU_PACKED write_afh_mode_rp; +#define WRITE_AFH_MODE_RP_SIZE 1 + +#define OCF_READ_EXT_INQUIRY_RESPONSE	0x0051 +typedef struct { +    uint8_t	status; +    uint8_t	fec; +    uint8_t	data[240]; +} QEMU_PACKED read_ext_inquiry_response_rp; +#define READ_EXT_INQUIRY_RESPONSE_RP_SIZE 242 + +#define OCF_WRITE_EXT_INQUIRY_RESPONSE	0x0052 +typedef struct { +    uint8_t	fec; +    uint8_t	data[240]; +} QEMU_PACKED write_ext_inquiry_response_cp; +#define WRITE_EXT_INQUIRY_RESPONSE_CP_SIZE 241 +typedef struct { +    uint8_t	status; +} QEMU_PACKED write_ext_inquiry_response_rp; +#define WRITE_EXT_INQUIRY_RESPONSE_RP_SIZE 1 + +/* Informational Parameters */ +#define OGF_INFO_PARAM		0x04 + +#define OCF_READ_LOCAL_VERSION		0x0001 +typedef struct { +    uint8_t	status; +    uint8_t	hci_ver; +    uint16_t	hci_rev; +    uint8_t	lmp_ver; +    uint16_t	manufacturer; +    uint16_t	lmp_subver; +} QEMU_PACKED read_local_version_rp; +#define READ_LOCAL_VERSION_RP_SIZE 9 + +#define OCF_READ_LOCAL_COMMANDS		0x0002 +typedef struct { +    uint8_t	status; +    uint8_t	commands[64]; +} QEMU_PACKED read_local_commands_rp; +#define READ_LOCAL_COMMANDS_RP_SIZE 65 + +#define OCF_READ_LOCAL_FEATURES		0x0003 +typedef struct { +    uint8_t	status; +    uint8_t	features[8]; +} QEMU_PACKED read_local_features_rp; +#define READ_LOCAL_FEATURES_RP_SIZE 9 + +#define OCF_READ_LOCAL_EXT_FEATURES	0x0004 +typedef struct { +    uint8_t	page_num; +} QEMU_PACKED read_local_ext_features_cp; +#define READ_LOCAL_EXT_FEATURES_CP_SIZE 1 +typedef struct { +    uint8_t	status; +    uint8_t	page_num; +    uint8_t	max_page_num; +    uint8_t	features[8]; +} QEMU_PACKED read_local_ext_features_rp; +#define READ_LOCAL_EXT_FEATURES_RP_SIZE 11 + +#define OCF_READ_BUFFER_SIZE		0x0005 +typedef struct { +    uint8_t	status; +    uint16_t	acl_mtu; +    uint8_t	sco_mtu; +    uint16_t	acl_max_pkt; +    uint16_t	sco_max_pkt; +} QEMU_PACKED read_buffer_size_rp; +#define READ_BUFFER_SIZE_RP_SIZE 8 + +#define OCF_READ_COUNTRY_CODE		0x0007 +typedef struct { +    uint8_t	status; +    uint8_t	country_code; +} QEMU_PACKED read_country_code_rp; +#define READ_COUNTRY_CODE_RP_SIZE 2 + +#define OCF_READ_BD_ADDR		0x0009 +typedef struct { +    uint8_t	status; +    bdaddr_t	bdaddr; +} QEMU_PACKED read_bd_addr_rp; +#define READ_BD_ADDR_RP_SIZE 7 + +/* Status params */ +#define OGF_STATUS_PARAM	0x05 + +#define OCF_READ_FAILED_CONTACT_COUNTER		0x0001 +typedef struct { +    uint8_t	status; +    uint16_t	handle; +    uint8_t	counter; +} QEMU_PACKED read_failed_contact_counter_rp; +#define READ_FAILED_CONTACT_COUNTER_RP_SIZE 4 + +#define OCF_RESET_FAILED_CONTACT_COUNTER	0x0002 +typedef struct { +    uint8_t	status; +    uint16_t	handle; +} QEMU_PACKED reset_failed_contact_counter_rp; +#define RESET_FAILED_CONTACT_COUNTER_RP_SIZE 4 + +#define OCF_READ_LINK_QUALITY		0x0003 +typedef struct { +    uint16_t	handle; +} QEMU_PACKED read_link_quality_cp; +#define READ_LINK_QUALITY_CP_SIZE 4 + +typedef struct { +    uint8_t	status; +    uint16_t	handle; +    uint8_t	link_quality; +} QEMU_PACKED read_link_quality_rp; +#define READ_LINK_QUALITY_RP_SIZE 4 + +#define OCF_READ_RSSI			0x0005 +typedef struct { +    uint8_t	status; +    uint16_t	handle; +    int8_t	rssi; +} QEMU_PACKED read_rssi_rp; +#define READ_RSSI_RP_SIZE 4 + +#define OCF_READ_AFH_MAP		0x0006 +typedef struct { +    uint8_t	status; +    uint16_t	handle; +    uint8_t	mode; +    uint8_t	map[10]; +} QEMU_PACKED read_afh_map_rp; +#define READ_AFH_MAP_RP_SIZE 14 + +#define OCF_READ_CLOCK			0x0007 +typedef struct { +    uint16_t	handle; +    uint8_t	which_clock; +} QEMU_PACKED read_clock_cp; +#define READ_CLOCK_CP_SIZE 3 +typedef struct { +    uint8_t	status; +    uint16_t	handle; +    uint32_t	clock; +    uint16_t	accuracy; +} QEMU_PACKED read_clock_rp; +#define READ_CLOCK_RP_SIZE 9 + +/* Testing commands */ +#define OGF_TESTING_CMD		0x3e + +/* Vendor specific commands */ +#define OGF_VENDOR_CMD		0x3f + +/* HCI Events */ + +#define EVT_INQUIRY_COMPLETE		0x01 + +#define EVT_INQUIRY_RESULT		0x02 +typedef struct { +    uint8_t	num_responses; +    bdaddr_t	bdaddr; +    uint8_t	pscan_rep_mode; +    uint8_t	pscan_period_mode; +    uint8_t	pscan_mode; +    uint8_t	dev_class[3]; +    uint16_t	clock_offset; +} QEMU_PACKED inquiry_info; +#define INQUIRY_INFO_SIZE 14 + +#define EVT_CONN_COMPLETE		0x03 +typedef struct { +    uint8_t	status; +    uint16_t	handle; +    bdaddr_t	bdaddr; +    uint8_t	link_type; +    uint8_t	encr_mode; +} QEMU_PACKED evt_conn_complete; +#define EVT_CONN_COMPLETE_SIZE 11 + +#define EVT_CONN_REQUEST		0x04 +typedef struct { +    bdaddr_t	bdaddr; +    uint8_t	dev_class[3]; +    uint8_t	link_type; +} QEMU_PACKED evt_conn_request; +#define EVT_CONN_REQUEST_SIZE 10 + +#define EVT_DISCONN_COMPLETE		0x05 +typedef struct { +    uint8_t	status; +    uint16_t	handle; +    uint8_t	reason; +} QEMU_PACKED evt_disconn_complete; +#define EVT_DISCONN_COMPLETE_SIZE 4 + +#define EVT_AUTH_COMPLETE		0x06 +typedef struct { +    uint8_t	status; +    uint16_t	handle; +} QEMU_PACKED evt_auth_complete; +#define EVT_AUTH_COMPLETE_SIZE 3 + +#define EVT_REMOTE_NAME_REQ_COMPLETE	0x07 +typedef struct { +    uint8_t	status; +    bdaddr_t	bdaddr; +    char	name[248]; +} QEMU_PACKED evt_remote_name_req_complete; +#define EVT_REMOTE_NAME_REQ_COMPLETE_SIZE 255 + +#define EVT_ENCRYPT_CHANGE		0x08 +typedef struct { +    uint8_t	status; +    uint16_t	handle; +    uint8_t	encrypt; +} QEMU_PACKED evt_encrypt_change; +#define EVT_ENCRYPT_CHANGE_SIZE 5 + +#define EVT_CHANGE_CONN_LINK_KEY_COMPLETE	0x09 +typedef struct { +    uint8_t	status; +    uint16_t	handle; +}  QEMU_PACKED evt_change_conn_link_key_complete; +#define EVT_CHANGE_CONN_LINK_KEY_COMPLETE_SIZE 3 + +#define EVT_MASTER_LINK_KEY_COMPLETE		0x0A +typedef struct { +    uint8_t	status; +    uint16_t	handle; +    uint8_t	key_flag; +} QEMU_PACKED evt_master_link_key_complete; +#define EVT_MASTER_LINK_KEY_COMPLETE_SIZE 4 + +#define EVT_READ_REMOTE_FEATURES_COMPLETE	0x0B +typedef struct { +    uint8_t	status; +    uint16_t	handle; +    uint8_t	features[8]; +} QEMU_PACKED evt_read_remote_features_complete; +#define EVT_READ_REMOTE_FEATURES_COMPLETE_SIZE 11 + +#define EVT_READ_REMOTE_VERSION_COMPLETE	0x0C +typedef struct { +    uint8_t	status; +    uint16_t	handle; +    uint8_t	lmp_ver; +    uint16_t	manufacturer; +    uint16_t	lmp_subver; +} QEMU_PACKED evt_read_remote_version_complete; +#define EVT_READ_REMOTE_VERSION_COMPLETE_SIZE 8 + +#define EVT_QOS_SETUP_COMPLETE		0x0D +typedef struct { +    uint8_t	status; +    uint16_t	handle; +    uint8_t	flags;			/* Reserved */ +    hci_qos	qos; +} QEMU_PACKED evt_qos_setup_complete; +#define EVT_QOS_SETUP_COMPLETE_SIZE (4 + HCI_QOS_CP_SIZE) + +#define EVT_CMD_COMPLETE 		0x0E +typedef struct { +    uint8_t	ncmd; +    uint16_t	opcode; +} QEMU_PACKED evt_cmd_complete; +#define EVT_CMD_COMPLETE_SIZE 3 + +#define EVT_CMD_STATUS 			0x0F +typedef struct { +    uint8_t	status; +    uint8_t	ncmd; +    uint16_t	opcode; +} QEMU_PACKED evt_cmd_status; +#define EVT_CMD_STATUS_SIZE 4 + +#define EVT_HARDWARE_ERROR		0x10 +typedef struct { +    uint8_t	code; +} QEMU_PACKED evt_hardware_error; +#define EVT_HARDWARE_ERROR_SIZE 1 + +#define EVT_FLUSH_OCCURRED		0x11 +typedef struct { +    uint16_t	handle; +} QEMU_PACKED evt_flush_occurred; +#define EVT_FLUSH_OCCURRED_SIZE 2 + +#define EVT_ROLE_CHANGE			0x12 +typedef struct { +    uint8_t	status; +    bdaddr_t	bdaddr; +    uint8_t	role; +} QEMU_PACKED evt_role_change; +#define EVT_ROLE_CHANGE_SIZE 8 + +#define EVT_NUM_COMP_PKTS		0x13 +typedef struct { +    uint8_t	num_hndl; +    struct { +        uint16_t handle; +        uint16_t num_packets; +    } connection[0]; +} QEMU_PACKED evt_num_comp_pkts; +#define EVT_NUM_COMP_PKTS_SIZE(num_hndl) (1 + 4 * (num_hndl)) + +#define EVT_MODE_CHANGE			0x14 +typedef struct { +    uint8_t	status; +    uint16_t	handle; +    uint8_t	mode; +    uint16_t	interval; +} QEMU_PACKED evt_mode_change; +#define EVT_MODE_CHANGE_SIZE 6 + +#define EVT_RETURN_LINK_KEYS		0x15 +typedef struct { +    uint8_t	num_keys; +    /* variable length part */ +} QEMU_PACKED evt_return_link_keys; +#define EVT_RETURN_LINK_KEYS_SIZE 1 + +#define EVT_PIN_CODE_REQ		0x16 +typedef struct { +    bdaddr_t	bdaddr; +} QEMU_PACKED evt_pin_code_req; +#define EVT_PIN_CODE_REQ_SIZE 6 + +#define EVT_LINK_KEY_REQ		0x17 +typedef struct { +    bdaddr_t	bdaddr; +} QEMU_PACKED evt_link_key_req; +#define EVT_LINK_KEY_REQ_SIZE 6 + +#define EVT_LINK_KEY_NOTIFY		0x18 +typedef struct { +    bdaddr_t	bdaddr; +    uint8_t	link_key[16]; +    uint8_t	key_type; +} QEMU_PACKED evt_link_key_notify; +#define EVT_LINK_KEY_NOTIFY_SIZE 23 + +#define EVT_LOOPBACK_COMMAND		0x19 + +#define EVT_DATA_BUFFER_OVERFLOW	0x1A +typedef struct { +    uint8_t	link_type; +} QEMU_PACKED evt_data_buffer_overflow; +#define EVT_DATA_BUFFER_OVERFLOW_SIZE 1 + +#define EVT_MAX_SLOTS_CHANGE		0x1B +typedef struct { +    uint16_t	handle; +    uint8_t	max_slots; +} QEMU_PACKED evt_max_slots_change; +#define EVT_MAX_SLOTS_CHANGE_SIZE 3 + +#define EVT_READ_CLOCK_OFFSET_COMPLETE	0x1C +typedef struct { +    uint8_t	status; +    uint16_t	handle; +    uint16_t	clock_offset; +} QEMU_PACKED evt_read_clock_offset_complete; +#define EVT_READ_CLOCK_OFFSET_COMPLETE_SIZE 5 + +#define EVT_CONN_PTYPE_CHANGED		0x1D +typedef struct { +    uint8_t	status; +    uint16_t	handle; +    uint16_t	ptype; +} QEMU_PACKED evt_conn_ptype_changed; +#define EVT_CONN_PTYPE_CHANGED_SIZE 5 + +#define EVT_QOS_VIOLATION		0x1E +typedef struct { +    uint16_t	handle; +} QEMU_PACKED evt_qos_violation; +#define EVT_QOS_VIOLATION_SIZE 2 + +#define EVT_PSCAN_REP_MODE_CHANGE	0x20 +typedef struct { +    bdaddr_t	bdaddr; +    uint8_t	pscan_rep_mode; +} QEMU_PACKED evt_pscan_rep_mode_change; +#define EVT_PSCAN_REP_MODE_CHANGE_SIZE 7 + +#define EVT_FLOW_SPEC_COMPLETE		0x21 +typedef struct { +    uint8_t	status; +    uint16_t	handle; +    uint8_t	flags; +    uint8_t	direction; +    hci_qos	qos; +} QEMU_PACKED evt_flow_spec_complete; +#define EVT_FLOW_SPEC_COMPLETE_SIZE (5 + HCI_QOS_CP_SIZE) + +#define EVT_INQUIRY_RESULT_WITH_RSSI	0x22 +typedef struct { +    uint8_t	num_responses; +    bdaddr_t	bdaddr; +    uint8_t	pscan_rep_mode; +    uint8_t	pscan_period_mode; +    uint8_t	dev_class[3]; +    uint16_t	clock_offset; +    int8_t	rssi; +} QEMU_PACKED inquiry_info_with_rssi; +#define INQUIRY_INFO_WITH_RSSI_SIZE 15 +typedef struct { +    uint8_t	num_responses; +    bdaddr_t	bdaddr; +    uint8_t	pscan_rep_mode; +    uint8_t	pscan_period_mode; +    uint8_t	pscan_mode; +    uint8_t	dev_class[3]; +    uint16_t	clock_offset; +    int8_t	rssi; +} QEMU_PACKED inquiry_info_with_rssi_and_pscan_mode; +#define INQUIRY_INFO_WITH_RSSI_AND_PSCAN_MODE_SIZE 16 + +#define EVT_READ_REMOTE_EXT_FEATURES_COMPLETE	0x23 +typedef struct { +    uint8_t	status; +    uint16_t	handle; +    uint8_t	page_num; +    uint8_t	max_page_num; +    uint8_t	features[8]; +} QEMU_PACKED evt_read_remote_ext_features_complete; +#define EVT_READ_REMOTE_EXT_FEATURES_COMPLETE_SIZE 13 + +#define EVT_SYNC_CONN_COMPLETE		0x2C +typedef struct { +    uint8_t	status; +    uint16_t	handle; +    bdaddr_t	bdaddr; +    uint8_t	link_type; +    uint8_t	trans_interval; +    uint8_t	retrans_window; +    uint16_t	rx_pkt_len; +    uint16_t	tx_pkt_len; +    uint8_t	air_mode; +} QEMU_PACKED evt_sync_conn_complete; +#define EVT_SYNC_CONN_COMPLETE_SIZE 17 + +#define EVT_SYNC_CONN_CHANGED		0x2D +typedef struct { +    uint8_t	status; +    uint16_t	handle; +    uint8_t	trans_interval; +    uint8_t	retrans_window; +    uint16_t	rx_pkt_len; +    uint16_t	tx_pkt_len; +} QEMU_PACKED evt_sync_conn_changed; +#define EVT_SYNC_CONN_CHANGED_SIZE 9 + +#define EVT_SNIFF_SUBRATE		0x2E +typedef struct { +    uint8_t	status; +    uint16_t	handle; +    uint16_t	max_remote_latency; +    uint16_t	max_local_latency; +    uint16_t	min_remote_timeout; +    uint16_t	min_local_timeout; +} QEMU_PACKED evt_sniff_subrate; +#define EVT_SNIFF_SUBRATE_SIZE 11 + +#define EVT_EXTENDED_INQUIRY_RESULT	0x2F +typedef struct { +    bdaddr_t	bdaddr; +    uint8_t	pscan_rep_mode; +    uint8_t	pscan_period_mode; +    uint8_t	dev_class[3]; +    uint16_t	clock_offset; +    int8_t	rssi; +    uint8_t	data[240]; +} QEMU_PACKED extended_inquiry_info; +#define EXTENDED_INQUIRY_INFO_SIZE 254 + +#define EVT_TESTING			0xFE + +#define EVT_VENDOR			0xFF + +/* Command opcode pack/unpack */ +#define cmd_opcode_pack(ogf, ocf)	(uint16_t)((ocf & 0x03ff)|(ogf << 10)) +#define cmd_opcode_ogf(op)		(op >> 10) +#define cmd_opcode_ocf(op)		(op & 0x03ff) + +/* ACL handle and flags pack/unpack */ +#define acl_handle_pack(h, f)	(uint16_t)(((h) & 0x0fff)|((f) << 12)) +#define acl_handle(h)		((h) & 0x0fff) +#define acl_flags(h)		((h) >> 12) + +/* HCI Packet structures */ +#define HCI_COMMAND_HDR_SIZE	3 +#define HCI_EVENT_HDR_SIZE	2 +#define HCI_ACL_HDR_SIZE	4 +#define HCI_SCO_HDR_SIZE	3 + +struct hci_command_hdr { +    uint16_t 	opcode;		/* OCF & OGF */ +    uint8_t	plen; +} QEMU_PACKED; + +struct hci_event_hdr { +    uint8_t	evt; +    uint8_t	plen; +} QEMU_PACKED; + +struct hci_acl_hdr { +    uint16_t	handle;		/* Handle & Flags(PB, BC) */ +    uint16_t	dlen; +} QEMU_PACKED; + +struct hci_sco_hdr { +    uint16_t	handle; +    uint8_t	dlen; +} QEMU_PACKED; + +/* L2CAP layer defines */ + +enum bt_l2cap_lm_bits { +    L2CAP_LM_MASTER	= 1 << 0, +    L2CAP_LM_AUTH	= 1 << 1, +    L2CAP_LM_ENCRYPT	= 1 << 2, +    L2CAP_LM_TRUSTED	= 1 << 3, +    L2CAP_LM_RELIABLE	= 1 << 4, +    L2CAP_LM_SECURE	= 1 << 5, +}; + +enum bt_l2cap_cid_predef { +    L2CAP_CID_INVALID	= 0x0000, +    L2CAP_CID_SIGNALLING= 0x0001, +    L2CAP_CID_GROUP	= 0x0002, +    L2CAP_CID_ALLOC	= 0x0040, +}; + +/* L2CAP command codes */ +enum bt_l2cap_cmd { +    L2CAP_COMMAND_REJ	= 1, +    L2CAP_CONN_REQ, +    L2CAP_CONN_RSP, +    L2CAP_CONF_REQ, +    L2CAP_CONF_RSP, +    L2CAP_DISCONN_REQ, +    L2CAP_DISCONN_RSP, +    L2CAP_ECHO_REQ, +    L2CAP_ECHO_RSP, +    L2CAP_INFO_REQ, +    L2CAP_INFO_RSP, +}; + +enum bt_l2cap_sar_bits { +    L2CAP_SAR_NO_SEG	= 0, +    L2CAP_SAR_START, +    L2CAP_SAR_END, +    L2CAP_SAR_CONT, +}; + +/* L2CAP structures */ +typedef struct { +    uint16_t	len; +    uint16_t	cid; +    uint8_t	data[0]; +} QEMU_PACKED l2cap_hdr; +#define L2CAP_HDR_SIZE 4 + +typedef struct { +    uint8_t	code; +    uint8_t	ident; +    uint16_t	len; +} QEMU_PACKED l2cap_cmd_hdr; +#define L2CAP_CMD_HDR_SIZE 4 + +typedef struct { +    uint16_t	reason; +} QEMU_PACKED l2cap_cmd_rej; +#define L2CAP_CMD_REJ_SIZE 2 + +typedef struct { +    uint16_t	dcid; +    uint16_t	scid; +} QEMU_PACKED l2cap_cmd_rej_cid; +#define L2CAP_CMD_REJ_CID_SIZE 4 + +/* reject reason */ +enum bt_l2cap_rej_reason { +    L2CAP_REJ_CMD_NOT_UNDERSTOOD = 0, +    L2CAP_REJ_SIG_TOOBIG, +    L2CAP_REJ_CID_INVAL, +}; + +typedef struct { +    uint16_t	psm; +    uint16_t	scid; +} QEMU_PACKED l2cap_conn_req; +#define L2CAP_CONN_REQ_SIZE 4 + +typedef struct { +    uint16_t	dcid; +    uint16_t	scid; +    uint16_t	result; +    uint16_t	status; +} QEMU_PACKED l2cap_conn_rsp; +#define L2CAP_CONN_RSP_SIZE 8 + +/* connect result */ +enum bt_l2cap_conn_res { +    L2CAP_CR_SUCCESS	= 0, +    L2CAP_CR_PEND, +    L2CAP_CR_BAD_PSM, +    L2CAP_CR_SEC_BLOCK, +    L2CAP_CR_NO_MEM, +}; + +/* connect status */ +enum bt_l2cap_conn_stat { +    L2CAP_CS_NO_INFO	= 0, +    L2CAP_CS_AUTHEN_PEND, +    L2CAP_CS_AUTHOR_PEND, +}; + +typedef struct { +    uint16_t	dcid; +    uint16_t	flags; +    uint8_t	data[0]; +} QEMU_PACKED l2cap_conf_req; +#define L2CAP_CONF_REQ_SIZE(datalen) (4 + (datalen)) + +typedef struct { +    uint16_t	scid; +    uint16_t	flags; +    uint16_t	result; +    uint8_t	data[0]; +} QEMU_PACKED l2cap_conf_rsp; +#define L2CAP_CONF_RSP_SIZE(datalen) (6 + datalen) + +enum bt_l2cap_conf_res { +    L2CAP_CONF_SUCCESS	= 0, +    L2CAP_CONF_UNACCEPT, +    L2CAP_CONF_REJECT, +    L2CAP_CONF_UNKNOWN, +}; + +typedef struct { +    uint8_t	type; +    uint8_t	len; +    uint8_t	val[0]; +} QEMU_PACKED l2cap_conf_opt; +#define L2CAP_CONF_OPT_SIZE 2 + +enum bt_l2cap_conf_val { +    L2CAP_CONF_MTU	= 1, +    L2CAP_CONF_FLUSH_TO, +    L2CAP_CONF_QOS, +    L2CAP_CONF_RFC, +    L2CAP_CONF_RFC_MODE	= L2CAP_CONF_RFC, +}; + +typedef struct { +    uint8_t	flags; +    uint8_t	service_type; +    uint32_t	token_rate; +    uint32_t	token_bucket_size; +    uint32_t	peak_bandwidth; +    uint32_t	latency; +    uint32_t	delay_variation; +} QEMU_PACKED l2cap_conf_opt_qos; +#define L2CAP_CONF_OPT_QOS_SIZE 22 + +enum bt_l2cap_conf_opt_qos_st { +    L2CAP_CONF_QOS_NO_TRAFFIC = 0x00, +    L2CAP_CONF_QOS_BEST_EFFORT, +    L2CAP_CONF_QOS_GUARANTEED, +}; + +#define L2CAP_CONF_QOS_WILDCARD	0xffffffff + +enum bt_l2cap_mode { +    L2CAP_MODE_BASIC	= 0, +    L2CAP_MODE_RETRANS	= 1, +    L2CAP_MODE_FLOWCTL	= 2, +}; + +typedef struct { +    uint16_t	dcid; +    uint16_t	scid; +} QEMU_PACKED l2cap_disconn_req; +#define L2CAP_DISCONN_REQ_SIZE 4 + +typedef struct { +    uint16_t	dcid; +    uint16_t	scid; +} QEMU_PACKED l2cap_disconn_rsp; +#define L2CAP_DISCONN_RSP_SIZE 4 + +typedef struct { +    uint16_t	type; +} QEMU_PACKED l2cap_info_req; +#define L2CAP_INFO_REQ_SIZE 2 + +typedef struct { +    uint16_t	type; +    uint16_t	result; +    uint8_t	data[0]; +} QEMU_PACKED l2cap_info_rsp; +#define L2CAP_INFO_RSP_SIZE 4 + +/* info type */ +enum bt_l2cap_info_type { +    L2CAP_IT_CL_MTU	= 1, +    L2CAP_IT_FEAT_MASK, +}; + +/* info result */ +enum bt_l2cap_info_result { +    L2CAP_IR_SUCCESS	= 0, +    L2CAP_IR_NOTSUPP, +}; + +/* Service Discovery Protocol defines */ +/* Note that all multibyte values in lower layer protocols (above in this file) + * are little-endian while SDP is big-endian.  */ + +/* Protocol UUIDs */ +enum sdp_proto_uuid { +    SDP_UUID		= 0x0001, +    UDP_UUID		= 0x0002, +    RFCOMM_UUID		= 0x0003, +    TCP_UUID		= 0x0004, +    TCS_BIN_UUID	= 0x0005, +    TCS_AT_UUID		= 0x0006, +    OBEX_UUID		= 0x0008, +    IP_UUID		= 0x0009, +    FTP_UUID		= 0x000a, +    HTTP_UUID		= 0x000c, +    WSP_UUID		= 0x000e, +    BNEP_UUID		= 0x000f, +    UPNP_UUID		= 0x0010, +    HIDP_UUID		= 0x0011, +    HCRP_CTRL_UUID	= 0x0012, +    HCRP_DATA_UUID	= 0x0014, +    HCRP_NOTE_UUID	= 0x0016, +    AVCTP_UUID		= 0x0017, +    AVDTP_UUID		= 0x0019, +    CMTP_UUID		= 0x001b, +    UDI_UUID		= 0x001d, +    MCAP_CTRL_UUID	= 0x001e, +    MCAP_DATA_UUID	= 0x001f, +    L2CAP_UUID		= 0x0100, +}; + +/* + * Service class identifiers of standard services and service groups + */ +enum service_class_id { +    SDP_SERVER_SVCLASS_ID		= 0x1000, +    BROWSE_GRP_DESC_SVCLASS_ID		= 0x1001, +    PUBLIC_BROWSE_GROUP			= 0x1002, +    SERIAL_PORT_SVCLASS_ID		= 0x1101, +    LAN_ACCESS_SVCLASS_ID		= 0x1102, +    DIALUP_NET_SVCLASS_ID		= 0x1103, +    IRMC_SYNC_SVCLASS_ID		= 0x1104, +    OBEX_OBJPUSH_SVCLASS_ID		= 0x1105, +    OBEX_FILETRANS_SVCLASS_ID		= 0x1106, +    IRMC_SYNC_CMD_SVCLASS_ID		= 0x1107, +    HEADSET_SVCLASS_ID			= 0x1108, +    CORDLESS_TELEPHONY_SVCLASS_ID	= 0x1109, +    AUDIO_SOURCE_SVCLASS_ID		= 0x110a, +    AUDIO_SINK_SVCLASS_ID		= 0x110b, +    AV_REMOTE_TARGET_SVCLASS_ID		= 0x110c, +    ADVANCED_AUDIO_SVCLASS_ID		= 0x110d, +    AV_REMOTE_SVCLASS_ID		= 0x110e, +    VIDEO_CONF_SVCLASS_ID		= 0x110f, +    INTERCOM_SVCLASS_ID			= 0x1110, +    FAX_SVCLASS_ID			= 0x1111, +    HEADSET_AGW_SVCLASS_ID		= 0x1112, +    WAP_SVCLASS_ID			= 0x1113, +    WAP_CLIENT_SVCLASS_ID		= 0x1114, +    PANU_SVCLASS_ID			= 0x1115, +    NAP_SVCLASS_ID			= 0x1116, +    GN_SVCLASS_ID			= 0x1117, +    DIRECT_PRINTING_SVCLASS_ID		= 0x1118, +    REFERENCE_PRINTING_SVCLASS_ID	= 0x1119, +    IMAGING_SVCLASS_ID			= 0x111a, +    IMAGING_RESPONDER_SVCLASS_ID	= 0x111b, +    IMAGING_ARCHIVE_SVCLASS_ID		= 0x111c, +    IMAGING_REFOBJS_SVCLASS_ID		= 0x111d, +    HANDSFREE_SVCLASS_ID		= 0x111e, +    HANDSFREE_AGW_SVCLASS_ID		= 0x111f, +    DIRECT_PRT_REFOBJS_SVCLASS_ID	= 0x1120, +    REFLECTED_UI_SVCLASS_ID		= 0x1121, +    BASIC_PRINTING_SVCLASS_ID		= 0x1122, +    PRINTING_STATUS_SVCLASS_ID		= 0x1123, +    HID_SVCLASS_ID			= 0x1124, +    HCR_SVCLASS_ID			= 0x1125, +    HCR_PRINT_SVCLASS_ID		= 0x1126, +    HCR_SCAN_SVCLASS_ID			= 0x1127, +    CIP_SVCLASS_ID			= 0x1128, +    VIDEO_CONF_GW_SVCLASS_ID		= 0x1129, +    UDI_MT_SVCLASS_ID			= 0x112a, +    UDI_TA_SVCLASS_ID			= 0x112b, +    AV_SVCLASS_ID			= 0x112c, +    SAP_SVCLASS_ID			= 0x112d, +    PBAP_PCE_SVCLASS_ID			= 0x112e, +    PBAP_PSE_SVCLASS_ID			= 0x112f, +    PBAP_SVCLASS_ID			= 0x1130, +    PNP_INFO_SVCLASS_ID			= 0x1200, +    GENERIC_NETWORKING_SVCLASS_ID	= 0x1201, +    GENERIC_FILETRANS_SVCLASS_ID	= 0x1202, +    GENERIC_AUDIO_SVCLASS_ID		= 0x1203, +    GENERIC_TELEPHONY_SVCLASS_ID	= 0x1204, +    UPNP_SVCLASS_ID			= 0x1205, +    UPNP_IP_SVCLASS_ID			= 0x1206, +    UPNP_PAN_SVCLASS_ID			= 0x1300, +    UPNP_LAP_SVCLASS_ID			= 0x1301, +    UPNP_L2CAP_SVCLASS_ID		= 0x1302, +    VIDEO_SOURCE_SVCLASS_ID		= 0x1303, +    VIDEO_SINK_SVCLASS_ID		= 0x1304, +    VIDEO_DISTRIBUTION_SVCLASS_ID	= 0x1305, +    MDP_SVCLASS_ID			= 0x1400, +    MDP_SOURCE_SVCLASS_ID		= 0x1401, +    MDP_SINK_SVCLASS_ID			= 0x1402, +    APPLE_AGENT_SVCLASS_ID		= 0x2112, +}; + +/* + * Standard profile descriptor identifiers; note these + * may be identical to some of the service classes defined above + */ +#define SDP_SERVER_PROFILE_ID		SDP_SERVER_SVCLASS_ID +#define BROWSE_GRP_DESC_PROFILE_ID	BROWSE_GRP_DESC_SVCLASS_ID +#define SERIAL_PORT_PROFILE_ID		SERIAL_PORT_SVCLASS_ID +#define LAN_ACCESS_PROFILE_ID		LAN_ACCESS_SVCLASS_ID +#define DIALUP_NET_PROFILE_ID		DIALUP_NET_SVCLASS_ID +#define IRMC_SYNC_PROFILE_ID		IRMC_SYNC_SVCLASS_ID +#define OBEX_OBJPUSH_PROFILE_ID		OBEX_OBJPUSH_SVCLASS_ID +#define OBEX_FILETRANS_PROFILE_ID	OBEX_FILETRANS_SVCLASS_ID +#define IRMC_SYNC_CMD_PROFILE_ID	IRMC_SYNC_CMD_SVCLASS_ID +#define HEADSET_PROFILE_ID		HEADSET_SVCLASS_ID +#define CORDLESS_TELEPHONY_PROFILE_ID	CORDLESS_TELEPHONY_SVCLASS_ID +#define AUDIO_SOURCE_PROFILE_ID		AUDIO_SOURCE_SVCLASS_ID +#define AUDIO_SINK_PROFILE_ID		AUDIO_SINK_SVCLASS_ID +#define AV_REMOTE_TARGET_PROFILE_ID	AV_REMOTE_TARGET_SVCLASS_ID +#define ADVANCED_AUDIO_PROFILE_ID	ADVANCED_AUDIO_SVCLASS_ID +#define AV_REMOTE_PROFILE_ID		AV_REMOTE_SVCLASS_ID +#define VIDEO_CONF_PROFILE_ID		VIDEO_CONF_SVCLASS_ID +#define INTERCOM_PROFILE_ID		INTERCOM_SVCLASS_ID +#define FAX_PROFILE_ID			FAX_SVCLASS_ID +#define HEADSET_AGW_PROFILE_ID		HEADSET_AGW_SVCLASS_ID +#define WAP_PROFILE_ID			WAP_SVCLASS_ID +#define WAP_CLIENT_PROFILE_ID		WAP_CLIENT_SVCLASS_ID +#define PANU_PROFILE_ID			PANU_SVCLASS_ID +#define NAP_PROFILE_ID			NAP_SVCLASS_ID +#define GN_PROFILE_ID			GN_SVCLASS_ID +#define DIRECT_PRINTING_PROFILE_ID	DIRECT_PRINTING_SVCLASS_ID +#define REFERENCE_PRINTING_PROFILE_ID	REFERENCE_PRINTING_SVCLASS_ID +#define IMAGING_PROFILE_ID		IMAGING_SVCLASS_ID +#define IMAGING_RESPONDER_PROFILE_ID	IMAGING_RESPONDER_SVCLASS_ID +#define IMAGING_ARCHIVE_PROFILE_ID	IMAGING_ARCHIVE_SVCLASS_ID +#define IMAGING_REFOBJS_PROFILE_ID	IMAGING_REFOBJS_SVCLASS_ID +#define HANDSFREE_PROFILE_ID		HANDSFREE_SVCLASS_ID +#define HANDSFREE_AGW_PROFILE_ID	HANDSFREE_AGW_SVCLASS_ID +#define DIRECT_PRT_REFOBJS_PROFILE_ID	DIRECT_PRT_REFOBJS_SVCLASS_ID +#define REFLECTED_UI_PROFILE_ID		REFLECTED_UI_SVCLASS_ID +#define BASIC_PRINTING_PROFILE_ID	BASIC_PRINTING_SVCLASS_ID +#define PRINTING_STATUS_PROFILE_ID	PRINTING_STATUS_SVCLASS_ID +#define HID_PROFILE_ID			HID_SVCLASS_ID +#define HCR_PROFILE_ID			HCR_SCAN_SVCLASS_ID +#define HCR_PRINT_PROFILE_ID		HCR_PRINT_SVCLASS_ID +#define HCR_SCAN_PROFILE_ID		HCR_SCAN_SVCLASS_ID +#define CIP_PROFILE_ID			CIP_SVCLASS_ID +#define VIDEO_CONF_GW_PROFILE_ID	VIDEO_CONF_GW_SVCLASS_ID +#define UDI_MT_PROFILE_ID		UDI_MT_SVCLASS_ID +#define UDI_TA_PROFILE_ID		UDI_TA_SVCLASS_ID +#define AV_PROFILE_ID			AV_SVCLASS_ID +#define SAP_PROFILE_ID			SAP_SVCLASS_ID +#define PBAP_PCE_PROFILE_ID		PBAP_PCE_SVCLASS_ID +#define PBAP_PSE_PROFILE_ID		PBAP_PSE_SVCLASS_ID +#define PBAP_PROFILE_ID			PBAP_SVCLASS_ID +#define PNP_INFO_PROFILE_ID		PNP_INFO_SVCLASS_ID +#define GENERIC_NETWORKING_PROFILE_ID	GENERIC_NETWORKING_SVCLASS_ID +#define GENERIC_FILETRANS_PROFILE_ID	GENERIC_FILETRANS_SVCLASS_ID +#define GENERIC_AUDIO_PROFILE_ID	GENERIC_AUDIO_SVCLASS_ID +#define GENERIC_TELEPHONY_PROFILE_ID	GENERIC_TELEPHONY_SVCLASS_ID +#define UPNP_PROFILE_ID			UPNP_SVCLASS_ID +#define UPNP_IP_PROFILE_ID		UPNP_IP_SVCLASS_ID +#define UPNP_PAN_PROFILE_ID		UPNP_PAN_SVCLASS_ID +#define UPNP_LAP_PROFILE_ID		UPNP_LAP_SVCLASS_ID +#define UPNP_L2CAP_PROFILE_ID		UPNP_L2CAP_SVCLASS_ID +#define VIDEO_SOURCE_PROFILE_ID		VIDEO_SOURCE_SVCLASS_ID +#define VIDEO_SINK_PROFILE_ID		VIDEO_SINK_SVCLASS_ID +#define VIDEO_DISTRIBUTION_PROFILE_ID	VIDEO_DISTRIBUTION_SVCLASS_ID +#define MDP_PROFILE_ID			MDP_SVCLASS_ID +#define MDP_SOURCE_PROFILE_ID		MDP_SROUCE_SVCLASS_ID +#define MDP_SINK_PROFILE_ID		MDP_SINK_SVCLASS_ID +#define APPLE_AGENT_PROFILE_ID		APPLE_AGENT_SVCLASS_ID + +/* Data Representation */ +enum bt_sdp_data_type { +    SDP_DTYPE_NIL	= 0 << 3, +    SDP_DTYPE_UINT	= 1 << 3, +    SDP_DTYPE_SINT	= 2 << 3, +    SDP_DTYPE_UUID	= 3 << 3, +    SDP_DTYPE_STRING	= 4 << 3, +    SDP_DTYPE_BOOL	= 5 << 3, +    SDP_DTYPE_SEQ	= 6 << 3, +    SDP_DTYPE_ALT	= 7 << 3, +    SDP_DTYPE_URL	= 8 << 3, +}; + +enum bt_sdp_data_size { +    SDP_DSIZE_1		= 0, +    SDP_DSIZE_2, +    SDP_DSIZE_4, +    SDP_DSIZE_8, +    SDP_DSIZE_16, +    SDP_DSIZE_NEXT1, +    SDP_DSIZE_NEXT2, +    SDP_DSIZE_NEXT4, +    SDP_DSIZE_MASK = SDP_DSIZE_NEXT4, +}; + +enum bt_sdp_cmd { +    SDP_ERROR_RSP		= 0x01, +    SDP_SVC_SEARCH_REQ		= 0x02, +    SDP_SVC_SEARCH_RSP		= 0x03, +    SDP_SVC_ATTR_REQ		= 0x04, +    SDP_SVC_ATTR_RSP		= 0x05, +    SDP_SVC_SEARCH_ATTR_REQ	= 0x06, +    SDP_SVC_SEARCH_ATTR_RSP	= 0x07, +}; + +enum bt_sdp_errorcode { +    SDP_INVALID_VERSION		= 0x0001, +    SDP_INVALID_RECORD_HANDLE	= 0x0002, +    SDP_INVALID_SYNTAX		= 0x0003, +    SDP_INVALID_PDU_SIZE	= 0x0004, +    SDP_INVALID_CSTATE		= 0x0005, +}; + +/* + * String identifiers are based on the SDP spec stating that + * "base attribute id of the primary (universal) language must be 0x0100" + * + * Other languages should have their own offset; e.g.: + * #define XXXLangBase yyyy + * #define AttrServiceName_XXX	0x0000+XXXLangBase + */ +#define SDP_PRIMARY_LANG_BASE 		0x0100 + +enum bt_sdp_attribute_id { +    SDP_ATTR_RECORD_HANDLE			= 0x0000, +    SDP_ATTR_SVCLASS_ID_LIST			= 0x0001, +    SDP_ATTR_RECORD_STATE			= 0x0002, +    SDP_ATTR_SERVICE_ID				= 0x0003, +    SDP_ATTR_PROTO_DESC_LIST			= 0x0004, +    SDP_ATTR_BROWSE_GRP_LIST			= 0x0005, +    SDP_ATTR_LANG_BASE_ATTR_ID_LIST		= 0x0006, +    SDP_ATTR_SVCINFO_TTL			= 0x0007, +    SDP_ATTR_SERVICE_AVAILABILITY		= 0x0008, +    SDP_ATTR_PFILE_DESC_LIST			= 0x0009, +    SDP_ATTR_DOC_URL				= 0x000a, +    SDP_ATTR_CLNT_EXEC_URL			= 0x000b, +    SDP_ATTR_ICON_URL				= 0x000c, +    SDP_ATTR_ADD_PROTO_DESC_LIST		= 0x000d, + +    SDP_ATTR_SVCNAME_PRIMARY			= SDP_PRIMARY_LANG_BASE + 0, +    SDP_ATTR_SVCDESC_PRIMARY			= SDP_PRIMARY_LANG_BASE + 1, +    SDP_ATTR_SVCPROV_PRIMARY			= SDP_PRIMARY_LANG_BASE + 2, + +    SDP_ATTR_GROUP_ID				= 0x0200, +    SDP_ATTR_IP_SUBNET				= 0x0200, + +    /* SDP */ +    SDP_ATTR_VERSION_NUM_LIST			= 0x0200, +    SDP_ATTR_SVCDB_STATE			= 0x0201, + +    SDP_ATTR_SERVICE_VERSION			= 0x0300, +    SDP_ATTR_EXTERNAL_NETWORK			= 0x0301, +    SDP_ATTR_SUPPORTED_DATA_STORES_LIST		= 0x0301, +    SDP_ATTR_FAX_CLASS1_SUPPORT			= 0x0302, +    SDP_ATTR_REMOTE_AUDIO_VOLUME_CONTROL	= 0x0302, +    SDP_ATTR_FAX_CLASS20_SUPPORT		= 0x0303, +    SDP_ATTR_SUPPORTED_FORMATS_LIST		= 0x0303, +    SDP_ATTR_FAX_CLASS2_SUPPORT			= 0x0304, +    SDP_ATTR_AUDIO_FEEDBACK_SUPPORT		= 0x0305, +    SDP_ATTR_NETWORK_ADDRESS			= 0x0306, +    SDP_ATTR_WAP_GATEWAY			= 0x0307, +    SDP_ATTR_HOMEPAGE_URL			= 0x0308, +    SDP_ATTR_WAP_STACK_TYPE			= 0x0309, +    SDP_ATTR_SECURITY_DESC			= 0x030a, +    SDP_ATTR_NET_ACCESS_TYPE			= 0x030b, +    SDP_ATTR_MAX_NET_ACCESSRATE			= 0x030c, +    SDP_ATTR_IP4_SUBNET				= 0x030d, +    SDP_ATTR_IP6_SUBNET				= 0x030e, +    SDP_ATTR_SUPPORTED_CAPABILITIES		= 0x0310, +    SDP_ATTR_SUPPORTED_FEATURES			= 0x0311, +    SDP_ATTR_SUPPORTED_FUNCTIONS		= 0x0312, +    SDP_ATTR_TOTAL_IMAGING_DATA_CAPACITY	= 0x0313, +    SDP_ATTR_SUPPORTED_REPOSITORIES		= 0x0314, + +    /* PnP Information */ +    SDP_ATTR_SPECIFICATION_ID			= 0x0200, +    SDP_ATTR_VENDOR_ID				= 0x0201, +    SDP_ATTR_PRODUCT_ID				= 0x0202, +    SDP_ATTR_VERSION				= 0x0203, +    SDP_ATTR_PRIMARY_RECORD			= 0x0204, +    SDP_ATTR_VENDOR_ID_SOURCE			= 0x0205, + +    /* BT HID */ +    SDP_ATTR_DEVICE_RELEASE_NUMBER		= 0x0200, +    SDP_ATTR_PARSER_VERSION			= 0x0201, +    SDP_ATTR_DEVICE_SUBCLASS			= 0x0202, +    SDP_ATTR_COUNTRY_CODE			= 0x0203, +    SDP_ATTR_VIRTUAL_CABLE			= 0x0204, +    SDP_ATTR_RECONNECT_INITIATE			= 0x0205, +    SDP_ATTR_DESCRIPTOR_LIST			= 0x0206, +    SDP_ATTR_LANG_ID_BASE_LIST			= 0x0207, +    SDP_ATTR_SDP_DISABLE			= 0x0208, +    SDP_ATTR_BATTERY_POWER			= 0x0209, +    SDP_ATTR_REMOTE_WAKEUP			= 0x020a, +    SDP_ATTR_PROFILE_VERSION			= 0x020b, +    SDP_ATTR_SUPERVISION_TIMEOUT		= 0x020c, +    SDP_ATTR_NORMALLY_CONNECTABLE		= 0x020d, +    SDP_ATTR_BOOT_DEVICE			= 0x020e, +}; + +#endif diff --git a/include/hw/char/cadence_uart.h b/include/hw/char/cadence_uart.h new file mode 100644 index 00000000..6310f525 --- /dev/null +++ b/include/hw/char/cadence_uart.h @@ -0,0 +1,53 @@ +/* + * Device model for Cadence UART + * + * Copyright (c) 2010 Xilinx Inc. + * Copyright (c) 2012 Peter A.G. Crosthwaite (peter.crosthwaite@petalogix.com) + * Copyright (c) 2012 PetaLogix Pty Ltd. + * Written by Haibing Ma + *            M.Habib + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef CADENCE_UART_H + +#include "hw/sysbus.h" +#include "sysemu/char.h" +#include "qemu/timer.h" + +#define CADENCE_UART_RX_FIFO_SIZE           16 +#define CADENCE_UART_TX_FIFO_SIZE           16 + +#define CADENCE_UART_R_MAX (0x48/4) + +#define TYPE_CADENCE_UART "cadence_uart" +#define CADENCE_UART(obj) OBJECT_CHECK(CadenceUARTState, (obj), \ +                                       TYPE_CADENCE_UART) + +typedef struct { +    /*< private >*/ +    SysBusDevice parent_obj; + +    /*< public >*/ +    MemoryRegion iomem; +    uint32_t r[CADENCE_UART_R_MAX]; +    uint8_t rx_fifo[CADENCE_UART_RX_FIFO_SIZE]; +    uint8_t tx_fifo[CADENCE_UART_TX_FIFO_SIZE]; +    uint32_t rx_wpos; +    uint32_t rx_count; +    uint32_t tx_count; +    uint64_t char_tx_time; +    CharDriverState *chr; +    qemu_irq irq; +    QEMUTimer *fifo_trigger_handle; +} CadenceUARTState; + +#define CADENCE_UART_H +#endif diff --git a/include/hw/char/digic-uart.h b/include/hw/char/digic-uart.h new file mode 100644 index 00000000..ef83a305 --- /dev/null +++ b/include/hw/char/digic-uart.h @@ -0,0 +1,47 @@ +/* + * Canon DIGIC UART block declarations. + * + * Copyright (C) 2013 Antony Pavlov <antonynpavlov@gmail.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef HW_CHAR_DIGIC_UART_H +#define HW_CHAR_DIGIC_UART_H + +#include "hw/sysbus.h" +#include "qemu/typedefs.h" + +#define TYPE_DIGIC_UART "digic-uart" +#define DIGIC_UART(obj) \ +    OBJECT_CHECK(DigicUartState, (obj), TYPE_DIGIC_UART) + +enum { +    R_TX = 0x00, +    R_RX, +    R_ST = (0x14 >> 2), +    R_MAX +}; + +typedef struct DigicUartState { +    /*< private >*/ +    SysBusDevice parent_obj; +    /*< public >*/ + +    MemoryRegion regs_region; +    CharDriverState *chr; + +    uint32_t reg_rx; +    uint32_t reg_st; +} DigicUartState; + +#endif /* HW_CHAR_DIGIC_UART_H */ diff --git a/include/hw/char/escc.h b/include/hw/char/escc.h new file mode 100644 index 00000000..2742d70e --- /dev/null +++ b/include/hw/char/escc.h @@ -0,0 +1,14 @@ +#ifndef HW_ESCC_H +#define HW_ESCC_H 1 + +/* escc.c */ +#define TYPE_ESCC "escc" +#define ESCC_SIZE 4 +MemoryRegion *escc_init(hwaddr base, qemu_irq irqA, qemu_irq irqB, +              CharDriverState *chrA, CharDriverState *chrB, +              int clock, int it_shift); + +void slavio_serial_ms_kbd_init(hwaddr base, qemu_irq irq, +                               int disabled, int clock, int it_shift); + +#endif diff --git a/include/hw/char/lm32_juart.h b/include/hw/char/lm32_juart.h new file mode 100644 index 00000000..70dc416e --- /dev/null +++ b/include/hw/char/lm32_juart.h @@ -0,0 +1,13 @@ +#ifndef QEMU_HW_CHAR_LM32_JUART_H +#define QEMU_HW_CHAR_LM32_JUART_H + +#include "hw/qdev.h" + +#define TYPE_LM32_JUART "lm32-juart" + +uint32_t lm32_juart_get_jtx(DeviceState *d); +uint32_t lm32_juart_get_jrx(DeviceState *d); +void lm32_juart_set_jtx(DeviceState *d, uint32_t jtx); +void lm32_juart_set_jrx(DeviceState *d, uint32_t jrx); + +#endif /* QEMU_HW_LM32_JUART_H */ diff --git a/include/hw/char/serial.h b/include/hw/char/serial.h new file mode 100644 index 00000000..15beb6b4 --- /dev/null +++ b/include/hw/char/serial.h @@ -0,0 +1,97 @@ +/* + * QEMU 16550A UART emulation + * + * Copyright (c) 2003-2004 Fabrice Bellard + * Copyright (c) 2008 Citrix Systems, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * 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 OTHER + * 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. + */ +#ifndef HW_SERIAL_H +#define HW_SERIAL_H 1 + +#include "hw/hw.h" +#include "sysemu/sysemu.h" +#include "exec/memory.h" +#include "qemu/fifo8.h" + +#define UART_FIFO_LENGTH    16      /* 16550A Fifo Length */ + +struct SerialState { +    uint16_t divider; +    uint8_t rbr; /* receive register */ +    uint8_t thr; /* transmit holding register */ +    uint8_t tsr; /* transmit shift register */ +    uint8_t ier; +    uint8_t iir; /* read only */ +    uint8_t lcr; +    uint8_t mcr; +    uint8_t lsr; /* read only */ +    uint8_t msr; /* read only */ +    uint8_t scr; +    uint8_t fcr; +    uint8_t fcr_vmstate; /* we can't write directly this value +                            it has side effects */ +    /* NOTE: this hidden state is necessary for tx irq generation as +       it can be reset while reading iir */ +    int thr_ipending; +    qemu_irq irq; +    CharDriverState *chr; +    int last_break_enable; +    int it_shift; +    int baudbase; +    int tsr_retry; +    uint32_t wakeup; + +    /* Time when the last byte was successfully sent out of the tsr */ +    uint64_t last_xmit_ts; +    Fifo8 recv_fifo; +    Fifo8 xmit_fifo; +    /* Interrupt trigger level for recv_fifo */ +    uint8_t recv_fifo_itl; + +    QEMUTimer *fifo_timeout_timer; +    int timeout_ipending;           /* timeout interrupt pending state */ + +    uint64_t char_transmit_time;    /* time to transmit a char in ticks */ +    int poll_msl; + +    QEMUTimer *modem_status_poll; +    MemoryRegion io; +}; + +extern const VMStateDescription vmstate_serial; +extern const MemoryRegionOps serial_io_ops; + +void serial_realize_core(SerialState *s, Error **errp); +void serial_exit_core(SerialState *s); +void serial_set_frequency(SerialState *s, uint32_t frequency); + +/* legacy pre qom */ +SerialState *serial_init(int base, qemu_irq irq, int baudbase, +                         CharDriverState *chr, MemoryRegion *system_io); +SerialState *serial_mm_init(MemoryRegion *address_space, +                            hwaddr base, int it_shift, +                            qemu_irq irq, int baudbase, +                            CharDriverState *chr, enum device_endian end); + +/* serial-isa.c */ +#define TYPE_ISA_SERIAL "isa-serial" +void serial_hds_isa_init(ISABus *bus, int n); + +#endif diff --git a/include/hw/char/stm32f2xx_usart.h b/include/hw/char/stm32f2xx_usart.h new file mode 100644 index 00000000..b97f192a --- /dev/null +++ b/include/hw/char/stm32f2xx_usart.h @@ -0,0 +1,73 @@ +/* + * STM32F2XX USART + * + * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me> + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * 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 OTHER + * 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. + */ + +#ifndef HW_STM32F2XX_USART_H +#define HW_STM32F2XX_USART_H + +#include "hw/sysbus.h" +#include "sysemu/char.h" +#include "hw/hw.h" + +#define USART_SR   0x00 +#define USART_DR   0x04 +#define USART_BRR  0x08 +#define USART_CR1  0x0C +#define USART_CR2  0x10 +#define USART_CR3  0x14 +#define USART_GTPR 0x18 + +#define USART_SR_RESET 0x00C00000 + +#define USART_SR_TXE  (1 << 7) +#define USART_SR_TC   (1 << 6) +#define USART_SR_RXNE (1 << 5) + +#define USART_CR1_UE  (1 << 13) +#define USART_CR1_RXNEIE  (1 << 5) +#define USART_CR1_TE  (1 << 3) +#define USART_CR1_RE  (1 << 2) + +#define TYPE_STM32F2XX_USART "stm32f2xx-usart" +#define STM32F2XX_USART(obj) \ +    OBJECT_CHECK(STM32F2XXUsartState, (obj), TYPE_STM32F2XX_USART) + +typedef struct { +    /* <private> */ +    SysBusDevice parent_obj; + +    /* <public> */ +    MemoryRegion mmio; + +    uint32_t usart_sr; +    uint32_t usart_dr; +    uint32_t usart_brr; +    uint32_t usart_cr1; +    uint32_t usart_cr2; +    uint32_t usart_cr3; +    uint32_t usart_gtpr; + +    CharDriverState *chr; +    qemu_irq irq; +} STM32F2XXUsartState; +#endif /* HW_STM32F2XX_USART_H */ diff --git a/include/hw/compat.h b/include/hw/compat.h new file mode 100644 index 00000000..94c8097d --- /dev/null +++ b/include/hw/compat.h @@ -0,0 +1,61 @@ +#ifndef HW_COMPAT_H +#define HW_COMPAT_H + +#define HW_COMPAT_2_3 \ +        {\ +            .driver   = "virtio-blk-pci",\ +            .property = "any_layout",\ +            .value    = "off",\ +        },{\ +            .driver   = "virtio-balloon-pci",\ +            .property = "any_layout",\ +            .value    = "off",\ +        },{\ +            .driver   = "virtio-serial-pci",\ +            .property = "any_layout",\ +            .value    = "off",\ +        },{\ +            .driver   = "virtio-9p-pci",\ +            .property = "any_layout",\ +            .value    = "off",\ +        },{\ +            .driver   = "virtio-rng-pci",\ +            .property = "any_layout",\ +            .value    = "off",\ +        }, + +#define HW_COMPAT_2_2 \ +        /* empty */ + +#define HW_COMPAT_2_1 \ +        {\ +            .driver   = "intel-hda",\ +            .property = "old_msi_addr",\ +            .value    = "on",\ +        },{\ +            .driver   = "VGA",\ +            .property = "qemu-extended-regs",\ +            .value    = "off",\ +        },{\ +            .driver   = "secondary-vga",\ +            .property = "qemu-extended-regs",\ +            .value    = "off",\ +        },{\ +            .driver   = "virtio-scsi-pci",\ +            .property = "any_layout",\ +            .value    = "off",\ +        },{\ +            .driver   = "usb-mouse",\ +            .property = "usb_version",\ +            .value    = stringify(1),\ +        },{\ +            .driver   = "usb-kbd",\ +            .property = "usb_version",\ +            .value    = stringify(1),\ +        },{\ +            .driver   = "virtio-pci",\ +            .property = "virtio-pci-bus-master-bug-migration",\ +            .value    = "on",\ +        }, + +#endif /* HW_COMPAT_H */ diff --git a/include/hw/cpu/a15mpcore.h b/include/hw/cpu/a15mpcore.h new file mode 100644 index 00000000..b423533d --- /dev/null +++ b/include/hw/cpu/a15mpcore.h @@ -0,0 +1,44 @@ +/* + * Cortex-A15MPCore internal peripheral emulation. + * + * Copyright (c) 2012 Linaro Limited. + * Written by Peter Maydell. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, see <http://www.gnu.org/licenses/>. + */ +#ifndef HW_CPU_A15MPCORE_H +#define HW_CPU_A15MPCORE_H + +#include "hw/sysbus.h" +#include "hw/intc/arm_gic.h" + +/* A15MP private memory region.  */ + +#define TYPE_A15MPCORE_PRIV "a15mpcore_priv" +#define A15MPCORE_PRIV(obj) \ +    OBJECT_CHECK(A15MPPrivState, (obj), TYPE_A15MPCORE_PRIV) + +typedef struct A15MPPrivState { +    /*< private >*/ +    SysBusDevice parent_obj; +    /*< public >*/ + +    uint32_t num_cpu; +    uint32_t num_irq; +    MemoryRegion container; + +    GICState gic; +} A15MPPrivState; + +#endif diff --git a/include/hw/cpu/a9mpcore.h b/include/hw/cpu/a9mpcore.h new file mode 100644 index 00000000..5d67ca22 --- /dev/null +++ b/include/hw/cpu/a9mpcore.h @@ -0,0 +1,39 @@ +/* + * Cortex-A9MPCore internal peripheral emulation. + * + * Copyright (c) 2009 CodeSourcery. + * Copyright (c) 2011 Linaro Limited. + * Written by Paul Brook, Peter Maydell. + * + * This code is licensed under the GPL. + */ +#ifndef HW_CPU_A9MPCORE_H +#define HW_CPU_A9MPCORE_H + +#include "hw/sysbus.h" +#include "hw/intc/arm_gic.h" +#include "hw/misc/a9scu.h" +#include "hw/timer/arm_mptimer.h" +#include "hw/timer/a9gtimer.h" + +#define TYPE_A9MPCORE_PRIV "a9mpcore_priv" +#define A9MPCORE_PRIV(obj) \ +    OBJECT_CHECK(A9MPPrivState, (obj), TYPE_A9MPCORE_PRIV) + +typedef struct A9MPPrivState { +    /*< private >*/ +    SysBusDevice parent_obj; +    /*< public >*/ + +    uint32_t num_cpu; +    MemoryRegion container; +    uint32_t num_irq; + +    A9SCUState scu; +    GICState gic; +    A9GTimerState gtimer; +    ARMMPTimerState mptimer; +    ARMMPTimerState wdt; +} A9MPPrivState; + +#endif diff --git a/include/hw/cpu/arm11mpcore.h b/include/hw/cpu/arm11mpcore.h new file mode 100644 index 00000000..6196109c --- /dev/null +++ b/include/hw/cpu/arm11mpcore.h @@ -0,0 +1,35 @@ +/* + * ARM11MPCore internal peripheral emulation. + * + * Copyright (c) 2006-2007 CodeSourcery. + * Written by Paul Brook + * + * This code is licensed under the GPL. + */ + +#ifndef HW_CPU_ARM11MPCORE_H +#define HW_CPU_ARM11MPCORE_H + +#include "hw/sysbus.h" +#include "hw/misc/arm11scu.h" +#include "hw/intc/arm_gic.h" +#include "hw/timer/arm_mptimer.h" + +#define TYPE_ARM11MPCORE_PRIV "arm11mpcore_priv" +#define ARM11MPCORE_PRIV(obj) \ +    OBJECT_CHECK(ARM11MPCorePriveState, (obj), TYPE_ARM11MPCORE_PRIV) + +typedef struct ARM11MPCorePriveState { +    SysBusDevice parent_obj; + +    uint32_t num_cpu; +    MemoryRegion container; +    uint32_t num_irq; + +    ARM11SCUState scu; +    GICState gic; +    ARMMPTimerState mptimer; +    ARMMPTimerState wdtimer; +} ARM11MPCorePriveState; + +#endif diff --git a/include/hw/cpu/icc_bus.h b/include/hw/cpu/icc_bus.h new file mode 100644 index 00000000..98a979fa --- /dev/null +++ b/include/hw/cpu/icc_bus.h @@ -0,0 +1,82 @@ +/* icc_bus.h + * emulate x86 ICC (Interrupt Controller Communications) bus + * + * Copyright (c) 2013 Red Hat, Inc + * + * Authors: + *     Igor Mammedov <imammedo@redhat.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/> + */ +#ifndef ICC_BUS_H +#define ICC_BUS_H + +#include "exec/memory.h" +#include "hw/qdev-core.h" + +#define TYPE_ICC_BUS "icc-bus" + +#ifndef CONFIG_USER_ONLY + +/** + * ICCBus: + * + * ICC bus + */ +typedef struct ICCBus { +    /*< private >*/ +    BusState parent_obj; +    /*< public >*/ + +    MemoryRegion *apic_address_space; +} ICCBus; + +#define ICC_BUS(obj) OBJECT_CHECK(ICCBus, (obj), TYPE_ICC_BUS) + +/** + * ICCDevice: + * + * ICC device + */ +typedef struct ICCDevice { +    /*< private >*/ +    DeviceState qdev; +    /*< public >*/ +} ICCDevice; + +/** + * ICCDeviceClass: + * @init: Initialization callback for derived classes. + * + * ICC device class + */ +typedef struct ICCDeviceClass { +    /*< private >*/ +    DeviceClass parent_class; +    /*< public >*/ + +    DeviceRealize realize; +} ICCDeviceClass; + +#define TYPE_ICC_DEVICE "icc-device" +#define ICC_DEVICE(obj) OBJECT_CHECK(ICCDevice, (obj), TYPE_ICC_DEVICE) +#define ICC_DEVICE_CLASS(klass) \ +     OBJECT_CLASS_CHECK(ICCDeviceClass, (klass), TYPE_ICC_DEVICE) +#define ICC_DEVICE_GET_CLASS(obj) \ +     OBJECT_GET_CLASS(ICCDeviceClass, (obj), TYPE_ICC_DEVICE) + +#define TYPE_ICC_BRIDGE "icc-bridge" + +#endif /* CONFIG_USER_ONLY */ +#endif diff --git a/include/hw/cris/etraxfs.h b/include/hw/cris/etraxfs.h new file mode 100644 index 00000000..73a6134c --- /dev/null +++ b/include/hw/cris/etraxfs.h @@ -0,0 +1,49 @@ +/* + * QEMU ETRAX System Emulator + * + * Copyright (c) 2008 Edgar E. Iglesias, Axis Communications AB. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * 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 OTHER + * 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. + */ + +#ifndef HW_EXTRAXFS_H +#define HW_EXTRAXFS_H 1 + +#include "net/net.h" +#include "hw/cris/etraxfs_dma.h" + +/* Instantiate an ETRAXFS Ethernet MAC.  */ +static inline DeviceState * +etraxfs_eth_init(NICInfo *nd, hwaddr base, int phyaddr, +                 void *dma_out, void *dma_in) +{ +    DeviceState *dev; +    qemu_check_nic_model(nd, "fseth"); + +    dev = qdev_create(NULL, "etraxfs-eth"); +    qdev_set_nic_properties(dev, nd); +    qdev_prop_set_uint32(dev, "phyaddr", phyaddr); +    qdev_prop_set_ptr(dev, "dma_out", dma_out); +    qdev_prop_set_ptr(dev, "dma_in", dma_in); +    qdev_init_nofail(dev); +    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base); +    return dev; +} + +#endif diff --git a/include/hw/cris/etraxfs_dma.h b/include/hw/cris/etraxfs_dma.h new file mode 100644 index 00000000..38104a67 --- /dev/null +++ b/include/hw/cris/etraxfs_dma.h @@ -0,0 +1,34 @@ +#ifndef HW_ETRAXFS_DMA_H +#define HW_ETRAXFS_DMA_H 1 + +struct dma_context_metadata { +	/* data descriptor md */ +	uint16_t metadata; +}; + +struct etraxfs_dma_client +{ +	/* DMA controller. */ +	int channel; +	void *ctrl; + +	/* client.  */ +	struct { +		int (*push)(void *opaque, unsigned char *buf, +		            int len, bool eop); +		void (*pull)(void *opaque); +		void (*metadata_push)(void *opaque, +		                      const struct dma_context_metadata *md); +		void *opaque; +	} client; +}; + +void *etraxfs_dmac_init(hwaddr base, int nr_channels); +void etraxfs_dmac_connect(void *opaque, int channel, qemu_irq *line, +			  int input); +void etraxfs_dmac_connect_client(void *opaque, int c,  +				 struct etraxfs_dma_client *cl); +int etraxfs_dmac_input(struct etraxfs_dma_client *client,  +		       void *buf, int len, int eop); + +#endif diff --git a/include/hw/devices.h b/include/hw/devices.h new file mode 100644 index 00000000..c60bcaba --- /dev/null +++ b/include/hw/devices.h @@ -0,0 +1,70 @@ +#ifndef QEMU_DEVICES_H +#define QEMU_DEVICES_H + +#include "hw/irq.h" + +/* ??? Not all users of this file can include cpu-common.h.  */ +struct MemoryRegion; + +/* Devices that have nowhere better to go.  */ + +/* smc91c111.c */ +void smc91c111_init(NICInfo *, uint32_t, qemu_irq); + +/* lan9118.c */ +void lan9118_init(NICInfo *, uint32_t, qemu_irq); + +/* tsc210x.c */ +uWireSlave *tsc2102_init(qemu_irq pint); +uWireSlave *tsc2301_init(qemu_irq penirq, qemu_irq kbirq, qemu_irq dav); +I2SCodec *tsc210x_codec(uWireSlave *chip); +uint32_t tsc210x_txrx(void *opaque, uint32_t value, int len); +void tsc210x_set_transform(uWireSlave *chip, +                MouseTransformInfo *info); +void tsc210x_key_event(uWireSlave *chip, int key, int down); + +/* tsc2005.c */ +void *tsc2005_init(qemu_irq pintdav); +uint32_t tsc2005_txrx(void *opaque, uint32_t value, int len); +void tsc2005_set_transform(void *opaque, MouseTransformInfo *info); + +/* stellaris_input.c */ +void stellaris_gamepad_init(int n, qemu_irq *irq, const int *keycode); + +/* blizzard.c */ +void *s1d13745_init(qemu_irq gpio_int); +void s1d13745_write(void *opaque, int dc, uint16_t value); +void s1d13745_write_block(void *opaque, int dc, +                void *buf, size_t len, int pitch); +uint16_t s1d13745_read(void *opaque, int dc); + +/* cbus.c */ +typedef struct { +    qemu_irq clk; +    qemu_irq dat; +    qemu_irq sel; +} CBus; +CBus *cbus_init(qemu_irq dat_out); +void cbus_attach(CBus *bus, void *slave_opaque); + +void *retu_init(qemu_irq irq, int vilma); +void *tahvo_init(qemu_irq irq, int betty); + +void retu_key_event(void *retu, int state); + +/* tc6393xb.c */ +typedef struct TC6393xbState TC6393xbState; +#define TC6393XB_RAM	0x110000 /* amount of ram for Video and USB */ +TC6393xbState *tc6393xb_init(struct MemoryRegion *sysmem, +                             uint32_t base, qemu_irq irq); +void tc6393xb_gpio_out_set(TC6393xbState *s, int line, +                    qemu_irq handler); +qemu_irq *tc6393xb_gpio_in_get(TC6393xbState *s); +qemu_irq tc6393xb_l3v_get(TC6393xbState *s); + +/* sm501.c */ +void sm501_init(struct MemoryRegion *address_space_mem, uint32_t base, +                uint32_t local_mem_bytes, qemu_irq irq, +                CharDriverState *chr); + +#endif diff --git a/include/hw/elf_ops.h b/include/hw/elf_ops.h new file mode 100644 index 00000000..bd719681 --- /dev/null +++ b/include/hw/elf_ops.h @@ -0,0 +1,393 @@ +static void glue(bswap_ehdr, SZ)(struct elfhdr *ehdr) +{ +    bswap16s(&ehdr->e_type);			/* Object file type */ +    bswap16s(&ehdr->e_machine);		/* Architecture */ +    bswap32s(&ehdr->e_version);		/* Object file version */ +    bswapSZs(&ehdr->e_entry);		/* Entry point virtual address */ +    bswapSZs(&ehdr->e_phoff);		/* Program header table file offset */ +    bswapSZs(&ehdr->e_shoff);		/* Section header table file offset */ +    bswap32s(&ehdr->e_flags);		/* Processor-specific flags */ +    bswap16s(&ehdr->e_ehsize);		/* ELF header size in bytes */ +    bswap16s(&ehdr->e_phentsize);		/* Program header table entry size */ +    bswap16s(&ehdr->e_phnum);		/* Program header table entry count */ +    bswap16s(&ehdr->e_shentsize);		/* Section header table entry size */ +    bswap16s(&ehdr->e_shnum);		/* Section header table entry count */ +    bswap16s(&ehdr->e_shstrndx);		/* Section header string table index */ +} + +static void glue(bswap_phdr, SZ)(struct elf_phdr *phdr) +{ +    bswap32s(&phdr->p_type);			/* Segment type */ +    bswapSZs(&phdr->p_offset);		/* Segment file offset */ +    bswapSZs(&phdr->p_vaddr);		/* Segment virtual address */ +    bswapSZs(&phdr->p_paddr);		/* Segment physical address */ +    bswapSZs(&phdr->p_filesz);		/* Segment size in file */ +    bswapSZs(&phdr->p_memsz);		/* Segment size in memory */ +    bswap32s(&phdr->p_flags);		/* Segment flags */ +    bswapSZs(&phdr->p_align);		/* Segment alignment */ +} + +static void glue(bswap_shdr, SZ)(struct elf_shdr *shdr) +{ +    bswap32s(&shdr->sh_name); +    bswap32s(&shdr->sh_type); +    bswapSZs(&shdr->sh_flags); +    bswapSZs(&shdr->sh_addr); +    bswapSZs(&shdr->sh_offset); +    bswapSZs(&shdr->sh_size); +    bswap32s(&shdr->sh_link); +    bswap32s(&shdr->sh_info); +    bswapSZs(&shdr->sh_addralign); +    bswapSZs(&shdr->sh_entsize); +} + +static void glue(bswap_sym, SZ)(struct elf_sym *sym) +{ +    bswap32s(&sym->st_name); +    bswapSZs(&sym->st_value); +    bswapSZs(&sym->st_size); +    bswap16s(&sym->st_shndx); +} + +static void glue(bswap_rela, SZ)(struct elf_rela *rela) +{ +    bswapSZs(&rela->r_offset); +    bswapSZs(&rela->r_info); +    bswapSZs((elf_word *)&rela->r_addend); +} + +static struct elf_shdr *glue(find_section, SZ)(struct elf_shdr *shdr_table, +                                               int n, int type) +{ +    int i; +    for(i=0;i<n;i++) { +        if (shdr_table[i].sh_type == type) +            return shdr_table + i; +    } +    return NULL; +} + +static int glue(symfind, SZ)(const void *s0, const void *s1) +{ +    hwaddr addr = *(hwaddr *)s0; +    struct elf_sym *sym = (struct elf_sym *)s1; +    int result = 0; +    if (addr < sym->st_value) { +        result = -1; +    } else if (addr >= sym->st_value + sym->st_size) { +        result = 1; +    } +    return result; +} + +static const char *glue(lookup_symbol, SZ)(struct syminfo *s, +                                           hwaddr orig_addr) +{ +    struct elf_sym *syms = glue(s->disas_symtab.elf, SZ); +    struct elf_sym *sym; + +    sym = bsearch(&orig_addr, syms, s->disas_num_syms, sizeof(*syms), +                  glue(symfind, SZ)); +    if (sym != NULL) { +        return s->disas_strtab + sym->st_name; +    } + +    return ""; +} + +static int glue(symcmp, SZ)(const void *s0, const void *s1) +{ +    struct elf_sym *sym0 = (struct elf_sym *)s0; +    struct elf_sym *sym1 = (struct elf_sym *)s1; +    return (sym0->st_value < sym1->st_value) +        ? -1 +        : ((sym0->st_value > sym1->st_value) ? 1 : 0); +} + +static int glue(load_symbols, SZ)(struct elfhdr *ehdr, int fd, int must_swab, +                                  int clear_lsb) +{ +    struct elf_shdr *symtab, *strtab, *shdr_table = NULL; +    struct elf_sym *syms = NULL; +    struct syminfo *s; +    int nsyms, i; +    char *str = NULL; + +    shdr_table = load_at(fd, ehdr->e_shoff, +                         sizeof(struct elf_shdr) * ehdr->e_shnum); +    if (!shdr_table) +        return -1; + +    if (must_swab) { +        for (i = 0; i < ehdr->e_shnum; i++) { +            glue(bswap_shdr, SZ)(shdr_table + i); +        } +    } + +    symtab = glue(find_section, SZ)(shdr_table, ehdr->e_shnum, SHT_SYMTAB); +    if (!symtab) +        goto fail; +    syms = load_at(fd, symtab->sh_offset, symtab->sh_size); +    if (!syms) +        goto fail; + +    nsyms = symtab->sh_size / sizeof(struct elf_sym); + +    i = 0; +    while (i < nsyms) { +        if (must_swab) +            glue(bswap_sym, SZ)(&syms[i]); +        /* We are only interested in function symbols. +           Throw everything else away.  */ +        if (syms[i].st_shndx == SHN_UNDEF || +                syms[i].st_shndx >= SHN_LORESERVE || +                ELF_ST_TYPE(syms[i].st_info) != STT_FUNC) { +            nsyms--; +            if (i < nsyms) { +                syms[i] = syms[nsyms]; +            } +            continue; +        } +        if (clear_lsb) { +            /* The bottom address bit marks a Thumb or MIPS16 symbol.  */ +            syms[i].st_value &= ~(glue(glue(Elf, SZ), _Addr))1; +        } +        i++; +    } +    syms = g_realloc(syms, nsyms * sizeof(*syms)); + +    qsort(syms, nsyms, sizeof(*syms), glue(symcmp, SZ)); +    for (i = 0; i < nsyms - 1; i++) { +        if (syms[i].st_size == 0) { +            syms[i].st_size = syms[i + 1].st_value - syms[i].st_value; +        } +    } + +    /* String table */ +    if (symtab->sh_link >= ehdr->e_shnum) +        goto fail; +    strtab = &shdr_table[symtab->sh_link]; + +    str = load_at(fd, strtab->sh_offset, strtab->sh_size); +    if (!str) +        goto fail; + +    /* Commit */ +    s = g_malloc0(sizeof(*s)); +    s->lookup_symbol = glue(lookup_symbol, SZ); +    glue(s->disas_symtab.elf, SZ) = syms; +    s->disas_num_syms = nsyms; +    s->disas_strtab = str; +    s->next = syminfos; +    syminfos = s; +    g_free(shdr_table); +    return 0; + fail: +    g_free(syms); +    g_free(str); +    g_free(shdr_table); +    return -1; +} + +static int glue(elf_reloc, SZ)(struct elfhdr *ehdr, int fd, int must_swab, +                               uint64_t (*translate_fn)(void *, uint64_t), +                               void *translate_opaque, uint8_t *data, +                               struct elf_phdr *ph, int elf_machine) +{ +    struct elf_shdr *reltab, *shdr_table = NULL; +    struct elf_rela *rels = NULL; +    int nrels, i, ret = -1; +    elf_word wordval; +    void *addr; + +    shdr_table = load_at(fd, ehdr->e_shoff, +                         sizeof(struct elf_shdr) * ehdr->e_shnum); +    if (!shdr_table) { +        return -1; +    } +    if (must_swab) { +        for (i = 0; i < ehdr->e_shnum; i++) { +            glue(bswap_shdr, SZ)(&shdr_table[i]); +        } +    } + +    reltab = glue(find_section, SZ)(shdr_table, ehdr->e_shnum, SHT_RELA); +    if (!reltab) { +        goto fail; +    } +    rels = load_at(fd, reltab->sh_offset, reltab->sh_size); +    if (!rels) { +        goto fail; +    } +    nrels = reltab->sh_size / sizeof(struct elf_rela); + +    for (i = 0; i < nrels; i++) { +        if (must_swab) { +            glue(bswap_rela, SZ)(&rels[i]); +        } +        if (rels[i].r_offset < ph->p_vaddr || +            rels[i].r_offset >= ph->p_vaddr + ph->p_filesz) { +            continue; +        } +        addr = &data[rels[i].r_offset - ph->p_vaddr]; +        switch (elf_machine) { +        case EM_S390: +            switch (rels[i].r_info) { +            case R_390_RELATIVE: +                wordval = *(elf_word *)addr; +                if (must_swab) { +                    bswapSZs(&wordval); +                } +                wordval = translate_fn(translate_opaque, wordval); +                if (must_swab) { +                    bswapSZs(&wordval); +                } +                *(elf_word *)addr = wordval; +                break; +            default: +                fprintf(stderr, "Unsupported relocation type %i!\n", +                        (int)rels[i].r_info); +            } +        } +    } + +    ret = 0; +fail: +    g_free(rels); +    g_free(shdr_table); +    return ret; +} + +static int glue(load_elf, SZ)(const char *name, int fd, +                              uint64_t (*translate_fn)(void *, uint64_t), +                              void *translate_opaque, +                              int must_swab, uint64_t *pentry, +                              uint64_t *lowaddr, uint64_t *highaddr, +                              int elf_machine, int clear_lsb) +{ +    struct elfhdr ehdr; +    struct elf_phdr *phdr = NULL, *ph; +    int size, i, total_size; +    elf_word mem_size, file_size; +    uint64_t addr, low = (uint64_t)-1, high = 0; +    uint8_t *data = NULL; +    char label[128]; +    int ret = ELF_LOAD_FAILED; + +    if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr)) +        goto fail; +    if (must_swab) { +        glue(bswap_ehdr, SZ)(&ehdr); +    } + +    switch (elf_machine) { +        case EM_PPC64: +            if (EM_PPC64 != ehdr.e_machine) +                if (EM_PPC != ehdr.e_machine) { +                    ret = ELF_LOAD_WRONG_ARCH; +                    goto fail; +                } +            break; +        case EM_X86_64: +            if (EM_X86_64 != ehdr.e_machine) +                if (EM_386 != ehdr.e_machine) { +                    ret = ELF_LOAD_WRONG_ARCH; +                    goto fail; +                } +            break; +        case EM_MICROBLAZE: +            if (EM_MICROBLAZE != ehdr.e_machine) +                if (EM_MICROBLAZE_OLD != ehdr.e_machine) { +                    ret = ELF_LOAD_WRONG_ARCH; +                    goto fail; +                } +            break; +        default: +            if (elf_machine != ehdr.e_machine) { +                ret = ELF_LOAD_WRONG_ARCH; +                goto fail; +            } +    } + +    if (pentry) +   	*pentry = (uint64_t)(elf_sword)ehdr.e_entry; + +    glue(load_symbols, SZ)(&ehdr, fd, must_swab, clear_lsb); + +    size = ehdr.e_phnum * sizeof(phdr[0]); +    if (lseek(fd, ehdr.e_phoff, SEEK_SET) != ehdr.e_phoff) { +        goto fail; +    } +    phdr = g_malloc0(size); +    if (!phdr) +        goto fail; +    if (read(fd, phdr, size) != size) +        goto fail; +    if (must_swab) { +        for(i = 0; i < ehdr.e_phnum; i++) { +            ph = &phdr[i]; +            glue(bswap_phdr, SZ)(ph); +        } +    } + +    total_size = 0; +    for(i = 0; i < ehdr.e_phnum; i++) { +        ph = &phdr[i]; +        if (ph->p_type == PT_LOAD) { +            mem_size = ph->p_memsz; /* Size of the ROM */ +            file_size = ph->p_filesz; /* Size of the allocated data */ +            data = g_malloc0(file_size); +            if (ph->p_filesz > 0) { +                if (lseek(fd, ph->p_offset, SEEK_SET) < 0) { +                    goto fail; +                } +                if (read(fd, data, file_size) != file_size) { +                    goto fail; +                } +            } +            /* address_offset is hack for kernel images that are +               linked at the wrong physical address.  */ +            if (translate_fn) { +                addr = translate_fn(translate_opaque, ph->p_paddr); +                glue(elf_reloc, SZ)(&ehdr, fd, must_swab,  translate_fn, +                                    translate_opaque, data, ph, elf_machine); +            } else { +                addr = ph->p_paddr; +            } + +            /* the entry pointer in the ELF header is a virtual +             * address, if the text segments paddr and vaddr differ +             * we need to adjust the entry */ +            if (pentry && !translate_fn && +                    ph->p_vaddr != ph->p_paddr && +                    ehdr.e_entry >= ph->p_vaddr && +                    ehdr.e_entry < ph->p_vaddr + ph->p_filesz && +                    ph->p_flags & PF_X) { +                *pentry = ehdr.e_entry - ph->p_vaddr + ph->p_paddr; +            } + +            snprintf(label, sizeof(label), "phdr #%d: %s", i, name); + +            /* rom_add_elf_program() seize the ownership of 'data' */ +            rom_add_elf_program(label, data, file_size, mem_size, addr); + +            total_size += mem_size; +            if (addr < low) +                low = addr; +            if ((addr + mem_size) > high) +                high = addr + mem_size; + +            data = NULL; +        } +    } +    g_free(phdr); +    if (lowaddr) +        *lowaddr = (uint64_t)(elf_sword)low; +    if (highaddr) +        *highaddr = (uint64_t)(elf_sword)high; +    return total_size; + fail: +    g_free(data); +    g_free(phdr); +    return ret; +} diff --git a/include/hw/empty_slot.h b/include/hw/empty_slot.h new file mode 100644 index 00000000..6079602c --- /dev/null +++ b/include/hw/empty_slot.h @@ -0,0 +1,7 @@ +#ifndef HW_EMPTY_SLOT_H +#define HW_EMPTY_SLOT_H 1 + +/* empty_slot.c */ +void empty_slot_init(hwaddr addr, uint64_t slot_size); + +#endif diff --git a/include/hw/fw-path-provider.h b/include/hw/fw-path-provider.h new file mode 100644 index 00000000..7afaec0b --- /dev/null +++ b/include/hw/fw-path-provider.h @@ -0,0 +1,48 @@ +/* + *  Firmware patch provider class and helpers definitions. + * + *  This program is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 2 of the License, + *  or (at your option) any later version. + * + *  This program is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef FW_PATH_PROVIDER_H +#define FW_PATH_PROVIDER_H 1 + +#include "qemu-common.h" +#include "qom/object.h" + +#define TYPE_FW_PATH_PROVIDER "fw-path-provider" + +#define FW_PATH_PROVIDER_CLASS(klass) \ +     OBJECT_CLASS_CHECK(FWPathProviderClass, (klass), TYPE_FW_PATH_PROVIDER) +#define FW_PATH_PROVIDER_GET_CLASS(obj) \ +    OBJECT_GET_CLASS(FWPathProviderClass, (obj), TYPE_FW_PATH_PROVIDER) +#define FW_PATH_PROVIDER(obj) \ +     INTERFACE_CHECK(FWPathProvider, (obj), TYPE_FW_PATH_PROVIDER) + +typedef struct FWPathProvider { +    Object parent_obj; +} FWPathProvider; + +typedef struct FWPathProviderClass { +    InterfaceClass parent_class; + +    char *(*get_dev_path)(FWPathProvider *p, BusState *bus, DeviceState *dev); +} FWPathProviderClass; + +char *fw_path_provider_get_dev_path(FWPathProvider *p, BusState *bus, +                                    DeviceState *dev); +char *fw_path_provider_try_get_dev_path(Object *o, BusState *bus, +                                        DeviceState *dev); + +#endif /* FW_PATH_PROVIDER_H */ diff --git a/include/hw/hotplug.h b/include/hw/hotplug.h new file mode 100644 index 00000000..2db025d0 --- /dev/null +++ b/include/hw/hotplug.h @@ -0,0 +1,92 @@ +/* + * Hotplug handler interface. + * + * Copyright (c) 2014 Red Hat Inc. + * + * Authors: + *  Igor Mammedov <imammedo@redhat.com>, + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ +#ifndef HOTPLUG_H +#define HOTPLUG_H + +#include "qom/object.h" +#include "qemu/typedefs.h" + +#define TYPE_HOTPLUG_HANDLER "hotplug-handler" + +#define HOTPLUG_HANDLER_CLASS(klass) \ +     OBJECT_CLASS_CHECK(HotplugHandlerClass, (klass), TYPE_HOTPLUG_HANDLER) +#define HOTPLUG_HANDLER_GET_CLASS(obj) \ +     OBJECT_GET_CLASS(HotplugHandlerClass, (obj), TYPE_HOTPLUG_HANDLER) +#define HOTPLUG_HANDLER(obj) \ +     INTERFACE_CHECK(HotplugHandler, (obj), TYPE_HOTPLUG_HANDLER) + + +typedef struct HotplugHandler { +    /* <private> */ +    Object Parent; +} HotplugHandler; + +/** + * hotplug_fn: + * @plug_handler: a device performing plug/uplug action + * @plugged_dev: a device that has been (un)plugged + * @errp: returns an error if this function fails + */ +typedef void (*hotplug_fn)(HotplugHandler *plug_handler, +                           DeviceState *plugged_dev, Error **errp); + +/** + * HotplugDeviceClass: + * + * Interface to be implemented by a device performing + * hardware (un)plug functions. + * + * @parent: Opaque parent interface. + * @plug: plug callback. + * @unplug_request: unplug request callback. + *                  Used as a means to initiate device unplug for devices that + *                  require asynchronous unplug handling. + * @unplug: unplug callback. + *          Used for device removal with devices that implement + *          asynchronous and synchronous (surprise) removal. + */ +typedef struct HotplugHandlerClass { +    /* <private> */ +    InterfaceClass parent; + +    /* <public> */ +    hotplug_fn plug; +    hotplug_fn unplug_request; +    hotplug_fn unplug; +} HotplugHandlerClass; + +/** + * hotplug_handler_plug: + * + * Call #HotplugHandlerClass.plug callback of @plug_handler. + */ +void hotplug_handler_plug(HotplugHandler *plug_handler, +                          DeviceState *plugged_dev, +                          Error **errp); + +/** + * hotplug_handler_unplug_request: + * + * Calls #HotplugHandlerClass.unplug_request callback of @plug_handler. + */ +void hotplug_handler_unplug_request(HotplugHandler *plug_handler, +                                    DeviceState *plugged_dev, +                                    Error **errp); +/** + * hotplug_handler_unplug: + * + * Calls #HotplugHandlerClass.unplug callback of @plug_handler. + */ +void hotplug_handler_unplug(HotplugHandler *plug_handler, +                            DeviceState *plugged_dev, +                            Error **errp); +#endif diff --git a/include/hw/hw.h b/include/hw/hw.h new file mode 100644 index 00000000..c78adae0 --- /dev/null +++ b/include/hw/hw.h @@ -0,0 +1,69 @@ +/* Declarations for use by hardware emulation.  */ +#ifndef QEMU_HW_H +#define QEMU_HW_H + +#include "qemu-common.h" + +#if !defined(CONFIG_USER_ONLY) && !defined(NEED_CPU_H) +#include "exec/cpu-common.h" +#endif + +#include "exec/ioport.h" +#include "hw/irq.h" +#include "block/aio.h" +#include "migration/vmstate.h" +#include "qemu/log.h" + +#ifdef NEED_CPU_H +#if TARGET_LONG_BITS == 64 +#define qemu_put_betl qemu_put_be64 +#define qemu_get_betl qemu_get_be64 +#define qemu_put_betls qemu_put_be64s +#define qemu_get_betls qemu_get_be64s +#define qemu_put_sbetl qemu_put_sbe64 +#define qemu_get_sbetl qemu_get_sbe64 +#define qemu_put_sbetls qemu_put_sbe64s +#define qemu_get_sbetls qemu_get_sbe64s +#else +#define qemu_put_betl qemu_put_be32 +#define qemu_get_betl qemu_get_be32 +#define qemu_put_betls qemu_put_be32s +#define qemu_get_betls qemu_get_be32s +#define qemu_put_sbetl qemu_put_sbe32 +#define qemu_get_sbetl qemu_get_sbe32 +#define qemu_put_sbetls qemu_put_sbe32s +#define qemu_get_sbetls qemu_get_sbe32s +#endif +#endif + +typedef void QEMUResetHandler(void *opaque); + +void qemu_register_reset(QEMUResetHandler *func, void *opaque); +void qemu_unregister_reset(QEMUResetHandler *func, void *opaque); + +#ifdef NEED_CPU_H +#if TARGET_LONG_BITS == 64 +#define VMSTATE_UINTTL_V(_f, _s, _v)                                  \ +    VMSTATE_UINT64_V(_f, _s, _v) +#define VMSTATE_UINTTL_EQUAL_V(_f, _s, _v)                            \ +    VMSTATE_UINT64_EQUAL_V(_f, _s, _v) +#define VMSTATE_UINTTL_ARRAY_V(_f, _s, _n, _v)                        \ +    VMSTATE_UINT64_ARRAY_V(_f, _s, _n, _v) +#else +#define VMSTATE_UINTTL_V(_f, _s, _v)                                  \ +    VMSTATE_UINT32_V(_f, _s, _v) +#define VMSTATE_UINTTL_EQUAL_V(_f, _s, _v)                            \ +    VMSTATE_UINT32_EQUAL_V(_f, _s, _v) +#define VMSTATE_UINTTL_ARRAY_V(_f, _s, _n, _v)                        \ +    VMSTATE_UINT32_ARRAY_V(_f, _s, _n, _v) +#endif +#define VMSTATE_UINTTL(_f, _s)                                        \ +    VMSTATE_UINTTL_V(_f, _s, 0) +#define VMSTATE_UINTTL_EQUAL(_f, _s)                                  \ +    VMSTATE_UINTTL_EQUAL_V(_f, _s, 0) +#define VMSTATE_UINTTL_ARRAY(_f, _s, _n)                              \ +    VMSTATE_UINTTL_ARRAY_V(_f, _s, _n, 0) + +#endif + +#endif diff --git a/include/hw/i2c/i2c.h b/include/hw/i2c/i2c.h new file mode 100644 index 00000000..4986ebc7 --- /dev/null +++ b/include/hw/i2c/i2c.h @@ -0,0 +1,86 @@ +#ifndef QEMU_I2C_H +#define QEMU_I2C_H + +#include "hw/qdev.h" + +/* The QEMU I2C implementation only supports simple transfers that complete +   immediately.  It does not support slave devices that need to be able to +   defer their response (eg. CPU slave interfaces where the data is supplied +   by the device driver in response to an interrupt).  */ + +enum i2c_event { +    I2C_START_RECV, +    I2C_START_SEND, +    I2C_FINISH, +    I2C_NACK /* Masker NACKed a receive byte.  */ +}; + +typedef struct I2CSlave I2CSlave; + +#define TYPE_I2C_SLAVE "i2c-slave" +#define I2C_SLAVE(obj) \ +     OBJECT_CHECK(I2CSlave, (obj), TYPE_I2C_SLAVE) +#define I2C_SLAVE_CLASS(klass) \ +     OBJECT_CLASS_CHECK(I2CSlaveClass, (klass), TYPE_I2C_SLAVE) +#define I2C_SLAVE_GET_CLASS(obj) \ +     OBJECT_GET_CLASS(I2CSlaveClass, (obj), TYPE_I2C_SLAVE) + +typedef struct I2CSlaveClass +{ +    DeviceClass parent_class; + +    /* Callbacks provided by the device.  */ +    int (*init)(I2CSlave *dev); + +    /* Master to slave.  */ +    int (*send)(I2CSlave *s, uint8_t data); + +    /* Slave to master.  */ +    int (*recv)(I2CSlave *s); + +    /* Notify the slave of a bus state change.  */ +    void (*event)(I2CSlave *s, enum i2c_event event); +} I2CSlaveClass; + +struct I2CSlave +{ +    DeviceState qdev; + +    /* Remaining fields for internal use by the I2C code.  */ +    uint8_t address; +}; + +I2CBus *i2c_init_bus(DeviceState *parent, const char *name); +void i2c_set_slave_address(I2CSlave *dev, uint8_t address); +int i2c_bus_busy(I2CBus *bus); +int i2c_start_transfer(I2CBus *bus, uint8_t address, int recv); +void i2c_end_transfer(I2CBus *bus); +void i2c_nack(I2CBus *bus); +int i2c_send(I2CBus *bus, uint8_t data); +int i2c_recv(I2CBus *bus); + +DeviceState *i2c_create_slave(I2CBus *bus, const char *name, uint8_t addr); + +/* wm8750.c */ +void wm8750_data_req_set(DeviceState *dev, +                void (*data_req)(void *, int, int), void *opaque); +void wm8750_dac_dat(void *opaque, uint32_t sample); +uint32_t wm8750_adc_dat(void *opaque); +void *wm8750_dac_buffer(void *opaque, int samples); +void wm8750_dac_commit(void *opaque); +void wm8750_set_bclk_in(void *opaque, int new_hz); + +/* lm832x.c */ +void lm832x_key_event(DeviceState *dev, int key, int state); + +extern const VMStateDescription vmstate_i2c_slave; + +#define VMSTATE_I2C_SLAVE(_field, _state) {                          \ +    .name       = (stringify(_field)),                               \ +    .size       = sizeof(I2CSlave),                                  \ +    .vmsd       = &vmstate_i2c_slave,                                \ +    .flags      = VMS_STRUCT,                                        \ +    .offset     = vmstate_offset_value(_state, _field, I2CSlave),    \ +} + +#endif diff --git a/include/hw/i2c/pm_smbus.h b/include/hw/i2c/pm_smbus.h new file mode 100644 index 00000000..926603fd --- /dev/null +++ b/include/hw/i2c/pm_smbus.h @@ -0,0 +1,20 @@ +#ifndef PM_SMBUS_H +#define PM_SMBUS_H + +typedef struct PMSMBus { +    I2CBus *smbus; +    MemoryRegion io; + +    uint8_t smb_stat; +    uint8_t smb_ctl; +    uint8_t smb_cmd; +    uint8_t smb_addr; +    uint8_t smb_data0; +    uint8_t smb_data1; +    uint8_t smb_data[32]; +    uint8_t smb_index; +} PMSMBus; + +void pm_smbus_init(DeviceState *parent, PMSMBus *smb); + +#endif /* !PM_SMBUS_H */ diff --git a/include/hw/i2c/smbus.h b/include/hw/i2c/smbus.h new file mode 100644 index 00000000..544bbc19 --- /dev/null +++ b/include/hw/i2c/smbus.h @@ -0,0 +1,83 @@ +#ifndef QEMU_SMBUS_H +#define QEMU_SMBUS_H + +/* + * QEMU SMBus API + * + * Copyright (c) 2007 Arastra, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * 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 OTHER + * 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 "hw/i2c/i2c.h" + +#define TYPE_SMBUS_DEVICE "smbus-device" +#define SMBUS_DEVICE(obj) \ +     OBJECT_CHECK(SMBusDevice, (obj), TYPE_SMBUS_DEVICE) +#define SMBUS_DEVICE_CLASS(klass) \ +     OBJECT_CLASS_CHECK(SMBusDeviceClass, (klass), TYPE_SMBUS_DEVICE) +#define SMBUS_DEVICE_GET_CLASS(obj) \ +     OBJECT_GET_CLASS(SMBusDeviceClass, (obj), TYPE_SMBUS_DEVICE) + +typedef struct SMBusDeviceClass +{ +    I2CSlaveClass parent_class; +    int (*init)(SMBusDevice *dev); +    void (*quick_cmd)(SMBusDevice *dev, uint8_t read); +    void (*send_byte)(SMBusDevice *dev, uint8_t val); +    uint8_t (*receive_byte)(SMBusDevice *dev); +    /* We can't distinguish between a word write and a block write with +       length 1, so pass the whole data block including the length byte +       (if present).  The device is responsible figuring out what type of +       command  this is.  */ +    void (*write_data)(SMBusDevice *dev, uint8_t cmd, uint8_t *buf, int len); +    /* Likewise we can't distinguish between different reads, or even know +       the length of the read until the read is complete, so read data a +       byte at a time.  The device is responsible for adding the length +       byte on block reads.  */ +    uint8_t (*read_data)(SMBusDevice *dev, uint8_t cmd, int n); +} SMBusDeviceClass; + +struct SMBusDevice { +    /* The SMBus protocol is implemented on top of I2C.  */ +    I2CSlave i2c; + +    /* Remaining fields for internal use only.  */ +    int mode; +    int data_len; +    uint8_t data_buf[34]; /* command + len + 32 bytes of data.  */ +    uint8_t command; +}; + +/* Master device commands.  */ +int smbus_quick_command(I2CBus *bus, uint8_t addr, int read); +int smbus_receive_byte(I2CBus *bus, uint8_t addr); +int smbus_send_byte(I2CBus *bus, uint8_t addr, uint8_t data); +int smbus_read_byte(I2CBus *bus, uint8_t addr, uint8_t command); +int smbus_write_byte(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t data); +int smbus_read_word(I2CBus *bus, uint8_t addr, uint8_t command); +int smbus_write_word(I2CBus *bus, uint8_t addr, uint8_t command, uint16_t data); +int smbus_read_block(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t *data); +int smbus_write_block(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t *data, +                      int len); + +void smbus_eeprom_init(I2CBus *smbus, int nb_eeprom, +                       const uint8_t *eeprom_spd, int size); + +#endif diff --git a/include/hw/i386/apic-msidef.h b/include/hw/i386/apic-msidef.h new file mode 100644 index 00000000..6e2eb71f --- /dev/null +++ b/include/hw/i386/apic-msidef.h @@ -0,0 +1,30 @@ +#ifndef HW_APIC_MSIDEF_H +#define HW_APIC_MSIDEF_H + +/* + * Intel APIC constants: from include/asm/msidef.h + */ + +/* + * Shifts for MSI data + */ + +#define MSI_DATA_VECTOR_SHIFT           0 +#define  MSI_DATA_VECTOR_MASK           0x000000ff + +#define MSI_DATA_DELIVERY_MODE_SHIFT    8 +#define MSI_DATA_LEVEL_SHIFT            14 +#define MSI_DATA_TRIGGER_SHIFT          15 + +/* + * Shift/mask fields for msi address + */ + +#define MSI_ADDR_DEST_MODE_SHIFT        2 + +#define MSI_ADDR_REDIRECTION_SHIFT      3 + +#define MSI_ADDR_DEST_ID_SHIFT          12 +#define  MSI_ADDR_DEST_ID_MASK          0x00ffff0 + +#endif /* HW_APIC_MSIDEF_H */ diff --git a/include/hw/i386/apic.h b/include/hw/i386/apic.h new file mode 100644 index 00000000..51eb6d38 --- /dev/null +++ b/include/hw/i386/apic.h @@ -0,0 +1,32 @@ +#ifndef APIC_H +#define APIC_H + +#include "qemu-common.h" + +/* apic.c */ +void apic_deliver_irq(uint8_t dest, uint8_t dest_mode, uint8_t delivery_mode, +                      uint8_t vector_num, uint8_t trigger_mode); +int apic_accept_pic_intr(DeviceState *s); +void apic_deliver_pic_intr(DeviceState *s, int level); +void apic_deliver_nmi(DeviceState *d); +int apic_get_interrupt(DeviceState *s); +void apic_reset_irq_delivered(void); +int apic_get_irq_delivered(void); +void cpu_set_apic_base(DeviceState *s, uint64_t val); +uint64_t cpu_get_apic_base(DeviceState *s); +void cpu_set_apic_tpr(DeviceState *s, uint8_t val); +uint8_t cpu_get_apic_tpr(DeviceState *s); +void apic_init_reset(DeviceState *s); +void apic_sipi(DeviceState *s); +void apic_handle_tpr_access_report(DeviceState *d, target_ulong ip, +                                   TPRAccess access); +void apic_poll_irq(DeviceState *d); +void apic_designate_bsp(DeviceState *d, bool bsp); + +/* pc.c */ +DeviceState *cpu_get_current_apic(void); + +/* cpu.c */ +bool cpu_is_bsp(X86CPU *cpu); + +#endif diff --git a/include/hw/i386/apic_internal.h b/include/hw/i386/apic_internal.h new file mode 100644 index 00000000..dc7a89d9 --- /dev/null +++ b/include/hw/i386/apic_internal.h @@ -0,0 +1,149 @@ +/* + *  APIC support - internal interfaces + * + *  Copyright (c) 2004-2005 Fabrice Bellard + *  Copyright (c) 2011      Jan Kiszka, Siemens AG + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/> + */ +#ifndef QEMU_APIC_INTERNAL_H +#define QEMU_APIC_INTERNAL_H + +#include "exec/memory.h" +#include "hw/cpu/icc_bus.h" +#include "qemu/timer.h" + +/* APIC Local Vector Table */ +#define APIC_LVT_TIMER                  0 +#define APIC_LVT_THERMAL                1 +#define APIC_LVT_PERFORM                2 +#define APIC_LVT_LINT0                  3 +#define APIC_LVT_LINT1                  4 +#define APIC_LVT_ERROR                  5 +#define APIC_LVT_NB                     6 + +/* APIC delivery modes */ +#define APIC_DM_FIXED                   0 +#define APIC_DM_LOWPRI                  1 +#define APIC_DM_SMI                     2 +#define APIC_DM_NMI                     4 +#define APIC_DM_INIT                    5 +#define APIC_DM_SIPI                    6 +#define APIC_DM_EXTINT                  7 + +/* APIC destination mode */ +#define APIC_DESTMODE_FLAT              0xf +#define APIC_DESTMODE_CLUSTER           1 + +#define APIC_TRIGGER_EDGE               0 +#define APIC_TRIGGER_LEVEL              1 + +#define APIC_LVT_TIMER_PERIODIC         (1<<17) +#define APIC_LVT_MASKED                 (1<<16) +#define APIC_LVT_LEVEL_TRIGGER          (1<<15) +#define APIC_LVT_REMOTE_IRR             (1<<14) +#define APIC_INPUT_POLARITY             (1<<13) +#define APIC_SEND_PENDING               (1<<12) + +#define ESR_ILLEGAL_ADDRESS (1 << 7) + +#define APIC_SV_DIRECTED_IO             (1<<12) +#define APIC_SV_ENABLE                  (1<<8) + +#define VAPIC_ENABLE_BIT                0 +#define VAPIC_ENABLE_MASK               (1 << VAPIC_ENABLE_BIT) + +#define MAX_APICS 255 + +typedef struct APICCommonState APICCommonState; + +#define TYPE_APIC_COMMON "apic-common" +#define APIC_COMMON(obj) \ +     OBJECT_CHECK(APICCommonState, (obj), TYPE_APIC_COMMON) +#define APIC_COMMON_CLASS(klass) \ +     OBJECT_CLASS_CHECK(APICCommonClass, (klass), TYPE_APIC_COMMON) +#define APIC_COMMON_GET_CLASS(obj) \ +     OBJECT_GET_CLASS(APICCommonClass, (obj), TYPE_APIC_COMMON) + +typedef struct APICCommonClass +{ +    ICCDeviceClass parent_class; + +    DeviceRealize realize; +    void (*set_base)(APICCommonState *s, uint64_t val); +    void (*set_tpr)(APICCommonState *s, uint8_t val); +    uint8_t (*get_tpr)(APICCommonState *s); +    void (*enable_tpr_reporting)(APICCommonState *s, bool enable); +    void (*vapic_base_update)(APICCommonState *s); +    void (*external_nmi)(APICCommonState *s); +    void (*pre_save)(APICCommonState *s); +    void (*post_load)(APICCommonState *s); +    void (*reset)(APICCommonState *s); +} APICCommonClass; + +struct APICCommonState { +    ICCDevice busdev; + +    MemoryRegion io_memory; +    X86CPU *cpu; +    uint32_t apicbase; +    uint8_t id; +    uint8_t version; +    uint8_t arb_id; +    uint8_t tpr; +    uint32_t spurious_vec; +    uint8_t log_dest; +    uint8_t dest_mode; +    uint32_t isr[8];  /* in service register */ +    uint32_t tmr[8];  /* trigger mode register */ +    uint32_t irr[8]; /* interrupt request register */ +    uint32_t lvt[APIC_LVT_NB]; +    uint32_t esr; /* error register */ +    uint32_t icr[2]; + +    uint32_t divide_conf; +    int count_shift; +    uint32_t initial_count; +    int64_t initial_count_load_time; +    int64_t next_time; +    int idx; +    QEMUTimer *timer; +    int64_t timer_expiry; +    int sipi_vector; +    int wait_for_sipi; + +    uint32_t vapic_control; +    DeviceState *vapic; +    hwaddr vapic_paddr; /* note: persistence via kvmvapic */ +}; + +typedef struct VAPICState { +    uint8_t tpr; +    uint8_t isr; +    uint8_t zero; +    uint8_t irr; +    uint8_t enabled; +} QEMU_PACKED VAPICState; + +extern bool apic_report_tpr_access; + +void apic_report_irq_delivered(int delivered); +bool apic_next_timer(APICCommonState *s, int64_t current_time); +void apic_enable_tpr_access_reporting(DeviceState *d, bool enable); +void apic_enable_vapic(DeviceState *d, hwaddr paddr); + +void vapic_report_tpr_access(DeviceState *dev, CPUState *cpu, target_ulong ip, +                             TPRAccess access); + +#endif /* !QEMU_APIC_INTERNAL_H */ diff --git a/include/hw/i386/ich9.h b/include/hw/i386/ich9.h new file mode 100644 index 00000000..b9d2b04b --- /dev/null +++ b/include/hw/i386/ich9.h @@ -0,0 +1,239 @@ +#ifndef HW_ICH9_H +#define HW_ICH9_H + +#include "hw/hw.h" +#include "hw/isa/isa.h" +#include "hw/sysbus.h" +#include "hw/i386/pc.h" +#include "hw/isa/apm.h" +#include "hw/i386/ioapic.h" +#include "hw/pci/pci.h" +#include "hw/pci/pcie_host.h" +#include "hw/pci/pci_bridge.h" +#include "hw/acpi/acpi.h" +#include "hw/acpi/ich9.h" +#include "hw/pci/pci_bus.h" + +void ich9_lpc_set_irq(void *opaque, int irq_num, int level); +int ich9_lpc_map_irq(PCIDevice *pci_dev, int intx); +PCIINTxRoute ich9_route_intx_pin_to_irq(void *opaque, int pirq_pin); +void ich9_lpc_pm_init(PCIDevice *pci_lpc, bool smm_enabled, bool enable_tco); +I2CBus *ich9_smb_init(PCIBus *bus, int devfn, uint32_t smb_io_base); + +void ich9_generate_smi(void); +void ich9_generate_nmi(void); + +#define ICH9_CC_SIZE                            (16 * 1024)     /* 16KB */ + +#define TYPE_ICH9_LPC_DEVICE "ICH9-LPC" +#define ICH9_LPC_DEVICE(obj) \ +     OBJECT_CHECK(ICH9LPCState, (obj), TYPE_ICH9_LPC_DEVICE) + +typedef struct ICH9LPCState { +    /* ICH9 LPC PCI to ISA bridge */ +    PCIDevice d; + +    /* (pci device, intx) -> pirq +     * In real chipset case, the unused slots are never used +     * as ICH9 supports only D25-D32 irq routing. +     * On the other hand in qemu case, any slot/function can be populated +     * via command line option. +     * So fallback interrupt routing for any devices in any slots is necessary. +    */ +    uint8_t irr[PCI_SLOT_MAX][PCI_NUM_PINS]; + +    APMState apm; +    ICH9LPCPMRegs pm; +    uint32_t sci_level; /* track sci level */ + +    /* 2.24 Pin Straps */ +    struct { +        bool spkr_hi; +    } pin_strap; + +    /* 10.1 Chipset Configuration registers(Memory Space) +     which is pointed by RCBA */ +    uint8_t chip_config[ICH9_CC_SIZE]; + +    /* +     * 13.7.5 RST_CNT---Reset Control Register (LPC I/F---D31:F0) +     * +     * register contents and IO memory region +     */ +    uint8_t rst_cnt; +    MemoryRegion rst_cnt_mem; + +    /* isa bus */ +    ISABus *isa_bus; +    MemoryRegion rbca_mem; +    Notifier machine_ready; + +    qemu_irq *pic; +    qemu_irq *ioapic; +} ICH9LPCState; + +Object *ich9_lpc_find(void); + +#define Q35_MASK(bit, ms_bit, ls_bit) \ +((uint##bit##_t)(((1ULL << ((ms_bit) + 1)) - 1) & ~((1ULL << ls_bit) - 1))) + +/* ICH9: Chipset Configuration Registers */ +#define ICH9_CC_ADDR_MASK                       (ICH9_CC_SIZE - 1) + +#define ICH9_CC +#define ICH9_CC_D28IP                           0x310C +#define ICH9_CC_D28IP_SHIFT                     4 +#define ICH9_CC_D28IP_MASK                      0xf +#define ICH9_CC_D28IP_DEFAULT                   0x00214321 +#define ICH9_CC_D31IR                           0x3140 +#define ICH9_CC_D30IR                           0x3142 +#define ICH9_CC_D29IR                           0x3144 +#define ICH9_CC_D28IR                           0x3146 +#define ICH9_CC_D27IR                           0x3148 +#define ICH9_CC_D26IR                           0x314C +#define ICH9_CC_D25IR                           0x3150 +#define ICH9_CC_DIR_DEFAULT                     0x3210 +#define ICH9_CC_D30IR_DEFAULT                   0x0 +#define ICH9_CC_DIR_SHIFT                       4 +#define ICH9_CC_DIR_MASK                        0x7 +#define ICH9_CC_OIC                             0x31FF +#define ICH9_CC_OIC_AEN                         0x1 +#define ICH9_CC_GCS                             0x3410 +#define ICH9_CC_GCS_DEFAULT                     0x00000020 +#define ICH9_CC_GCS_NO_REBOOT                   (1 << 5) + +/* D28:F[0-5] */ +#define ICH9_PCIE_DEV                           28 +#define ICH9_PCIE_FUNC_MAX                      6 + + +/* D29:F0 USB UHCI Controller #1 */ +#define ICH9_USB_UHCI1_DEV                      29 +#define ICH9_USB_UHCI1_FUNC                     0 + +/* D30:F0 DMI-to-PCI bridge */ +#define ICH9_D2P_BRIDGE                         "ICH9 D2P BRIDGE" +#define ICH9_D2P_BRIDGE_SAVEVM_VERSION          0 + +#define ICH9_D2P_BRIDGE_DEV                     30 +#define ICH9_D2P_BRIDGE_FUNC                    0 + +#define ICH9_D2P_SECONDARY_DEFAULT              (256 - 8) + +#define ICH9_D2P_A2_REVISION                    0x92 + +/* D31:F0 LPC Processor Interface */ +#define ICH9_RST_CNT_IOPORT                     0xCF9 + +/* D31:F1 LPC controller */ +#define ICH9_A2_LPC                             "ICH9 A2 LPC" +#define ICH9_A2_LPC_SAVEVM_VERSION              0 + +#define ICH9_LPC_DEV                            31 +#define ICH9_LPC_FUNC                           0 + +#define ICH9_A2_LPC_REVISION                    0x2 +#define ICH9_LPC_NB_PIRQS                       8       /* PCI A-H */ + +#define ICH9_LPC_PMBASE                         0x40 +#define ICH9_LPC_PMBASE_BASE_ADDRESS_MASK       Q35_MASK(32, 15, 7) +#define ICH9_LPC_PMBASE_RTE                     0x1 +#define ICH9_LPC_PMBASE_DEFAULT                 0x1 +#define ICH9_LPC_ACPI_CTRL                      0x44 +#define ICH9_LPC_ACPI_CTRL_ACPI_EN              0x80 +#define ICH9_LPC_ACPI_CTRL_SCI_IRQ_SEL_MASK     Q35_MASK(8, 2, 0) +#define ICH9_LPC_ACPI_CTRL_9                    0x0 +#define ICH9_LPC_ACPI_CTRL_10                   0x1 +#define ICH9_LPC_ACPI_CTRL_11                   0x2 +#define ICH9_LPC_ACPI_CTRL_20                   0x4 +#define ICH9_LPC_ACPI_CTRL_21                   0x5 +#define ICH9_LPC_ACPI_CTRL_DEFAULT              0x0 + +#define ICH9_LPC_PIRQA_ROUT                     0x60 +#define ICH9_LPC_PIRQB_ROUT                     0x61 +#define ICH9_LPC_PIRQC_ROUT                     0x62 +#define ICH9_LPC_PIRQD_ROUT                     0x63 + +#define ICH9_LPC_PIRQE_ROUT                     0x68 +#define ICH9_LPC_PIRQF_ROUT                     0x69 +#define ICH9_LPC_PIRQG_ROUT                     0x6a +#define ICH9_LPC_PIRQH_ROUT                     0x6b + +#define ICH9_LPC_PIRQ_ROUT_IRQEN                0x80 +#define ICH9_LPC_PIRQ_ROUT_MASK                 Q35_MASK(8, 3, 0) +#define ICH9_LPC_PIRQ_ROUT_DEFAULT              0x80 + +#define ICH9_LPC_GEN_PMCON_1                    0xa0 +#define ICH9_LPC_GEN_PMCON_1_SMI_LOCK           (1 << 4) +#define ICH9_LPC_GEN_PMCON_2                    0xa2 +#define ICH9_LPC_GEN_PMCON_3                    0xa4 +#define ICH9_LPC_GEN_PMCON_LOCK                 0xa6 + +#define ICH9_LPC_RCBA                           0xf0 +#define ICH9_LPC_RCBA_BA_MASK                   Q35_MASK(32, 31, 14) +#define ICH9_LPC_RCBA_EN                        0x1 +#define ICH9_LPC_RCBA_DEFAULT                   0x0 + +#define ICH9_LPC_PIC_NUM_PINS                   16 +#define ICH9_LPC_IOAPIC_NUM_PINS                24 + +/* D31:F2 SATA Controller #1 */ +#define ICH9_SATA1_DEV                          31 +#define ICH9_SATA1_FUNC                         2 + +/* D30:F1 power management I/O registers +   offset from the address ICH9_LPC_PMBASE */ + +/* ICH9 LPC PM I/O registers are 128 ports and 128-aligned */ +#define ICH9_PMIO_SIZE                          128 +#define ICH9_PMIO_MASK                          (ICH9_PMIO_SIZE - 1) + +#define ICH9_PMIO_PM1_STS                       0x00 +#define ICH9_PMIO_PM1_EN                        0x02 +#define ICH9_PMIO_PM1_CNT                       0x04 +#define ICH9_PMIO_PM1_TMR                       0x08 +#define ICH9_PMIO_GPE0_STS                      0x20 +#define ICH9_PMIO_GPE0_EN                       0x28 +#define ICH9_PMIO_GPE0_LEN                      16 +#define ICH9_PMIO_SMI_EN                        0x30 +#define ICH9_PMIO_SMI_EN_APMC_EN                (1 << 5) +#define ICH9_PMIO_SMI_EN_TCO_EN                 (1 << 13) +#define ICH9_PMIO_SMI_STS                       0x34 +#define ICH9_PMIO_TCO_RLD                       0x60 +#define ICH9_PMIO_TCO_LEN                       32 + +/* FADT ACPI_ENABLE/ACPI_DISABLE */ +#define ICH9_APM_ACPI_ENABLE                    0x2 +#define ICH9_APM_ACPI_DISABLE                   0x3 + + +/* D31:F3 SMBus controller */ +#define ICH9_A2_SMB_REVISION                    0x02 +#define ICH9_SMB_PI                             0x00 + +#define ICH9_SMB_SMBMBAR0                       0x10 +#define ICH9_SMB_SMBMBAR1                       0x14 +#define ICH9_SMB_SMBM_BAR                       0 +#define ICH9_SMB_SMBM_SIZE                      (1 << 8) +#define ICH9_SMB_SMB_BASE                       0x20 +#define ICH9_SMB_SMB_BASE_BAR                   4 +#define ICH9_SMB_SMB_BASE_SIZE                  (1 << 5) +#define ICH9_SMB_HOSTC                          0x40 +#define ICH9_SMB_HOSTC_SSRESET                  ((uint8_t)(1 << 3)) +#define ICH9_SMB_HOSTC_I2C_EN                   ((uint8_t)(1 << 2)) +#define ICH9_SMB_HOSTC_SMB_SMI_EN               ((uint8_t)(1 << 1)) +#define ICH9_SMB_HOSTC_HST_EN                   ((uint8_t)(1 << 0)) + +/* D31:F3 SMBus I/O and memory mapped I/O registers */ +#define ICH9_SMB_DEV                            31 +#define ICH9_SMB_FUNC                           3 + +#define ICH9_SMB_HST_STS                        0x00 +#define ICH9_SMB_HST_CNT                        0x02 +#define ICH9_SMB_HST_CMD                        0x03 +#define ICH9_SMB_XMIT_SLVA                      0x04 +#define ICH9_SMB_HST_D0                         0x05 +#define ICH9_SMB_HST_D1                         0x06 +#define ICH9_SMB_HOST_BLOCK_DB                  0x07 + +#endif /* HW_ICH9_H */ diff --git a/include/hw/i386/intel_iommu.h b/include/hw/i386/intel_iommu.h new file mode 100644 index 00000000..e321ee4f --- /dev/null +++ b/include/hw/i386/intel_iommu.h @@ -0,0 +1,120 @@ +/* + * QEMU emulation of an Intel IOMMU (VT-d) + *   (DMA Remapping device) + * + * Copyright (C) 2013 Knut Omang, Oracle <knut.omang@oracle.com> + * Copyright (C) 2014 Le Tan, <tamlokveer@gmail.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along + * with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef INTEL_IOMMU_H +#define INTEL_IOMMU_H +#include "hw/qdev.h" +#include "sysemu/dma.h" + +#define TYPE_INTEL_IOMMU_DEVICE "intel-iommu" +#define INTEL_IOMMU_DEVICE(obj) \ +     OBJECT_CHECK(IntelIOMMUState, (obj), TYPE_INTEL_IOMMU_DEVICE) + +/* DMAR Hardware Unit Definition address (IOMMU unit) */ +#define Q35_HOST_BRIDGE_IOMMU_ADDR  0xfed90000ULL + +#define VTD_PCI_BUS_MAX             256 +#define VTD_PCI_SLOT_MAX            32 +#define VTD_PCI_FUNC_MAX            8 +#define VTD_PCI_DEVFN_MAX           256 +#define VTD_PCI_SLOT(devfn)         (((devfn) >> 3) & 0x1f) +#define VTD_PCI_FUNC(devfn)         ((devfn) & 0x07) +#define VTD_SID_TO_BUS(sid)         (((sid) >> 8) & 0xff) +#define VTD_SID_TO_DEVFN(sid)       ((sid) & 0xff) + +#define DMAR_REG_SIZE               0x230 +#define VTD_HOST_ADDRESS_WIDTH      39 +#define VTD_HAW_MASK                ((1ULL << VTD_HOST_ADDRESS_WIDTH) - 1) + +typedef struct VTDContextEntry VTDContextEntry; +typedef struct VTDContextCacheEntry VTDContextCacheEntry; +typedef struct IntelIOMMUState IntelIOMMUState; +typedef struct VTDAddressSpace VTDAddressSpace; +typedef struct VTDIOTLBEntry VTDIOTLBEntry; + +/* Context-Entry */ +struct VTDContextEntry { +    uint64_t lo; +    uint64_t hi; +}; + +struct VTDContextCacheEntry { +    /* The cache entry is obsolete if +     * context_cache_gen!=IntelIOMMUState.context_cache_gen +     */ +    uint32_t context_cache_gen; +    struct VTDContextEntry context_entry; +}; + +struct VTDAddressSpace { +    uint8_t bus_num; +    uint8_t devfn; +    AddressSpace as; +    MemoryRegion iommu; +    IntelIOMMUState *iommu_state; +    VTDContextCacheEntry context_cache_entry; +}; + +struct VTDIOTLBEntry { +    uint64_t gfn; +    uint16_t domain_id; +    uint64_t slpte; +    bool read_flags; +    bool write_flags; +}; + +/* The iommu (DMAR) device state struct */ +struct IntelIOMMUState { +    SysBusDevice busdev; +    MemoryRegion csrmem; +    uint8_t csr[DMAR_REG_SIZE];     /* register values */ +    uint8_t wmask[DMAR_REG_SIZE];   /* R/W bytes */ +    uint8_t w1cmask[DMAR_REG_SIZE]; /* RW1C(Write 1 to Clear) bytes */ +    uint8_t womask[DMAR_REG_SIZE];  /* WO (write only - read returns 0) */ +    uint32_t version; + +    dma_addr_t root;                /* Current root table pointer */ +    bool root_extended;             /* Type of root table (extended or not) */ +    bool dmar_enabled;              /* Set if DMA remapping is enabled */ + +    uint16_t iq_head;               /* Current invalidation queue head */ +    uint16_t iq_tail;               /* Current invalidation queue tail */ +    dma_addr_t iq;                  /* Current invalidation queue pointer */ +    uint16_t iq_size;               /* IQ Size in number of entries */ +    bool qi_enabled;                /* Set if the QI is enabled */ +    uint8_t iq_last_desc_type;      /* The type of last completed descriptor */ + +    /* The index of the Fault Recording Register to be used next. +     * Wraps around from N-1 to 0, where N is the number of FRCD_REG. +     */ +    uint16_t next_frcd_reg; + +    uint64_t cap;                   /* The value of capability reg */ +    uint64_t ecap;                  /* The value of extended capability reg */ + +    uint32_t context_cache_gen;     /* Should be in [1,MAX] */ +    GHashTable *iotlb;              /* IOTLB */ + +    MemoryRegionIOMMUOps iommu_ops; +    VTDAddressSpace **address_spaces[VTD_PCI_BUS_MAX]; +}; + +#endif diff --git a/include/hw/i386/ioapic.h b/include/hw/i386/ioapic.h new file mode 100644 index 00000000..6245388c --- /dev/null +++ b/include/hw/i386/ioapic.h @@ -0,0 +1,28 @@ +/* + *  ioapic.c IOAPIC emulation logic + * + *  Copyright (c) 2011 Jan Kiszka, Siemens AG + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef HW_IOAPIC_H +#define HW_IOAPIC_H + +#define IOAPIC_NUM_PINS 24 +#define IO_APIC_DEFAULT_ADDRESS 0xfec00000 + +void ioapic_eoi_broadcast(int vector); + +#endif /* !HW_IOAPIC_H */ diff --git a/include/hw/i386/ioapic_internal.h b/include/hw/i386/ioapic_internal.h new file mode 100644 index 00000000..3be33521 --- /dev/null +++ b/include/hw/i386/ioapic_internal.h @@ -0,0 +1,103 @@ +/* + *  IOAPIC emulation logic - internal interfaces + * + *  Copyright (c) 2004-2005 Fabrice Bellard + *  Copyright (c) 2009      Xiantao Zhang, Intel + *  Copyright (c) 2011 Jan Kiszka, Siemens AG + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef QEMU_IOAPIC_INTERNAL_H +#define QEMU_IOAPIC_INTERNAL_H + +#include "hw/hw.h" +#include "exec/memory.h" +#include "hw/sysbus.h" + +#define MAX_IOAPICS                     1 + +#define IOAPIC_VERSION                  0x11 + +#define IOAPIC_LVT_DEST_SHIFT           56 +#define IOAPIC_LVT_MASKED_SHIFT         16 +#define IOAPIC_LVT_TRIGGER_MODE_SHIFT   15 +#define IOAPIC_LVT_REMOTE_IRR_SHIFT     14 +#define IOAPIC_LVT_POLARITY_SHIFT       13 +#define IOAPIC_LVT_DELIV_STATUS_SHIFT   12 +#define IOAPIC_LVT_DEST_MODE_SHIFT      11 +#define IOAPIC_LVT_DELIV_MODE_SHIFT     8 + +#define IOAPIC_LVT_MASKED               (1 << IOAPIC_LVT_MASKED_SHIFT) +#define IOAPIC_LVT_REMOTE_IRR           (1 << IOAPIC_LVT_REMOTE_IRR_SHIFT) + +#define IOAPIC_TRIGGER_EDGE             0 +#define IOAPIC_TRIGGER_LEVEL            1 + +/*io{apic,sapic} delivery mode*/ +#define IOAPIC_DM_FIXED                 0x0 +#define IOAPIC_DM_LOWEST_PRIORITY       0x1 +#define IOAPIC_DM_PMI                   0x2 +#define IOAPIC_DM_NMI                   0x4 +#define IOAPIC_DM_INIT                  0x5 +#define IOAPIC_DM_SIPI                  0x6 +#define IOAPIC_DM_EXTINT                0x7 +#define IOAPIC_DM_MASK                  0x7 + +#define IOAPIC_VECTOR_MASK              0xff + +#define IOAPIC_IOREGSEL                 0x00 +#define IOAPIC_IOWIN                    0x10 + +#define IOAPIC_REG_ID                   0x00 +#define IOAPIC_REG_VER                  0x01 +#define IOAPIC_REG_ARB                  0x02 +#define IOAPIC_REG_REDTBL_BASE          0x10 +#define IOAPIC_ID                       0x00 + +#define IOAPIC_ID_SHIFT                 24 +#define IOAPIC_ID_MASK                  0xf + +#define IOAPIC_VER_ENTRIES_SHIFT        16 + +typedef struct IOAPICCommonState IOAPICCommonState; + +#define TYPE_IOAPIC_COMMON "ioapic-common" +#define IOAPIC_COMMON(obj) \ +     OBJECT_CHECK(IOAPICCommonState, (obj), TYPE_IOAPIC_COMMON) +#define IOAPIC_COMMON_CLASS(klass) \ +     OBJECT_CLASS_CHECK(IOAPICCommonClass, (klass), TYPE_IOAPIC_COMMON) +#define IOAPIC_COMMON_GET_CLASS(obj) \ +     OBJECT_GET_CLASS(IOAPICCommonClass, (obj), TYPE_IOAPIC_COMMON) + +typedef struct IOAPICCommonClass { +    SysBusDeviceClass parent_class; + +    DeviceRealize realize; +    void (*pre_save)(IOAPICCommonState *s); +    void (*post_load)(IOAPICCommonState *s); +} IOAPICCommonClass; + +struct IOAPICCommonState { +    SysBusDevice busdev; +    MemoryRegion io_memory; +    uint8_t id; +    uint8_t ioregsel; +    uint32_t irr; +    uint64_t ioredtbl[IOAPIC_NUM_PINS]; +}; + +void ioapic_reset_common(DeviceState *dev); + +#endif /* !QEMU_IOAPIC_INTERNAL_H */ diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h new file mode 100644 index 00000000..954203d2 --- /dev/null +++ b/include/hw/i386/pc.h @@ -0,0 +1,633 @@ +#ifndef HW_PC_H +#define HW_PC_H + +#include "qemu-common.h" +#include "exec/memory.h" +#include "hw/boards.h" +#include "hw/isa/isa.h" +#include "hw/block/fdc.h" +#include "net/net.h" +#include "hw/i386/ioapic.h" + +#include "qemu/range.h" +#include "qemu/bitmap.h" +#include "sysemu/sysemu.h" +#include "hw/pci/pci.h" +#include "hw/boards.h" +#include "hw/compat.h" +#include "hw/mem/pc-dimm.h" + +#define HPET_INTCAP "hpet-intcap" + +/** + * PCMachineState: + * @acpi_dev: link to ACPI PM device that performs ACPI hotplug handling + * @enforce_aligned_dimm: check that DIMM's address/size is aligned by + *                        backend's alignment value if provided + */ +struct PCMachineState { +    /*< private >*/ +    MachineState parent_obj; + +    /* <public> */ +    MemoryHotplugState hotplug_memory; + +    HotplugHandler *acpi_dev; +    ISADevice *rtc; + +    uint64_t max_ram_below_4g; +    OnOffAuto vmport; +    OnOffAuto smm; +    bool enforce_aligned_dimm; +}; + +#define PC_MACHINE_ACPI_DEVICE_PROP "acpi-device" +#define PC_MACHINE_MEMHP_REGION_SIZE "hotplug-memory-region-size" +#define PC_MACHINE_MAX_RAM_BELOW_4G "max-ram-below-4g" +#define PC_MACHINE_VMPORT           "vmport" +#define PC_MACHINE_SMM              "smm" +#define PC_MACHINE_ENFORCE_ALIGNED_DIMM "enforce-aligned-dimm" + +/** + * PCMachineClass: + * @get_hotplug_handler: pointer to parent class callback @get_hotplug_handler + */ +struct PCMachineClass { +    /*< private >*/ +    MachineClass parent_class; + +    /*< public >*/ +    HotplugHandler *(*get_hotplug_handler)(MachineState *machine, +                                           DeviceState *dev); +}; + +typedef struct PCMachineState PCMachineState; +typedef struct PCMachineClass PCMachineClass; + +#define TYPE_PC_MACHINE "generic-pc-machine" +#define PC_MACHINE(obj) \ +    OBJECT_CHECK(PCMachineState, (obj), TYPE_PC_MACHINE) +#define PC_MACHINE_GET_CLASS(obj) \ +    OBJECT_GET_CLASS(PCMachineClass, (obj), TYPE_PC_MACHINE) +#define PC_MACHINE_CLASS(klass) \ +    OBJECT_CLASS_CHECK(PCMachineClass, (klass), TYPE_PC_MACHINE) + +/* PC-style peripherals (also used by other machines).  */ + +typedef struct PcPciInfo { +    Range w32; +    Range w64; +} PcPciInfo; + +#define ACPI_PM_PROP_S3_DISABLED "disable_s3" +#define ACPI_PM_PROP_S4_DISABLED "disable_s4" +#define ACPI_PM_PROP_S4_VAL "s4_val" +#define ACPI_PM_PROP_SCI_INT "sci_int" +#define ACPI_PM_PROP_ACPI_ENABLE_CMD "acpi_enable_cmd" +#define ACPI_PM_PROP_ACPI_DISABLE_CMD "acpi_disable_cmd" +#define ACPI_PM_PROP_PM_IO_BASE "pm_io_base" +#define ACPI_PM_PROP_GPE0_BLK "gpe0_blk" +#define ACPI_PM_PROP_GPE0_BLK_LEN "gpe0_blk_len" +#define ACPI_PM_PROP_TCO_ENABLED "enable_tco" + +struct PcGuestInfo { +    bool isapc_ram_fw; +    hwaddr ram_size, ram_size_below_4g; +    unsigned apic_id_limit; +    bool apic_xrupt_override; +    uint64_t numa_nodes; +    uint64_t *node_mem; +    uint64_t *node_cpu; +    FWCfgState *fw_cfg; +    int legacy_acpi_table_size; +    bool has_acpi_build; +    bool has_reserved_memory; +    bool rsdp_in_ram; +}; + +/* parallel.c */ + +void parallel_hds_isa_init(ISABus *bus, int n); + +bool parallel_mm_init(MemoryRegion *address_space, +                      hwaddr base, int it_shift, qemu_irq irq, +                      CharDriverState *chr); + +/* i8259.c */ + +extern DeviceState *isa_pic; +qemu_irq *i8259_init(ISABus *bus, qemu_irq parent_irq); +qemu_irq *kvm_i8259_init(ISABus *bus); +int pic_read_irq(DeviceState *d); +int pic_get_output(DeviceState *d); +void hmp_info_pic(Monitor *mon, const QDict *qdict); +void hmp_info_irq(Monitor *mon, const QDict *qdict); + +/* Global System Interrupts */ + +#define GSI_NUM_PINS IOAPIC_NUM_PINS + +typedef struct GSIState { +    qemu_irq i8259_irq[ISA_NUM_IRQS]; +    qemu_irq ioapic_irq[IOAPIC_NUM_PINS]; +} GSIState; + +void gsi_handler(void *opaque, int n, int level); + +/* vmport.c */ +typedef uint32_t (VMPortReadFunc)(void *opaque, uint32_t address); + +static inline void vmport_init(ISABus *bus) +{ +    isa_create_simple(bus, "vmport"); +} + +void vmport_register(unsigned char command, VMPortReadFunc *func, void *opaque); +void vmmouse_get_data(uint32_t *data); +void vmmouse_set_data(const uint32_t *data); + +/* pckbd.c */ + +void i8042_init(qemu_irq kbd_irq, qemu_irq mouse_irq, uint32_t io_base); +void i8042_mm_init(qemu_irq kbd_irq, qemu_irq mouse_irq, +                   MemoryRegion *region, ram_addr_t size, +                   hwaddr mask); +void i8042_isa_mouse_fake_event(void *opaque); +void i8042_setup_a20_line(ISADevice *dev, qemu_irq *a20_out); + +/* pc.c */ +extern int fd_bootchk; + +bool pc_machine_is_smm_enabled(PCMachineState *pcms); +void pc_register_ferr_irq(qemu_irq irq); +void pc_acpi_smi_interrupt(void *opaque, int irq, int level); + +void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge); +void pc_hot_add_cpu(const int64_t id, Error **errp); +void pc_acpi_init(const char *default_dsdt); + +PcGuestInfo *pc_guest_info_init(ram_addr_t below_4g_mem_size, +                                ram_addr_t above_4g_mem_size); + +void pc_set_legacy_acpi_data_size(void); + +#define PCI_HOST_PROP_PCI_HOLE_START   "pci-hole-start" +#define PCI_HOST_PROP_PCI_HOLE_END     "pci-hole-end" +#define PCI_HOST_PROP_PCI_HOLE64_START "pci-hole64-start" +#define PCI_HOST_PROP_PCI_HOLE64_END   "pci-hole64-end" +#define PCI_HOST_PROP_PCI_HOLE64_SIZE  "pci-hole64-size" +#define DEFAULT_PCI_HOLE64_SIZE (~0x0ULL) + + +void pc_pci_as_mapping_init(Object *owner, MemoryRegion *system_memory, +                            MemoryRegion *pci_address_space); + +FWCfgState *xen_load_linux(const char *kernel_filename, +                           const char *kernel_cmdline, +                           const char *initrd_filename, +                           ram_addr_t below_4g_mem_size, +                           PcGuestInfo *guest_info); +FWCfgState *pc_memory_init(MachineState *machine, +                           MemoryRegion *system_memory, +                           ram_addr_t below_4g_mem_size, +                           ram_addr_t above_4g_mem_size, +                           MemoryRegion *rom_memory, +                           MemoryRegion **ram_memory, +                           PcGuestInfo *guest_info); +qemu_irq pc_allocate_cpu_irq(void); +DeviceState *pc_vga_init(ISABus *isa_bus, PCIBus *pci_bus); +void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi, +                          ISADevice **rtc_state, +                          bool create_fdctrl, +                          bool no_vmport, +                          uint32 hpet_irqs); +void pc_init_ne2k_isa(ISABus *bus, NICInfo *nd); +void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size, +                  const char *boot_device, MachineState *machine, +                  BusState *ide0, BusState *ide1, +                  ISADevice *s); +void pc_nic_init(ISABus *isa_bus, PCIBus *pci_bus); +void pc_pci_device_init(PCIBus *pci_bus); + +typedef void (*cpu_set_smm_t)(int smm, void *arg); + +void ioapic_init_gsi(GSIState *gsi_state, const char *parent_name); + +/* acpi_piix.c */ + +I2CBus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base, +                      qemu_irq sci_irq, qemu_irq smi_irq, +                      int smm_enabled, DeviceState **piix4_pm); +void piix4_smbus_register_device(SMBusDevice *dev, uint8_t addr); + +/* hpet.c */ +extern int no_hpet; + +/* piix_pci.c */ +struct PCII440FXState; +typedef struct PCII440FXState PCII440FXState; + +PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix_devfn, +                    ISABus **isa_bus, qemu_irq *pic, +                    MemoryRegion *address_space_mem, +                    MemoryRegion *address_space_io, +                    ram_addr_t ram_size, +                    ram_addr_t below_4g_mem_size, +                    ram_addr_t above_4g_mem_size, +                    MemoryRegion *pci_memory, +                    MemoryRegion *ram_memory); + +PCIBus *find_i440fx(void); +/* piix4.c */ +extern PCIDevice *piix4_dev; +int piix4_init(PCIBus *bus, ISABus **isa_bus, int devfn); + +/* vga.c */ +enum vga_retrace_method { +    VGA_RETRACE_DUMB, +    VGA_RETRACE_PRECISE +}; + +extern enum vga_retrace_method vga_retrace_method; + +int isa_vga_mm_init(hwaddr vram_base, +                    hwaddr ctrl_base, int it_shift, +                    MemoryRegion *address_space); + +/* ne2000.c */ +static inline bool isa_ne2000_init(ISABus *bus, int base, int irq, NICInfo *nd) +{ +    DeviceState *dev; +    ISADevice *isadev; + +    qemu_check_nic_model(nd, "ne2k_isa"); + +    isadev = isa_try_create(bus, "ne2k_isa"); +    if (!isadev) { +        return false; +    } +    dev = DEVICE(isadev); +    qdev_prop_set_uint32(dev, "iobase", base); +    qdev_prop_set_uint32(dev, "irq",    irq); +    qdev_set_nic_properties(dev, nd); +    qdev_init_nofail(dev); +    return true; +} + +/* pc_sysfw.c */ +void pc_system_firmware_init(MemoryRegion *rom_memory, +                             bool isapc_ram_fw); + +/* pvpanic.c */ +uint16_t pvpanic_port(void); + +/* e820 types */ +#define E820_RAM        1 +#define E820_RESERVED   2 +#define E820_ACPI       3 +#define E820_NVS        4 +#define E820_UNUSABLE   5 + +int e820_add_entry(uint64_t, uint64_t, uint32_t); +int e820_get_num_entries(void); +bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *); + +#define PC_COMPAT_2_3 \ +        HW_COMPAT_2_3 \ +        {\ +            .driver   = TYPE_X86_CPU,\ +            .property = "arat",\ +            .value    = "off",\ +        },{\ +            .driver   = "qemu64" "-" TYPE_X86_CPU,\ +            .property = "level",\ +            .value    = stringify(4),\ +        },{\ +            .driver   = "kvm64" "-" TYPE_X86_CPU,\ +            .property = "level",\ +            .value    = stringify(5),\ +        },{\ +            .driver   = "pentium3" "-" TYPE_X86_CPU,\ +            .property = "level",\ +            .value    = stringify(2),\ +        },{\ +            .driver   = "n270" "-" TYPE_X86_CPU,\ +            .property = "level",\ +            .value    = stringify(5),\ +        },{\ +            .driver   = "Conroe" "-" TYPE_X86_CPU,\ +            .property = "level",\ +            .value    = stringify(4),\ +        },{\ +            .driver   = "Penryn" "-" TYPE_X86_CPU,\ +            .property = "level",\ +            .value    = stringify(4),\ +        },{\ +            .driver   = "Nehalem" "-" TYPE_X86_CPU,\ +            .property = "level",\ +            .value    = stringify(4),\ +        },{\ +            .driver   = "n270" "-" TYPE_X86_CPU,\ +            .property = "xlevel",\ +            .value    = stringify(0x8000000a),\ +        },{\ +            .driver   = "Penryn" "-" TYPE_X86_CPU,\ +            .property = "xlevel",\ +            .value    = stringify(0x8000000a),\ +        },{\ +            .driver   = "Conroe" "-" TYPE_X86_CPU,\ +            .property = "xlevel",\ +            .value    = stringify(0x8000000a),\ +        },{\ +            .driver   = "Nehalem" "-" TYPE_X86_CPU,\ +            .property = "xlevel",\ +            .value    = stringify(0x8000000a),\ +        },{\ +            .driver   = "Westmere" "-" TYPE_X86_CPU,\ +            .property = "xlevel",\ +            .value    = stringify(0x8000000a),\ +        },{\ +            .driver   = "SandyBridge" "-" TYPE_X86_CPU,\ +            .property = "xlevel",\ +            .value    = stringify(0x8000000a),\ +        },{\ +            .driver   = "IvyBridge" "-" TYPE_X86_CPU,\ +            .property = "xlevel",\ +            .value    = stringify(0x8000000a),\ +        },{\ +            .driver   = "Haswell" "-" TYPE_X86_CPU,\ +            .property = "xlevel",\ +            .value    = stringify(0x8000000a),\ +        },{\ +            .driver   = "Haswell-noTSX" "-" TYPE_X86_CPU,\ +            .property = "xlevel",\ +            .value    = stringify(0x8000000a),\ +        },{\ +            .driver   = "Broadwell" "-" TYPE_X86_CPU,\ +            .property = "xlevel",\ +            .value    = stringify(0x8000000a),\ +        },{\ +            .driver   = "Broadwell-noTSX" "-" TYPE_X86_CPU,\ +            .property = "xlevel",\ +            .value    = stringify(0x8000000a),\ +        }, + +#define PC_COMPAT_2_2 \ +        PC_COMPAT_2_3 \ +        HW_COMPAT_2_2 + +#define PC_COMPAT_2_1 \ +        PC_COMPAT_2_2 \ +        HW_COMPAT_2_1 + +#define PC_COMPAT_2_0 \ +        PC_COMPAT_2_1 \ +        {\ +            .driver   = "virtio-scsi-pci",\ +            .property = "any_layout",\ +            .value    = "off",\ +        },{\ +            .driver   = "PIIX4_PM",\ +            .property = "memory-hotplug-support",\ +            .value    = "off",\ +        },\ +        {\ +            .driver   = "apic",\ +            .property = "version",\ +            .value    = stringify(0x11),\ +        },\ +        {\ +            .driver   = "nec-usb-xhci",\ +            .property = "superspeed-ports-first",\ +            .value    = "off",\ +        },\ +        {\ +            .driver   = "nec-usb-xhci",\ +            .property = "force-pcie-endcap",\ +            .value    = "on",\ +        },\ +        {\ +            .driver   = "pci-serial",\ +            .property = "prog_if",\ +            .value    = stringify(0),\ +        },\ +        {\ +            .driver   = "pci-serial-2x",\ +            .property = "prog_if",\ +            .value    = stringify(0),\ +        },\ +        {\ +            .driver   = "pci-serial-4x",\ +            .property = "prog_if",\ +            .value    = stringify(0),\ +        },\ +        {\ +            .driver   = "virtio-net-pci",\ +            .property = "guest_announce",\ +            .value    = "off",\ +        },\ +        {\ +            .driver   = "ICH9-LPC",\ +            .property = "memory-hotplug-support",\ +            .value    = "off",\ +        },{\ +            .driver   = "xio3130-downstream",\ +            .property = COMPAT_PROP_PCP,\ +            .value    = "off",\ +        },{\ +            .driver   = "ioh3420",\ +            .property = COMPAT_PROP_PCP,\ +            .value    = "off",\ +        }, + +#define PC_COMPAT_1_7 \ +        PC_COMPAT_2_0 \ +        {\ +            .driver   = TYPE_USB_DEVICE,\ +            .property = "msos-desc",\ +            .value    = "no",\ +        },\ +        {\ +            .driver   = "PIIX4_PM",\ +            .property = "acpi-pci-hotplug-with-bridge-support",\ +            .value    = "off",\ +        },\ +        {\ +            .driver   = "hpet",\ +            .property = HPET_INTCAP,\ +            .value    = stringify(4),\ +        }, + +#define PC_COMPAT_1_6 \ +        PC_COMPAT_1_7 \ +        {\ +            .driver   = "e1000",\ +            .property = "mitigation",\ +            .value    = "off",\ +        },{\ +            .driver   = "qemu64-" TYPE_X86_CPU,\ +            .property = "model",\ +            .value    = stringify(2),\ +        },{\ +            .driver   = "qemu32-" TYPE_X86_CPU,\ +            .property = "model",\ +            .value    = stringify(3),\ +        },{\ +            .driver   = "i440FX-pcihost",\ +            .property = "short_root_bus",\ +            .value    = stringify(1),\ +        },{\ +            .driver   = "q35-pcihost",\ +            .property = "short_root_bus",\ +            .value    = stringify(1),\ +        }, + +#define PC_COMPAT_1_5 \ +        PC_COMPAT_1_6 \ +        {\ +            .driver   = "Conroe-" TYPE_X86_CPU,\ +            .property = "model",\ +            .value    = stringify(2),\ +        },{\ +            .driver   = "Conroe-" TYPE_X86_CPU,\ +            .property = "level",\ +            .value    = stringify(2),\ +        },{\ +            .driver   = "Penryn-" TYPE_X86_CPU,\ +            .property = "model",\ +            .value    = stringify(2),\ +        },{\ +            .driver   = "Penryn-" TYPE_X86_CPU,\ +            .property = "level",\ +            .value    = stringify(2),\ +        },{\ +            .driver   = "Nehalem-" TYPE_X86_CPU,\ +            .property = "model",\ +            .value    = stringify(2),\ +        },{\ +            .driver   = "Nehalem-" TYPE_X86_CPU,\ +            .property = "level",\ +            .value    = stringify(2),\ +        },{\ +            .driver   = "virtio-net-pci",\ +            .property = "any_layout",\ +            .value    = "off",\ +        },{\ +            .driver = TYPE_X86_CPU,\ +            .property = "pmu",\ +            .value = "on",\ +        },{\ +            .driver   = "i440FX-pcihost",\ +            .property = "short_root_bus",\ +            .value    = stringify(0),\ +        },{\ +            .driver   = "q35-pcihost",\ +            .property = "short_root_bus",\ +            .value    = stringify(0),\ +        }, + +#define PC_COMPAT_1_4 \ +        PC_COMPAT_1_5 \ +        {\ +            .driver   = "scsi-hd",\ +            .property = "discard_granularity",\ +            .value    = stringify(0),\ +        },{\ +            .driver   = "scsi-cd",\ +            .property = "discard_granularity",\ +            .value    = stringify(0),\ +        },{\ +            .driver   = "scsi-disk",\ +            .property = "discard_granularity",\ +            .value    = stringify(0),\ +        },{\ +            .driver   = "ide-hd",\ +            .property = "discard_granularity",\ +            .value    = stringify(0),\ +        },{\ +            .driver   = "ide-cd",\ +            .property = "discard_granularity",\ +            .value    = stringify(0),\ +        },{\ +            .driver   = "ide-drive",\ +            .property = "discard_granularity",\ +            .value    = stringify(0),\ +        },{\ +            .driver   = "virtio-blk-pci",\ +            .property = "discard_granularity",\ +            .value    = stringify(0),\ +        },{\ +            .driver   = "virtio-serial-pci",\ +            .property = "vectors",\ +            /* DEV_NVECTORS_UNSPECIFIED as a uint32_t string */\ +            .value    = stringify(0xFFFFFFFF),\ +        },{ \ +            .driver   = "virtio-net-pci", \ +            .property = "ctrl_guest_offloads", \ +            .value    = "off", \ +        },{\ +            .driver   = "e1000",\ +            .property = "romfile",\ +            .value    = "pxe-e1000.rom",\ +        },{\ +            .driver   = "ne2k_pci",\ +            .property = "romfile",\ +            .value    = "pxe-ne2k_pci.rom",\ +        },{\ +            .driver   = "pcnet",\ +            .property = "romfile",\ +            .value    = "pxe-pcnet.rom",\ +        },{\ +            .driver   = "rtl8139",\ +            .property = "romfile",\ +            .value    = "pxe-rtl8139.rom",\ +        },{\ +            .driver   = "virtio-net-pci",\ +            .property = "romfile",\ +            .value    = "pxe-virtio.rom",\ +        },{\ +            .driver   = "486-" TYPE_X86_CPU,\ +            .property = "model",\ +            .value    = stringify(0),\ +        }, + +static inline void pc_common_machine_options(MachineClass *m) +{ +    m->default_boot_order = "cad"; +} + +static inline void pc_default_machine_options(MachineClass *m) +{ +    pc_common_machine_options(m); +    m->hot_add_cpu = pc_hot_add_cpu; +    m->max_cpus = 255; +} + +#define DEFINE_PC_MACHINE(suffix, namestr, initfn, optsfn) \ +    static void pc_machine_##suffix##_class_init(ObjectClass *oc, void *data) \ +    { \ +        MachineClass *mc = MACHINE_CLASS(oc); \ +        optsfn(mc); \ +        mc->name = namestr; \ +        mc->init = initfn; \ +    } \ +    static const TypeInfo pc_machine_type_##suffix = { \ +        .name       = namestr TYPE_MACHINE_SUFFIX, \ +        .parent     = TYPE_PC_MACHINE, \ +        .class_init = pc_machine_##suffix##_class_init, \ +    }; \ +    static void pc_machine_init_##suffix(void) \ +    { \ +        type_register(&pc_machine_type_##suffix); \ +    } \ +    machine_init(pc_machine_init_##suffix) + +#define SET_MACHINE_COMPAT(m, COMPAT) do { \ +    static GlobalProperty props[] = { \ +        COMPAT \ +        { /* end of list */ } \ +    }; \ +    (m)->compat_props = props; \ +} while (0) + +#endif diff --git a/include/hw/i386/smbios.h b/include/hw/i386/smbios.h new file mode 100644 index 00000000..d2850bed --- /dev/null +++ b/include/hw/i386/smbios.h @@ -0,0 +1,227 @@ +#ifndef QEMU_SMBIOS_H +#define QEMU_SMBIOS_H +/* + * SMBIOS Support + * + * Copyright (C) 2009 Hewlett-Packard Development Company, L.P. + * + * Authors: + *  Alex Williamson <alex.williamson@hp.com> + * + * This work is licensed under the terms of the GNU GPL, version 2.  See + * the COPYING file in the top-level directory. + * + */ + +#include "qemu/option.h" + +#define SMBIOS_MAX_TYPE 127 + +void smbios_entry_add(QemuOpts *opts); +void smbios_set_cpuid(uint32_t version, uint32_t features); +void smbios_set_defaults(const char *manufacturer, const char *product, +                         const char *version, bool legacy_mode, +                         bool uuid_encoded); +uint8_t *smbios_get_table_legacy(size_t *length); +void smbios_get_tables(uint8_t **tables, size_t *tables_len, +                       uint8_t **anchor, size_t *anchor_len); + +/* + * SMBIOS spec defined tables + */ + +/* SMBIOS entry point (anchor). + * BIOS must place this at a 16-bit-aligned address between 0xf0000 and 0xfffff. + */ +struct smbios_entry_point { +    uint8_t anchor_string[4]; +    uint8_t checksum; +    uint8_t length; +    uint8_t smbios_major_version; +    uint8_t smbios_minor_version; +    uint16_t max_structure_size; +    uint8_t entry_point_revision; +    uint8_t formatted_area[5]; +    uint8_t intermediate_anchor_string[5]; +    uint8_t intermediate_checksum; +    uint16_t structure_table_length; +    uint32_t structure_table_address; +    uint16_t number_of_structures; +    uint8_t smbios_bcd_revision; +} QEMU_PACKED; + +/* This goes at the beginning of every SMBIOS structure. */ +struct smbios_structure_header { +    uint8_t type; +    uint8_t length; +    uint16_t handle; +} QEMU_PACKED; + +/* SMBIOS type 0 - BIOS Information */ +struct smbios_type_0 { +    struct smbios_structure_header header; +    uint8_t vendor_str; +    uint8_t bios_version_str; +    uint16_t bios_starting_address_segment; +    uint8_t bios_release_date_str; +    uint8_t bios_rom_size; +    uint64_t bios_characteristics; +    uint8_t bios_characteristics_extension_bytes[2]; +    uint8_t system_bios_major_release; +    uint8_t system_bios_minor_release; +    uint8_t embedded_controller_major_release; +    uint8_t embedded_controller_minor_release; +} QEMU_PACKED; + +/* UUID encoding. The time_* fields are little-endian, as specified by SMBIOS + * version 2.6. + */ +struct smbios_uuid { +    uint32_t time_low; +    uint16_t time_mid; +    uint16_t time_hi_and_version; +    uint8_t clock_seq_hi_and_reserved; +    uint8_t clock_seq_low; +    uint8_t node[6]; +} QEMU_PACKED; + +/* SMBIOS type 1 - System Information */ +struct smbios_type_1 { +    struct smbios_structure_header header; +    uint8_t manufacturer_str; +    uint8_t product_name_str; +    uint8_t version_str; +    uint8_t serial_number_str; +    struct smbios_uuid uuid; +    uint8_t wake_up_type; +    uint8_t sku_number_str; +    uint8_t family_str; +} QEMU_PACKED; + +/* SMBIOS type 2 - Base Board */ +struct smbios_type_2 { +    struct smbios_structure_header header; +    uint8_t manufacturer_str; +    uint8_t product_str; +    uint8_t version_str; +    uint8_t serial_number_str; +    uint8_t asset_tag_number_str; +    uint8_t feature_flags; +    uint8_t location_str; +    uint16_t chassis_handle; +    uint8_t board_type; +    uint8_t contained_element_count; +    /* contained elements follow */ +} QEMU_PACKED; + +/* SMBIOS type 3 - System Enclosure (v2.7) */ +struct smbios_type_3 { +    struct smbios_structure_header header; +    uint8_t manufacturer_str; +    uint8_t type; +    uint8_t version_str; +    uint8_t serial_number_str; +    uint8_t asset_tag_number_str; +    uint8_t boot_up_state; +    uint8_t power_supply_state; +    uint8_t thermal_state; +    uint8_t security_status; +    uint32_t oem_defined; +    uint8_t height; +    uint8_t number_of_power_cords; +    uint8_t contained_element_count; +    uint8_t sku_number_str; +    /* contained elements follow */ +} QEMU_PACKED; + +/* SMBIOS type 4 - Processor Information (v2.6) */ +struct smbios_type_4 { +    struct smbios_structure_header header; +    uint8_t socket_designation_str; +    uint8_t processor_type; +    uint8_t processor_family; +    uint8_t processor_manufacturer_str; +    uint32_t processor_id[2]; +    uint8_t processor_version_str; +    uint8_t voltage; +    uint16_t external_clock; +    uint16_t max_speed; +    uint16_t current_speed; +    uint8_t status; +    uint8_t processor_upgrade; +    uint16_t l1_cache_handle; +    uint16_t l2_cache_handle; +    uint16_t l3_cache_handle; +    uint8_t serial_number_str; +    uint8_t asset_tag_number_str; +    uint8_t part_number_str; +    uint8_t core_count; +    uint8_t core_enabled; +    uint8_t thread_count; +    uint16_t processor_characteristics; +    uint16_t processor_family2; +} QEMU_PACKED; + +/* SMBIOS type 16 - Physical Memory Array (v2.7) */ +struct smbios_type_16 { +    struct smbios_structure_header header; +    uint8_t location; +    uint8_t use; +    uint8_t error_correction; +    uint32_t maximum_capacity; +    uint16_t memory_error_information_handle; +    uint16_t number_of_memory_devices; +    uint64_t extended_maximum_capacity; +} QEMU_PACKED; + +/* SMBIOS type 17 - Memory Device (v2.8) */ +struct smbios_type_17 { +    struct smbios_structure_header header; +    uint16_t physical_memory_array_handle; +    uint16_t memory_error_information_handle; +    uint16_t total_width; +    uint16_t data_width; +    uint16_t size; +    uint8_t form_factor; +    uint8_t device_set; +    uint8_t device_locator_str; +    uint8_t bank_locator_str; +    uint8_t memory_type; +    uint16_t type_detail; +    uint16_t speed; +    uint8_t manufacturer_str; +    uint8_t serial_number_str; +    uint8_t asset_tag_number_str; +    uint8_t part_number_str; +    uint8_t attributes; +    uint32_t extended_size; +    uint16_t configured_clock_speed; +    uint16_t minimum_voltage; +    uint16_t maximum_voltage; +    uint16_t configured_voltage; +} QEMU_PACKED; + +/* SMBIOS type 19 - Memory Array Mapped Address (v2.7) */ +struct smbios_type_19 { +    struct smbios_structure_header header; +    uint32_t starting_address; +    uint32_t ending_address; +    uint16_t memory_array_handle; +    uint8_t partition_width; +    uint64_t extended_starting_address; +    uint64_t extended_ending_address; +} QEMU_PACKED; + +/* SMBIOS type 32 - System Boot Information */ +struct smbios_type_32 { +    struct smbios_structure_header header; +    uint8_t reserved[6]; +    uint8_t boot_status; +} QEMU_PACKED; + +/* SMBIOS type 127 -- End-of-table */ +struct smbios_type_127 { +    struct smbios_structure_header header; +} QEMU_PACKED; + +#endif /*QEMU_SMBIOS_H */ diff --git a/include/hw/i386/topology.h b/include/hw/i386/topology.h new file mode 100644 index 00000000..9c6f3a93 --- /dev/null +++ b/include/hw/i386/topology.h @@ -0,0 +1,134 @@ +/* + *  x86 CPU topology data structures and functions + * + *  Copyright (c) 2012 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * 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 OTHER + * 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. + */ +#ifndef HW_I386_TOPOLOGY_H +#define HW_I386_TOPOLOGY_H + +/* This file implements the APIC-ID-based CPU topology enumeration logic, + * documented at the following document: + *   Intel® 64 Architecture Processor Topology Enumeration + *   http://software.intel.com/en-us/articles/intel-64-architecture-processor-topology-enumeration/ + * + * This code should be compatible with AMD's "Extended Method" described at: + *   AMD CPUID Specification (Publication #25481) + *   Section 3: Multiple Core Calcuation + * as long as: + *  nr_threads is set to 1; + *  OFFSET_IDX is assumed to be 0; + *  CPUID Fn8000_0008_ECX[ApicIdCoreIdSize[3:0]] is set to apicid_core_width(). + */ + +#include <stdint.h> +#include <string.h> + +#include "qemu/bitops.h" + +/* APIC IDs can be 32-bit, but beware: APIC IDs > 255 require x2APIC support + */ +typedef uint32_t apic_id_t; + +/* Return the bit width needed for 'count' IDs + */ +static unsigned apicid_bitwidth_for_count(unsigned count) +{ +    g_assert(count >= 1); +    count -= 1; +    return count ? 32 - clz32(count) : 0; +} + +/* Bit width of the SMT_ID (thread ID) field on the APIC ID + */ +static inline unsigned apicid_smt_width(unsigned nr_cores, unsigned nr_threads) +{ +    return apicid_bitwidth_for_count(nr_threads); +} + +/* Bit width of the Core_ID field + */ +static inline unsigned apicid_core_width(unsigned nr_cores, unsigned nr_threads) +{ +    return apicid_bitwidth_for_count(nr_cores); +} + +/* Bit offset of the Core_ID field + */ +static inline unsigned apicid_core_offset(unsigned nr_cores, +                                          unsigned nr_threads) +{ +    return apicid_smt_width(nr_cores, nr_threads); +} + +/* Bit offset of the Pkg_ID (socket ID) field + */ +static inline unsigned apicid_pkg_offset(unsigned nr_cores, unsigned nr_threads) +{ +    return apicid_core_offset(nr_cores, nr_threads) + +           apicid_core_width(nr_cores, nr_threads); +} + +/* Make APIC ID for the CPU based on Pkg_ID, Core_ID, SMT_ID + * + * The caller must make sure core_id < nr_cores and smt_id < nr_threads. + */ +static inline apic_id_t apicid_from_topo_ids(unsigned nr_cores, +                                             unsigned nr_threads, +                                             unsigned pkg_id, +                                             unsigned core_id, +                                             unsigned smt_id) +{ +    return (pkg_id  << apicid_pkg_offset(nr_cores, nr_threads)) | +           (core_id << apicid_core_offset(nr_cores, nr_threads)) | +           smt_id; +} + +/* Calculate thread/core/package IDs for a specific topology, + * based on (contiguous) CPU index + */ +static inline void x86_topo_ids_from_idx(unsigned nr_cores, +                                         unsigned nr_threads, +                                         unsigned cpu_index, +                                         unsigned *pkg_id, +                                         unsigned *core_id, +                                         unsigned *smt_id) +{ +    unsigned core_index = cpu_index / nr_threads; +    *smt_id = cpu_index % nr_threads; +    *core_id = core_index % nr_cores; +    *pkg_id = core_index / nr_cores; +} + +/* Make APIC ID for the CPU 'cpu_index' + * + * 'cpu_index' is a sequential, contiguous ID for the CPU. + */ +static inline apic_id_t x86_apicid_from_cpu_idx(unsigned nr_cores, +                                                unsigned nr_threads, +                                                unsigned cpu_index) +{ +    unsigned pkg_id, core_id, smt_id; +    x86_topo_ids_from_idx(nr_cores, nr_threads, cpu_index, +                          &pkg_id, &core_id, &smt_id); +    return apicid_from_topo_ids(nr_cores, nr_threads, pkg_id, core_id, smt_id); +} + +#endif /* HW_I386_TOPOLOGY_H */ diff --git a/include/hw/ide.h b/include/hw/ide.h new file mode 100644 index 00000000..bc8bd321 --- /dev/null +++ b/include/hw/ide.h @@ -0,0 +1,33 @@ +#ifndef HW_IDE_H +#define HW_IDE_H + +#include "hw/isa/isa.h" +#include "hw/pci/pci.h" +#include "exec/memory.h" + +#define MAX_IDE_DEVS	2 + +/* ide-isa.c */ +ISADevice *isa_ide_init(ISABus *bus, int iobase, int iobase2, int isairq, +                        DriveInfo *hd0, DriveInfo *hd1); + +/* ide-pci.c */ +void pci_cmd646_ide_init(PCIBus *bus, DriveInfo **hd_table, +                         int secondary_ide_enabled); +PCIDevice *pci_piix3_xen_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn); +PCIDevice *pci_piix3_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn); +PCIDevice *pci_piix4_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn); +int pci_piix3_xen_ide_unplug(DeviceState *dev); +void vt82c686b_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn); + +/* ide-mmio.c */ +void mmio_ide_init_drives(DeviceState *dev, DriveInfo *hd0, DriveInfo *hd1); + +int ide_get_geometry(BusState *bus, int unit, +                     int16_t *cyls, int8_t *heads, int8_t *secs); +int ide_get_bios_chs_trans(BusState *bus, int unit); + +/* ide/core.c */ +void ide_drive_get(DriveInfo **hd, int max_bus); + +#endif /* HW_IDE_H */ diff --git a/include/hw/input/adb.h b/include/hw/input/adb.h new file mode 100644 index 00000000..bdfccd40 --- /dev/null +++ b/include/hw/input/adb.h @@ -0,0 +1,87 @@ +/* + * QEMU ADB emulation shared definitions and prototypes + * + * Copyright (c) 2004-2007 Fabrice Bellard + * Copyright (c) 2007 Jocelyn Mayer + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * 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 OTHER + * 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. + */ + +#if !defined(__ADB_H__) +#define __ADB_H__ + +#include "hw/qdev.h" + +#define MAX_ADB_DEVICES 16 + +#define ADB_MAX_OUT_LEN 16 + +typedef struct ADBBusState ADBBusState; +typedef struct ADBDevice ADBDevice; + +/* buf = NULL means polling */ +typedef int ADBDeviceRequest(ADBDevice *d, uint8_t *buf_out, +                              const uint8_t *buf, int len); + +#define TYPE_ADB_DEVICE "adb-device" +#define ADB_DEVICE(obj) OBJECT_CHECK(ADBDevice, (obj), TYPE_ADB_DEVICE) + +struct ADBDevice { +    /*< private >*/ +    DeviceState parent_obj; +    /*< public >*/ + +    int devaddr; +    int handler; +}; + +#define ADB_DEVICE_CLASS(cls) \ +    OBJECT_CLASS_CHECK(ADBDeviceClass, (cls), TYPE_ADB_DEVICE) +#define ADB_DEVICE_GET_CLASS(obj) \ +    OBJECT_GET_CLASS(ADBDeviceClass, (obj), TYPE_ADB_DEVICE) + +typedef struct ADBDeviceClass { +    /*< private >*/ +    DeviceClass parent_class; +    /*< public >*/ + +    ADBDeviceRequest *devreq; +} ADBDeviceClass; + +#define TYPE_ADB_BUS "apple-desktop-bus" +#define ADB_BUS(obj) OBJECT_CHECK(ADBBusState, (obj), TYPE_ADB_BUS) + +struct ADBBusState { +    /*< private >*/ +    BusState parent_obj; +    /*< public >*/ + +    ADBDevice *devices[MAX_ADB_DEVICES]; +    int nb_devices; +    int poll_index; +}; + +int adb_request(ADBBusState *s, uint8_t *buf_out, +                const uint8_t *buf, int len); +int adb_poll(ADBBusState *s, uint8_t *buf_out); + +#define TYPE_ADB_KEYBOARD "adb-keyboard" +#define TYPE_ADB_MOUSE "adb-mouse" + +#endif /* !defined(__ADB_H__) */ diff --git a/include/hw/input/hid.h b/include/hw/input/hid.h new file mode 100644 index 00000000..2127c7ce --- /dev/null +++ b/include/hw/input/hid.h @@ -0,0 +1,84 @@ +#ifndef QEMU_HID_H +#define QEMU_HID_H + +#include "migration/vmstate.h" +#include "ui/input.h" + +#define HID_MOUSE     1 +#define HID_TABLET    2 +#define HID_KEYBOARD  3 + +typedef struct HIDPointerEvent { +    int32_t xdx, ydy; /* relative iff it's a mouse, otherwise absolute */ +    int32_t dz, buttons_state; +} HIDPointerEvent; + +#define QUEUE_LENGTH    16 /* should be enough for a triple-click */ +#define QUEUE_MASK      (QUEUE_LENGTH-1u) +#define QUEUE_INCR(v)   ((v)++, (v) &= QUEUE_MASK) + +typedef struct HIDState HIDState; +typedef void (*HIDEventFunc)(HIDState *s); + +typedef struct HIDMouseState { +    HIDPointerEvent queue[QUEUE_LENGTH]; +    int mouse_grabbed; +} HIDMouseState; + +typedef struct HIDKeyboardState { +    uint32_t keycodes[QUEUE_LENGTH]; +    uint16_t modifiers; +    uint8_t leds; +    uint8_t key[16]; +    int32_t keys; +} HIDKeyboardState; + +struct HIDState { +    union { +        HIDMouseState ptr; +        HIDKeyboardState kbd; +    }; +    uint32_t head; /* index into circular queue */ +    uint32_t n; +    int kind; +    int32_t protocol; +    uint8_t idle; +    bool idle_pending; +    QEMUTimer *idle_timer; +    HIDEventFunc event; +    QemuInputHandlerState *s; +}; + +void hid_init(HIDState *hs, int kind, HIDEventFunc event); +void hid_reset(HIDState *hs); +void hid_free(HIDState *hs); + +bool hid_has_events(HIDState *hs); +void hid_set_next_idle(HIDState *hs); +void hid_pointer_activate(HIDState *hs); +int hid_pointer_poll(HIDState *hs, uint8_t *buf, int len); +int hid_keyboard_poll(HIDState *hs, uint8_t *buf, int len); +int hid_keyboard_write(HIDState *hs, uint8_t *buf, int len); + +extern const VMStateDescription vmstate_hid_keyboard_device; + +#define VMSTATE_HID_KEYBOARD_DEVICE(_field, _state) {                \ +    .name       = (stringify(_field)),                               \ +    .size       = sizeof(HIDState),                                  \ +    .vmsd       = &vmstate_hid_keyboard_device,                      \ +    .flags      = VMS_STRUCT,                                        \ +    .offset     = vmstate_offset_value(_state, _field, HIDState),    \ +} + +extern const VMStateDescription vmstate_hid_ptr_device; + +#define VMSTATE_HID_POINTER_DEVICE(_field, _state) {                 \ +    .name       = (stringify(_field)),                               \ +    .size       = sizeof(HIDState),                                  \ +    .vmsd       = &vmstate_hid_ptr_device,                           \ +    .flags      = VMS_STRUCT,                                        \ +    .offset     = vmstate_offset_value(_state, _field, HIDState),    \ +} + + +#endif /* QEMU_HID_H */ diff --git a/include/hw/input/ps2.h b/include/hw/input/ps2.h new file mode 100644 index 00000000..7c45ce7c --- /dev/null +++ b/include/hw/input/ps2.h @@ -0,0 +1,38 @@ +/* + * QEMU PS/2 keyboard/mouse emulation + * + * Copyright (C) 2003 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * 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 OTHER + * 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. + */ + +#ifndef HW_PS2_H +#define HW_PS2_H + +/* ps2.c */ +void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg); +void *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg); +void ps2_write_mouse(void *, int val); +void ps2_write_keyboard(void *, int val); +uint32_t ps2_read_data(void *); +void ps2_queue(void *, int b); +void ps2_keyboard_set_translation(void *opaque, int mode); +void ps2_mouse_fake_event(void *opaque); + +#endif /* !HW_PS2_H */ diff --git a/include/hw/intc/allwinner-a10-pic.h b/include/hw/intc/allwinner-a10-pic.h new file mode 100644 index 00000000..5721b2e6 --- /dev/null +++ b/include/hw/intc/allwinner-a10-pic.h @@ -0,0 +1,40 @@ +#ifndef AW_A10_PIC_H +#define AW_A10_PIC_H + +#define TYPE_AW_A10_PIC  "allwinner-a10-pic" +#define AW_A10_PIC(obj) OBJECT_CHECK(AwA10PICState, (obj), TYPE_AW_A10_PIC) + +#define AW_A10_PIC_VECTOR       0 +#define AW_A10_PIC_BASE_ADDR    4 +#define AW_A10_PIC_PROTECT      8 +#define AW_A10_PIC_NMI          0xc +#define AW_A10_PIC_IRQ_PENDING  0x10 +#define AW_A10_PIC_FIQ_PENDING  0x20 +#define AW_A10_PIC_SELECT       0x30 +#define AW_A10_PIC_ENABLE       0x40 +#define AW_A10_PIC_MASK         0x50 + +#define AW_A10_PIC_INT_NR       95 +#define AW_A10_PIC_REG_NUM      DIV_ROUND_UP(AW_A10_PIC_INT_NR, 32) + +typedef struct AwA10PICState { +    /*< private >*/ +    SysBusDevice parent_obj; +    /*< public >*/ +    MemoryRegion iomem; +    qemu_irq parent_fiq; +    qemu_irq parent_irq; + +    uint32_t vector; +    uint32_t base_addr; +    uint32_t protect; +    uint32_t nmi; +    uint32_t irq_pending[AW_A10_PIC_REG_NUM]; +    uint32_t fiq_pending[AW_A10_PIC_REG_NUM]; +    uint32_t select[AW_A10_PIC_REG_NUM]; +    uint32_t enable[AW_A10_PIC_REG_NUM]; +    uint32_t mask[AW_A10_PIC_REG_NUM]; +    /*priority setting here*/ +} AwA10PICState; + +#endif diff --git a/include/hw/intc/arm_gic.h b/include/hw/intc/arm_gic.h new file mode 100644 index 00000000..0971e377 --- /dev/null +++ b/include/hw/intc/arm_gic.h @@ -0,0 +1,42 @@ +/* + * ARM GIC support + * + * Copyright (c) 2012 Linaro Limited + * Written by Peter Maydell + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef HW_ARM_GIC_H +#define HW_ARM_GIC_H + +#include "arm_gic_common.h" + +#define TYPE_ARM_GIC "arm_gic" +#define ARM_GIC(obj) \ +     OBJECT_CHECK(GICState, (obj), TYPE_ARM_GIC) +#define ARM_GIC_CLASS(klass) \ +     OBJECT_CLASS_CHECK(ARMGICClass, (klass), TYPE_ARM_GIC) +#define ARM_GIC_GET_CLASS(obj) \ +     OBJECT_GET_CLASS(ARMGICClass, (obj), TYPE_ARM_GIC) + +typedef struct ARMGICClass { +    /*< private >*/ +    ARMGICCommonClass parent_class; +    /*< public >*/ + +    DeviceRealize parent_realize; +} ARMGICClass; + +#endif diff --git a/include/hw/intc/arm_gic_common.h b/include/hw/intc/arm_gic_common.h new file mode 100644 index 00000000..899db3d7 --- /dev/null +++ b/include/hw/intc/arm_gic_common.h @@ -0,0 +1,141 @@ +/* + * ARM GIC support + * + * Copyright (c) 2012 Linaro Limited + * Written by Peter Maydell + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef HW_ARM_GIC_COMMON_H +#define HW_ARM_GIC_COMMON_H + +#include "hw/sysbus.h" + +/* Maximum number of possible interrupts, determined by the GIC architecture */ +#define GIC_MAXIRQ 1020 +/* First 32 are private to each CPU (SGIs and PPIs). */ +#define GIC_INTERNAL 32 +#define GIC_NR_SGIS 16 +/* Maximum number of possible CPU interfaces, determined by GIC architecture */ +#define GIC_NCPU 8 + +#define MAX_NR_GROUP_PRIO 128 +#define GIC_NR_APRS (MAX_NR_GROUP_PRIO / 32) + +#define GIC_MIN_BPR 0 +#define GIC_MIN_ABPR (GIC_MIN_BPR + 1) + +typedef struct gic_irq_state { +    /* The enable bits are only banked for per-cpu interrupts.  */ +    uint8_t enabled; +    uint8_t pending; +    uint8_t active; +    uint8_t level; +    bool model; /* 0 = N:N, 1 = 1:N */ +    bool edge_trigger; /* true: edge-triggered, false: level-triggered  */ +    uint8_t group; +} gic_irq_state; + +typedef struct GICState { +    /*< private >*/ +    SysBusDevice parent_obj; +    /*< public >*/ + +    qemu_irq parent_irq[GIC_NCPU]; +    qemu_irq parent_fiq[GIC_NCPU]; +    /* GICD_CTLR; for a GIC with the security extensions the NS banked version +     * of this register is just an alias of bit 1 of the S banked version. +     */ +    uint32_t ctlr; +    /* GICC_CTLR; again, the NS banked version is just aliases of bits of +     * the S banked register, so our state only needs to store the S version. +     */ +    uint32_t cpu_ctlr[GIC_NCPU]; + +    gic_irq_state irq_state[GIC_MAXIRQ]; +    uint8_t irq_target[GIC_MAXIRQ]; +    uint8_t priority1[GIC_INTERNAL][GIC_NCPU]; +    uint8_t priority2[GIC_MAXIRQ - GIC_INTERNAL]; +    uint16_t last_active[GIC_MAXIRQ][GIC_NCPU]; +    /* For each SGI on the target CPU, we store 8 bits +     * indicating which source CPUs have made this SGI +     * pending on the target CPU. These correspond to +     * the bytes in the GIC_SPENDSGIR* registers as +     * read by the target CPU. +     */ +    uint8_t sgi_pending[GIC_NR_SGIS][GIC_NCPU]; + +    uint16_t priority_mask[GIC_NCPU]; +    uint16_t running_irq[GIC_NCPU]; +    uint16_t running_priority[GIC_NCPU]; +    uint16_t current_pending[GIC_NCPU]; + +    /* If we present the GICv2 without security extensions to a guest, +     * the guest can configure the GICC_CTLR to configure group 1 binary point +     * in the abpr. +     * For a GIC with Security Extensions we use use bpr for the +     * secure copy and abpr as storage for the non-secure copy of the register. +     */ +    uint8_t  bpr[GIC_NCPU]; +    uint8_t  abpr[GIC_NCPU]; + +    /* The APR is implementation defined, so we choose a layout identical to +     * the KVM ABI layout for QEMU's implementation of the gic: +     * If an interrupt for preemption level X is active, then +     *   APRn[X mod 32] == 0b1,  where n = X / 32 +     * otherwise the bit is clear. +     * +     * TODO: rewrite the interrupt acknowlege/complete routines to use +     * the APR registers to track the necessary information to update +     * s->running_priority[] on interrupt completion (ie completely remove +     * last_active[][] and running_irq[]). This will be necessary if we ever +     * want to support TCG<->KVM migration, or TCG guests which can +     * do power management involving powering down and restarting +     * the GIC. +     */ +    uint32_t apr[GIC_NR_APRS][GIC_NCPU]; + +    uint32_t num_cpu; + +    MemoryRegion iomem; /* Distributor */ +    /* This is just so we can have an opaque pointer which identifies +     * both this GIC and which CPU interface we should be accessing. +     */ +    struct GICState *backref[GIC_NCPU]; +    MemoryRegion cpuiomem[GIC_NCPU + 1]; /* CPU interfaces */ +    uint32_t num_irq; +    uint32_t revision; +    bool security_extn; +    int dev_fd; /* kvm device fd if backed by kvm vgic support */ +} GICState; + +#define TYPE_ARM_GIC_COMMON "arm_gic_common" +#define ARM_GIC_COMMON(obj) \ +     OBJECT_CHECK(GICState, (obj), TYPE_ARM_GIC_COMMON) +#define ARM_GIC_COMMON_CLASS(klass) \ +     OBJECT_CLASS_CHECK(ARMGICCommonClass, (klass), TYPE_ARM_GIC_COMMON) +#define ARM_GIC_COMMON_GET_CLASS(obj) \ +     OBJECT_GET_CLASS(ARMGICCommonClass, (obj), TYPE_ARM_GIC_COMMON) + +typedef struct ARMGICCommonClass { +    /*< private >*/ +    SysBusDeviceClass parent_class; +    /*< public >*/ + +    void (*pre_save)(GICState *s); +    void (*post_load)(GICState *s); +} ARMGICCommonClass; + +#endif diff --git a/include/hw/intc/realview_gic.h b/include/hw/intc/realview_gic.h new file mode 100644 index 00000000..1783ea11 --- /dev/null +++ b/include/hw/intc/realview_gic.h @@ -0,0 +1,28 @@ +/* + * ARM RealView Emulation Baseboard Interrupt Controller + * + * Copyright (c) 2006-2007 CodeSourcery. + * Written by Paul Brook + * + * This code is licensed under the GPL. + */ + +#ifndef HW_INTC_REALVIEW_GIC_H +#define HW_INTC_REALVIEW_GIC_H + +#include "hw/sysbus.h" +#include "hw/intc/arm_gic.h" + +#define TYPE_REALVIEW_GIC "realview_gic" +#define REALVIEW_GIC(obj) \ +    OBJECT_CHECK(RealViewGICState, (obj), TYPE_REALVIEW_GIC) + +typedef struct RealViewGICState { +    SysBusDevice parent_obj; + +    MemoryRegion container; + +    GICState gic; +} RealViewGICState; + +#endif diff --git a/include/hw/ipack/ipack.h b/include/hw/ipack/ipack.h new file mode 100644 index 00000000..e95ffe82 --- /dev/null +++ b/include/hw/ipack/ipack.h @@ -0,0 +1,87 @@ +/* + * QEMU IndustryPack emulation + * + * Copyright (C) 2012 Igalia, S.L. + * Author: Alberto Garcia <agarcia@igalia.com> + * + * This code is licensed under the GNU GPL v2 or (at your option) any + * later version. + */ + +#ifndef QEMU_IPACK_H +#define QEMU_IPACK_H + +#include "hw/qdev.h" + +typedef struct IPackBus IPackBus; + +#define TYPE_IPACK_BUS "IndustryPack" +#define IPACK_BUS(obj) OBJECT_CHECK(IPackBus, (obj), TYPE_IPACK_BUS) + +struct IPackBus { +    /*< private >*/ +    BusState parent_obj; + +    /* All fields are private */ +    uint8_t n_slots; +    uint8_t free_slot; +    qemu_irq_handler set_irq; +}; + +typedef struct IPackDevice IPackDevice; +typedef struct IPackDeviceClass IPackDeviceClass; + +#define TYPE_IPACK_DEVICE "ipack-device" +#define IPACK_DEVICE(obj) \ +     OBJECT_CHECK(IPackDevice, (obj), TYPE_IPACK_DEVICE) +#define IPACK_DEVICE_CLASS(klass)                                        \ +     OBJECT_CLASS_CHECK(IPackDeviceClass, (klass), TYPE_IPACK_DEVICE) +#define IPACK_DEVICE_GET_CLASS(obj) \ +     OBJECT_GET_CLASS(IPackDeviceClass, (obj), TYPE_IPACK_DEVICE) + +struct IPackDeviceClass { +    /*< private >*/ +    DeviceClass parent_class; +    /*< public >*/ + +    DeviceRealize realize; +    DeviceUnrealize unrealize; + +    uint16_t (*io_read)(IPackDevice *dev, uint8_t addr); +    void (*io_write)(IPackDevice *dev, uint8_t addr, uint16_t val); + +    uint16_t (*id_read)(IPackDevice *dev, uint8_t addr); +    void (*id_write)(IPackDevice *dev, uint8_t addr, uint16_t val); + +    uint16_t (*int_read)(IPackDevice *dev, uint8_t addr); +    void (*int_write)(IPackDevice *dev, uint8_t addr, uint16_t val); + +    uint16_t (*mem_read16)(IPackDevice *dev, uint32_t addr); +    void (*mem_write16)(IPackDevice *dev, uint32_t addr, uint16_t val); + +    uint8_t (*mem_read8)(IPackDevice *dev, uint32_t addr); +    void (*mem_write8)(IPackDevice *dev, uint32_t addr, uint8_t val); +}; + +struct IPackDevice { +    /*< private >*/ +    DeviceState parent_obj; +    /*< public >*/ + +    int32_t slot; +    /* IRQ objects for the IndustryPack INT0# and INT1# */ +    qemu_irq *irq; +}; + +extern const VMStateDescription vmstate_ipack_device; + +#define VMSTATE_IPACK_DEVICE(_field, _state)                            \ +    VMSTATE_STRUCT(_field, _state, 1, vmstate_ipack_device, IPackDevice) + +IPackDevice *ipack_device_find(IPackBus *bus, int32_t slot); +void ipack_bus_new_inplace(IPackBus *bus, size_t bus_size, +                           DeviceState *parent, +                           const char *name, uint8_t n_slots, +                           qemu_irq_handler handler); + +#endif diff --git a/include/hw/irq.h b/include/hw/irq.h new file mode 100644 index 00000000..4c4c2eaf --- /dev/null +++ b/include/hw/irq.h @@ -0,0 +1,65 @@ +#ifndef QEMU_IRQ_H +#define QEMU_IRQ_H + +/* Generic IRQ/GPIO pin infrastructure.  */ + +#define TYPE_IRQ "irq" + +typedef struct IRQState *qemu_irq; + +typedef void (*qemu_irq_handler)(void *opaque, int n, int level); + +void qemu_set_irq(qemu_irq irq, int level); + +static inline void qemu_irq_raise(qemu_irq irq) +{ +    qemu_set_irq(irq, 1); +} + +static inline void qemu_irq_lower(qemu_irq irq) +{ +    qemu_set_irq(irq, 0); +} + +static inline void qemu_irq_pulse(qemu_irq irq) +{ +    qemu_set_irq(irq, 1); +    qemu_set_irq(irq, 0); +} + +/* Returns an array of N IRQs. Each IRQ is assigned the argument handler and + * opaque data. + */ +qemu_irq *qemu_allocate_irqs(qemu_irq_handler handler, void *opaque, int n); + +/* + * Allocates a single IRQ. The irq is assigned with a handler, an opaque + * data and the interrupt number. + */ +qemu_irq qemu_allocate_irq(qemu_irq_handler handler, void *opaque, int n); + +/* Extends an Array of IRQs. Old IRQs have their handlers and opaque data + * preserved. New IRQs are assigned the argument handler and opaque data. + */ +qemu_irq *qemu_extend_irqs(qemu_irq *old, int n_old, qemu_irq_handler handler, +                                void *opaque, int n); + +void qemu_free_irqs(qemu_irq *s, int n); +void qemu_free_irq(qemu_irq irq); + +/* Returns a new IRQ with opposite polarity.  */ +qemu_irq qemu_irq_invert(qemu_irq irq); + +/* Returns a new IRQ which feeds into both the passed IRQs */ +qemu_irq qemu_irq_split(qemu_irq irq1, qemu_irq irq2); + +/* Returns a new IRQ set which connects 1:1 to another IRQ set, which + * may be set later. + */ +qemu_irq *qemu_irq_proxy(qemu_irq **target, int n); + +/* For internal use in qtest.  Similar to qemu_irq_split, but operating +   on an existing vector of qemu_irq.  */ +void qemu_irq_intercept_in(qemu_irq *gpio_in, qemu_irq_handler handler, int n); + +#endif diff --git a/include/hw/isa/apm.h b/include/hw/isa/apm.h new file mode 100644 index 00000000..3edea5f6 --- /dev/null +++ b/include/hw/isa/apm.h @@ -0,0 +1,25 @@ +#ifndef APM_H +#define APM_H + +#include <stdint.h> +#include "qemu-common.h" +#include "hw/hw.h" +#include "exec/memory.h" + +typedef void (*apm_ctrl_changed_t)(uint32_t val, void *arg); + +typedef struct APMState { +    uint8_t apmc; +    uint8_t apms; + +    apm_ctrl_changed_t callback; +    void *arg; +    MemoryRegion io; +} APMState; + +void apm_init(PCIDevice *dev, APMState *s, apm_ctrl_changed_t callback, +              void *arg); + +extern const VMStateDescription vmstate_apm; + +#endif /* APM_H */ diff --git a/include/hw/isa/i8259_internal.h b/include/hw/isa/i8259_internal.h new file mode 100644 index 00000000..cded5096 --- /dev/null +++ b/include/hw/isa/i8259_internal.h @@ -0,0 +1,83 @@ +/* + * QEMU 8259 - internal interfaces + * + * Copyright (c) 2011 Jan Kiszka, Siemens AG + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * 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 OTHER + * 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. + */ + +#ifndef QEMU_I8259_INTERNAL_H +#define QEMU_I8259_INTERNAL_H + +#include "hw/hw.h" +#include "hw/i386/pc.h" +#include "hw/isa/isa.h" + +typedef struct PICCommonState PICCommonState; + +#define TYPE_PIC_COMMON "pic-common" +#define PIC_COMMON(obj) \ +     OBJECT_CHECK(PICCommonState, (obj), TYPE_PIC_COMMON) +#define PIC_COMMON_CLASS(klass) \ +     OBJECT_CLASS_CHECK(PICCommonClass, (klass), TYPE_PIC_COMMON) +#define PIC_COMMON_GET_CLASS(obj) \ +     OBJECT_GET_CLASS(PICCommonClass, (obj), TYPE_PIC_COMMON) + +typedef struct PICCommonClass +{ +    ISADeviceClass parent_class; + +    void (*pre_save)(PICCommonState *s); +    void (*post_load)(PICCommonState *s); +} PICCommonClass; + +struct PICCommonState { +    ISADevice parent_obj; + +    uint8_t last_irr; /* edge detection */ +    uint8_t irr; /* interrupt request register */ +    uint8_t imr; /* interrupt mask register */ +    uint8_t isr; /* interrupt service register */ +    uint8_t priority_add; /* highest irq priority */ +    uint8_t irq_base; +    uint8_t read_reg_select; +    uint8_t poll; +    uint8_t special_mask; +    uint8_t init_state; +    uint8_t auto_eoi; +    uint8_t rotate_on_auto_eoi; +    uint8_t special_fully_nested_mode; +    uint8_t init4; /* true if 4 byte init */ +    uint8_t single_mode; /* true if slave pic is not initialized */ +    uint8_t elcr; /* PIIX edge/trigger selection*/ +    uint8_t elcr_mask; +    qemu_irq int_out[1]; +    uint32_t master; /* reflects /SP input pin */ +    uint32_t iobase; +    uint32_t elcr_addr; +    MemoryRegion base_io; +    MemoryRegion elcr_io; +}; + +void pic_reset_common(PICCommonState *s); + +ISADevice *i8259_init_chip(const char *name, ISABus *bus, bool master); + + +#endif /* !QEMU_I8259_INTERNAL_H */ diff --git a/include/hw/isa/isa.h b/include/hw/isa/isa.h new file mode 100644 index 00000000..f21ceaaf --- /dev/null +++ b/include/hw/isa/isa.h @@ -0,0 +1,120 @@ +#ifndef HW_ISA_H +#define HW_ISA_H + +/* ISA bus */ + +#include "exec/ioport.h" +#include "exec/memory.h" +#include "hw/qdev.h" + +#define ISA_NUM_IRQS 16 + +#define TYPE_ISA_DEVICE "isa-device" +#define ISA_DEVICE(obj) \ +     OBJECT_CHECK(ISADevice, (obj), TYPE_ISA_DEVICE) +#define ISA_DEVICE_CLASS(klass) \ +     OBJECT_CLASS_CHECK(ISADeviceClass, (klass), TYPE_ISA_DEVICE) +#define ISA_DEVICE_GET_CLASS(obj) \ +     OBJECT_GET_CLASS(ISADeviceClass, (obj), TYPE_ISA_DEVICE) + +#define TYPE_ISA_BUS "ISA" +#define ISA_BUS(obj) OBJECT_CHECK(ISABus, (obj), TYPE_ISA_BUS) + +#define TYPE_APPLE_SMC "isa-applesmc" +#define APPLESMC_MAX_DATA_LENGTH       32 +#define APPLESMC_PROP_IO_BASE "iobase" + +static inline uint16_t applesmc_port(void) +{ +    Object *obj = object_resolve_path_type("", TYPE_APPLE_SMC, NULL); + +    if (obj) { +        return object_property_get_int(obj, APPLESMC_PROP_IO_BASE, NULL); +    } +    return 0; +} + +typedef struct ISADeviceClass { +    DeviceClass parent_class; +} ISADeviceClass; + +struct ISABus { +    /*< private >*/ +    BusState parent_obj; +    /*< public >*/ + +    MemoryRegion *address_space; +    MemoryRegion *address_space_io; +    qemu_irq *irqs; +}; + +struct ISADevice { +    /*< private >*/ +    DeviceState parent_obj; +    /*< public >*/ + +    uint32_t isairq[2]; +    int nirqs; +    int ioport_id; +}; + +ISABus *isa_bus_new(DeviceState *dev, MemoryRegion *address_space, +                    MemoryRegion *address_space_io); +void isa_bus_irqs(ISABus *bus, qemu_irq *irqs); +qemu_irq isa_get_irq(ISADevice *dev, int isairq); +void isa_init_irq(ISADevice *dev, qemu_irq *p, int isairq); +MemoryRegion *isa_address_space(ISADevice *dev); +MemoryRegion *isa_address_space_io(ISADevice *dev); +ISADevice *isa_create(ISABus *bus, const char *name); +ISADevice *isa_try_create(ISABus *bus, const char *name); +ISADevice *isa_create_simple(ISABus *bus, const char *name); + +ISADevice *isa_vga_init(ISABus *bus); + +/** + * isa_register_ioport: Install an I/O port region on the ISA bus. + * + * Register an I/O port region via memory_region_add_subregion + * inside the ISA I/O address space. + * + * @dev: the ISADevice against which these are registered; may be NULL. + * @io: the #MemoryRegion being registered. + * @start: the base I/O port. + */ +void isa_register_ioport(ISADevice *dev, MemoryRegion *io, uint16_t start); + +/** + * isa_register_portio_list: Initialize a set of ISA io ports + * + * Several ISA devices have many dis-joint I/O ports.  Worse, these I/O + * ports can be interleaved with I/O ports from other devices.  This + * function makes it easy to create multiple MemoryRegions for a single + * device and use the legacy portio routines. + * + * @dev: the ISADevice against which these are registered; may be NULL. + * @start: the base I/O port against which the portio->offset is applied. + * @portio: the ports, sorted by offset. + * @opaque: passed into the portio callbacks. + * @name: passed into memory_region_init_io. + */ +void isa_register_portio_list(ISADevice *dev, uint16_t start, +                              const MemoryRegionPortio *portio, +                              void *opaque, const char *name); + +static inline ISABus *isa_bus_from_device(ISADevice *d) +{ +    return ISA_BUS(qdev_get_parent_bus(DEVICE(d))); +} + +/* dma.c */ +int DMA_get_channel_mode (int nchan); +int DMA_read_memory (int nchan, void *buf, int pos, int size); +int DMA_write_memory (int nchan, void *buf, int pos, int size); +void DMA_hold_DREQ (int nchan); +void DMA_release_DREQ (int nchan); +void DMA_schedule(int nchan); +void DMA_init(int high_page_enable, qemu_irq *cpu_request_exit); +void DMA_register_channel (int nchan, +                           DMA_transfer_handler transfer_handler, +                           void *opaque); +#endif diff --git a/include/hw/isa/pc87312.h b/include/hw/isa/pc87312.h new file mode 100644 index 00000000..bf74470d --- /dev/null +++ b/include/hw/isa/pc87312.h @@ -0,0 +1,65 @@ +/* + * QEMU National Semiconductor PC87312 (Super I/O) + * + * Copyright (c) 2010-2012 Herve Poussineau + * Copyright (c) 2011-2012 Andreas Färber + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * 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 OTHER + * 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. + */ +#ifndef QEMU_PC87312_H +#define QEMU_PC87312_H + +#include "hw/isa/isa.h" + + +#define TYPE_PC87312 "pc87312" +#define PC87312(obj) OBJECT_CHECK(PC87312State, (obj), TYPE_PC87312) + +typedef struct PC87312State { +    ISADevice dev; + +    uint32_t iobase; +    uint8_t config; /* initial configuration */ + +    struct { +        ISADevice *dev; +    } parallel; + +    struct { +        ISADevice *dev; +    } uart[2]; + +    struct { +        ISADevice *dev; +    } fdc; + +    struct { +        ISADevice *dev; +    } ide; + +    MemoryRegion io; + +    uint8_t read_id_step; +    uint8_t selected_index; + +    uint8_t regs[3]; +} PC87312State; + + +#endif diff --git a/include/hw/isa/vt82c686.h b/include/hw/isa/vt82c686.h new file mode 100644 index 00000000..471b5e9e --- /dev/null +++ b/include/hw/isa/vt82c686.h @@ -0,0 +1,11 @@ +#ifndef HW_VT82C686_H +#define HW_VT82C686_H + +/* vt82c686.c */ +ISABus *vt82c686b_init(PCIBus * bus, int devfn); +void vt82c686b_ac97_init(PCIBus *bus, int devfn); +void vt82c686b_mc97_init(PCIBus *bus, int devfn); +I2CBus *vt82c686b_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base, +                          qemu_irq sci_irq); + +#endif diff --git a/include/hw/kvm/clock.h b/include/hw/kvm/clock.h new file mode 100644 index 00000000..252ea134 --- /dev/null +++ b/include/hw/kvm/clock.h @@ -0,0 +1,24 @@ +/* + * QEMU KVM support, paravirtual clock device + * + * Copyright (C) 2011 Siemens AG + * + * Authors: + *  Jan Kiszka        <jan.kiszka@siemens.com> + * + * This work is licensed under the terms of the GNU GPL version 2. + * See the COPYING file in the top-level directory. + * + */ + +#ifdef CONFIG_KVM + +void kvmclock_create(void); + +#else /* CONFIG_KVM */ + +static inline void kvmclock_create(void) +{ +} + +#endif /* !CONFIG_KVM */ diff --git a/include/hw/lm32/lm32_pic.h b/include/hw/lm32/lm32_pic.h new file mode 100644 index 00000000..189fa386 --- /dev/null +++ b/include/hw/lm32/lm32_pic.h @@ -0,0 +1,14 @@ +#ifndef QEMU_HW_LM32_PIC_H +#define QEMU_HW_LM32_PIC_H + +#include "qemu-common.h" + +uint32_t lm32_pic_get_ip(DeviceState *d); +uint32_t lm32_pic_get_im(DeviceState *d); +void lm32_pic_set_ip(DeviceState *d, uint32_t ip); +void lm32_pic_set_im(DeviceState *d, uint32_t im); + +void lm32_hmp_info_pic(Monitor *mon, const QDict *qdict); +void lm32_hmp_info_irq(Monitor *mon, const QDict *qdict); + +#endif /* QEMU_HW_LM32_PIC_H */ diff --git a/include/hw/loader.h b/include/hw/loader.h new file mode 100644 index 00000000..f7b43ab6 --- /dev/null +++ b/include/hw/loader.h @@ -0,0 +1,98 @@ +#ifndef LOADER_H +#define LOADER_H +#include "qapi/qmp/qdict.h" +#include "hw/nvram/fw_cfg.h" + +/* loader.c */ +/** + * get_image_size: retrieve size of an image file + * @filename: Path to the image file + * + * Returns the size of the image file on success, -1 otherwise. + * On error, errno is also set as appropriate. + */ +int get_image_size(const char *filename); +int load_image(const char *filename, uint8_t *addr); /* deprecated */ +ssize_t load_image_size(const char *filename, void *addr, size_t size); +int load_image_targphys(const char *filename, hwaddr, +                        uint64_t max_sz); + +/* This is the limit on the maximum uncompressed image size that + * load_image_gzipped_buffer() and load_image_gzipped() will read. It prevents + * g_malloc() in those functions from allocating a huge amount of memory. + */ +#define LOAD_IMAGE_MAX_GUNZIP_BYTES (256 << 20) + +int load_image_gzipped_buffer(const char *filename, uint64_t max_sz, +                              uint8_t **buffer); +int load_image_gzipped(const char *filename, hwaddr addr, uint64_t max_sz); + +#define ELF_LOAD_FAILED       -1 +#define ELF_LOAD_NOT_ELF      -2 +#define ELF_LOAD_WRONG_ARCH   -3 +#define ELF_LOAD_WRONG_ENDIAN -4 +const char *load_elf_strerror(int error); +int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t), +             void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr, +             uint64_t *highaddr, int big_endian, int elf_machine, +             int clear_lsb); +int load_aout(const char *filename, hwaddr addr, int max_sz, +              int bswap_needed, hwaddr target_page_size); +int load_uimage(const char *filename, hwaddr *ep, +                hwaddr *loadaddr, int *is_linux, +                uint64_t (*translate_fn)(void *, uint64_t), +                void *translate_opaque); + +/** + * load_ramdisk: + * @filename: Path to the ramdisk image + * @addr: Memory address to load the ramdisk to + * @max_sz: Maximum allowed ramdisk size (for non-u-boot ramdisks) + * + * Load a ramdisk image with U-Boot header to the specified memory + * address. + * + * Returns the size of the loaded image on success, -1 otherwise. + */ +int load_ramdisk(const char *filename, hwaddr addr, uint64_t max_sz); + +ssize_t read_targphys(const char *name, +                      int fd, hwaddr dst_addr, size_t nbytes); +void pstrcpy_targphys(const char *name, +                      hwaddr dest, int buf_size, +                      const char *source); + +extern bool option_rom_has_mr; +extern bool rom_file_has_mr; + +int rom_add_file(const char *file, const char *fw_dir, +                 hwaddr addr, int32_t bootindex, +                 bool option_rom); +MemoryRegion *rom_add_blob(const char *name, const void *blob, size_t len, +                           size_t max_len, hwaddr addr, +                           const char *fw_file_name, +                           FWCfgReadCallback fw_callback, +                           void *callback_opaque); +int rom_add_elf_program(const char *name, void *data, size_t datasize, +                        size_t romsize, hwaddr addr); +int rom_check_and_register_reset(void); +void rom_set_fw(FWCfgState *f); +int rom_copy(uint8_t *dest, hwaddr addr, size_t size); +void *rom_ptr(hwaddr addr); +void hmp_info_roms(Monitor *mon, const QDict *qdict); + +#define rom_add_file_fixed(_f, _a, _i)          \ +    rom_add_file(_f, NULL, _a, _i, false) +#define rom_add_blob_fixed(_f, _b, _l, _a)      \ +    rom_add_blob(_f, _b, _l, _l, _a, NULL, NULL, NULL) + +#define PC_ROM_MIN_VGA     0xc0000 +#define PC_ROM_MIN_OPTION  0xc8000 +#define PC_ROM_MAX         0xe0000 +#define PC_ROM_ALIGN       0x800 +#define PC_ROM_SIZE        (PC_ROM_MAX - PC_ROM_MIN_VGA) + +int rom_add_vga(const char *file); +int rom_add_option(const char *file, int32_t bootindex); + +#endif diff --git a/include/hw/m68k/mcf.h b/include/hw/m68k/mcf.h new file mode 100644 index 00000000..fbc8dc26 --- /dev/null +++ b/include/hw/m68k/mcf.h @@ -0,0 +1,30 @@ +#ifndef HW_MCF_H +#define HW_MCF_H +/* Motorola ColdFire device prototypes.  */ + +struct MemoryRegion; + +/* mcf_uart.c */ +uint64_t mcf_uart_read(void *opaque, hwaddr addr, +                       unsigned size); +void mcf_uart_write(void *opaque, hwaddr addr, +                    uint64_t val, unsigned size); +void *mcf_uart_init(qemu_irq irq, CharDriverState *chr); +void mcf_uart_mm_init(struct MemoryRegion *sysmem, +                      hwaddr base, +                      qemu_irq irq, CharDriverState *chr); + +/* mcf_intc.c */ +qemu_irq *mcf_intc_init(struct MemoryRegion *sysmem, +                        hwaddr base, +                        M68kCPU *cpu); + +/* mcf_fec.c */ +void mcf_fec_init(struct MemoryRegion *sysmem, NICInfo *nd, +                  hwaddr base, qemu_irq *irq); + +/* mcf5206.c */ +qemu_irq *mcf5206_init(struct MemoryRegion *sysmem, +                       uint32_t base, M68kCPU *cpu); + +#endif diff --git a/include/hw/mem/pc-dimm.h b/include/hw/mem/pc-dimm.h new file mode 100644 index 00000000..d83bf30e --- /dev/null +++ b/include/hw/mem/pc-dimm.h @@ -0,0 +1,97 @@ +/* + * PC DIMM device + * + * Copyright ProfitBricks GmbH 2012 + * Copyright (C) 2013-2014 Red Hat Inc + * + * Authors: + *  Vasilis Liaskovitis <vasilis.liaskovitis@profitbricks.com> + *  Igor Mammedov <imammedo@redhat.com> + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ + +#ifndef QEMU_PC_DIMM_H +#define QEMU_PC_DIMM_H + +#include "exec/memory.h" +#include "sysemu/hostmem.h" +#include "hw/qdev.h" + +#define DEFAULT_PC_DIMMSIZE (1024*1024*1024) + +#define TYPE_PC_DIMM "pc-dimm" +#define PC_DIMM(obj) \ +    OBJECT_CHECK(PCDIMMDevice, (obj), TYPE_PC_DIMM) +#define PC_DIMM_CLASS(oc) \ +    OBJECT_CLASS_CHECK(PCDIMMDeviceClass, (oc), TYPE_PC_DIMM) +#define PC_DIMM_GET_CLASS(obj) \ +    OBJECT_GET_CLASS(PCDIMMDeviceClass, (obj), TYPE_PC_DIMM) + +#define PC_DIMM_ADDR_PROP "addr" +#define PC_DIMM_SLOT_PROP "slot" +#define PC_DIMM_NODE_PROP "node" +#define PC_DIMM_SIZE_PROP "size" +#define PC_DIMM_MEMDEV_PROP "memdev" + +#define PC_DIMM_UNASSIGNED_SLOT -1 + +/** + * PCDIMMDevice: + * @addr: starting guest physical address, where @PCDIMMDevice is mapped. + *         Default value: 0, means that address is auto-allocated. + * @node: numa node to which @PCDIMMDevice is attached. + * @slot: slot number into which @PCDIMMDevice is plugged in. + *        Default value: -1, means that slot is auto-allocated. + * @hostmem: host memory backend providing memory for @PCDIMMDevice + */ +typedef struct PCDIMMDevice { +    /* private */ +    DeviceState parent_obj; + +    /* public */ +    uint64_t addr; +    uint32_t node; +    int32_t slot; +    HostMemoryBackend *hostmem; +} PCDIMMDevice; + +/** + * PCDIMMDeviceClass: + * @get_memory_region: returns #MemoryRegion associated with @dimm + */ +typedef struct PCDIMMDeviceClass { +    /* private */ +    DeviceClass parent_class; + +    /* public */ +    MemoryRegion *(*get_memory_region)(PCDIMMDevice *dimm); +} PCDIMMDeviceClass; + +/** + * MemoryHotplugState: + * @base: address in guest RAM address space where hotplug memory + * address space begins. + * @mr: hotplug memory address space container + */ +typedef struct MemoryHotplugState { +    ram_addr_t base; +    MemoryRegion mr; +} MemoryHotplugState; + +uint64_t pc_dimm_get_free_addr(uint64_t address_space_start, +                               uint64_t address_space_size, +                               uint64_t *hint, uint64_t align, uint64_t size, +                               Error **errp); + +int pc_dimm_get_free_slot(const int *hint, int max_slots, Error **errp); + +int qmp_pc_dimm_device_list(Object *obj, void *opaque); +uint64_t pc_existing_dimms_capacity(Error **errp); +void pc_dimm_memory_plug(DeviceState *dev, MemoryHotplugState *hpms, +                         MemoryRegion *mr, uint64_t align, Error **errp); +void pc_dimm_memory_unplug(DeviceState *dev, MemoryHotplugState *hpms, +                           MemoryRegion *mr); +#endif diff --git a/include/hw/mips/bios.h b/include/hw/mips/bios.h new file mode 100644 index 00000000..b4b88ac4 --- /dev/null +++ b/include/hw/mips/bios.h @@ -0,0 +1,8 @@ +#include "cpu.h" + +#define BIOS_SIZE (4 * 1024 * 1024) +#ifdef TARGET_WORDS_BIGENDIAN +#define BIOS_FILENAME "mips_bios.bin" +#else +#define BIOS_FILENAME "mipsel_bios.bin" +#endif diff --git a/include/hw/mips/cpudevs.h b/include/hw/mips/cpudevs.h new file mode 100644 index 00000000..b2626f29 --- /dev/null +++ b/include/hw/mips/cpudevs.h @@ -0,0 +1,17 @@ +#ifndef HW_MIPS_CPUDEVS_H +#define HW_MIPS_CPUDEVS_H +/* Definitions for MIPS CPU internal devices.  */ + +/* mips_addr.c */ +uint64_t cpu_mips_kseg0_to_phys(void *opaque, uint64_t addr); +uint64_t cpu_mips_phys_to_kseg0(void *opaque, uint64_t addr); +uint64_t cpu_mips_kvm_um_phys_to_kseg0(void *opaque, uint64_t addr); + + +/* mips_int.c */ +void cpu_mips_irq_init_cpu(CPUMIPSState *env); + +/* mips_timer.c */ +void cpu_mips_clock_init(CPUMIPSState *); + +#endif diff --git a/include/hw/mips/mips.h b/include/hw/mips/mips.h new file mode 100644 index 00000000..e0065ce8 --- /dev/null +++ b/include/hw/mips/mips.h @@ -0,0 +1,23 @@ +#ifndef HW_MIPS_H +#define HW_MIPS_H +/* Definitions for mips board emulation.  */ + +/* Kernels can be configured with 64KB pages */ +#define INITRD_PAGE_MASK (~((1 << 16) - 1)) + +#include "exec/memory.h" + +/* gt64xxx.c */ +PCIBus *gt64120_register(qemu_irq *pic); + +/* bonito.c */ +PCIBus *bonito_init(qemu_irq *pic); + +/* rc4030.c */ +typedef struct rc4030DMAState *rc4030_dma; +void rc4030_dma_read(void *dma, uint8_t *buf, int len); +void rc4030_dma_write(void *dma, uint8_t *buf, int len); + +DeviceState *rc4030_init(rc4030_dma **dmas, MemoryRegion **dma_mr); + +#endif diff --git a/include/hw/misc/a9scu.h b/include/hw/misc/a9scu.h new file mode 100644 index 00000000..efb0c305 --- /dev/null +++ b/include/hw/misc/a9scu.h @@ -0,0 +1,31 @@ +/* + * Cortex-A9MPCore Snoop Control Unit (SCU) emulation. + * + * Copyright (c) 2009 CodeSourcery. + * Copyright (c) 2011 Linaro Limited. + * Written by Paul Brook, Peter Maydell. + * + * This code is licensed under the GPL. + */ +#ifndef HW_MISC_A9SCU_H +#define HW_MISC_A9SCU_H + +#include "hw/sysbus.h" + +/* A9MP private memory region.  */ + +typedef struct A9SCUState { +    /*< private >*/ +    SysBusDevice parent_obj; +    /*< public >*/ + +    MemoryRegion iomem; +    uint32_t control; +    uint32_t status; +    uint32_t num_cpu; +} A9SCUState; + +#define TYPE_A9_SCU "a9-scu" +#define A9_SCU(obj) OBJECT_CHECK(A9SCUState, (obj), TYPE_A9_SCU) + +#endif diff --git a/include/hw/misc/arm11scu.h b/include/hw/misc/arm11scu.h new file mode 100644 index 00000000..5ad0f3d3 --- /dev/null +++ b/include/hw/misc/arm11scu.h @@ -0,0 +1,29 @@ +/* + * ARM11MPCore Snoop Control Unit (SCU) emulation + * + * Copyright (c) 2006-2007 CodeSourcery. + * Copyright (c) 2013 SUSE LINUX Products GmbH + * Written by Paul Brook and Andreas Färber + * + * This code is licensed under the GPL. + */ + +#ifndef HW_MISC_ARM11SCU_H +#define HW_MISC_ARM11SCU_H + +#include "hw/sysbus.h" + +#define TYPE_ARM11_SCU "arm11-scu" +#define ARM11_SCU(obj) OBJECT_CHECK(ARM11SCUState, (obj), TYPE_ARM11_SCU) + +typedef struct ARM11SCUState { +    /*< private >*/ +    SysBusDevice parent_obj; +    /*< public >*/ + +    uint32_t control; +    uint32_t num_cpu; +    MemoryRegion iomem; +} ARM11SCUState; + +#endif diff --git a/include/hw/misc/arm_integrator_debug.h b/include/hw/misc/arm_integrator_debug.h new file mode 100644 index 00000000..37789b69 --- /dev/null +++ b/include/hw/misc/arm_integrator_debug.h @@ -0,0 +1,18 @@ +/* + * ARM Integrator Board Debug, switch and LED section + * + * Browse the data sheet: + * + *    http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0159b/Babbfijf.html + * + * Copyright (c) 2013 Alex Bennée <alex@bennee.com> + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ +#ifndef QEMU_INTEGRATOR_DEBUG_H +#define QEMU_INTEGRATOR_DEBUG_H + +#define TYPE_INTEGRATOR_DEBUG "integrator_debug" + +#endif diff --git a/include/hw/misc/stm32f2xx_syscfg.h b/include/hw/misc/stm32f2xx_syscfg.h new file mode 100644 index 00000000..69e6a30f --- /dev/null +++ b/include/hw/misc/stm32f2xx_syscfg.h @@ -0,0 +1,61 @@ +/* + * STM32F2XX SYSCFG + * + * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me> + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * 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 OTHER + * 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. + */ + +#ifndef HW_STM32F2XX_SYSCFG_H +#define HW_STM32F2XX_SYSCFG_H + +#include "hw/sysbus.h" +#include "hw/hw.h" + +#define SYSCFG_MEMRMP  0x00 +#define SYSCFG_PMC     0x04 +#define SYSCFG_EXTICR1 0x08 +#define SYSCFG_EXTICR2 0x0C +#define SYSCFG_EXTICR3 0x10 +#define SYSCFG_EXTICR4 0x14 +#define SYSCFG_CMPCR   0x20 + +#define TYPE_STM32F2XX_SYSCFG "stm32f2xx-syscfg" +#define STM32F2XX_SYSCFG(obj) \ +    OBJECT_CHECK(STM32F2XXSyscfgState, (obj), TYPE_STM32F2XX_SYSCFG) + +typedef struct { +    /* <private> */ +    SysBusDevice parent_obj; + +    /* <public> */ +    MemoryRegion mmio; + +    uint32_t syscfg_memrmp; +    uint32_t syscfg_pmc; +    uint32_t syscfg_exticr1; +    uint32_t syscfg_exticr2; +    uint32_t syscfg_exticr3; +    uint32_t syscfg_exticr4; +    uint32_t syscfg_cmpcr; + +    qemu_irq irq; +} STM32F2XXSyscfgState; + +#endif /* HW_STM32F2XX_SYSCFG_H */ diff --git a/include/hw/misc/tmp105_regs.h b/include/hw/misc/tmp105_regs.h new file mode 100644 index 00000000..9b55abaf --- /dev/null +++ b/include/hw/misc/tmp105_regs.h @@ -0,0 +1,50 @@ +/* + * Texas Instruments TMP105 Temperature Sensor I2C messages + * + * Browse the data sheet: + * + *    http://www.ti.com/lit/gpn/tmp105 + * + * Copyright (C) 2012 Alex Horn <alex.horn@cs.ox.ac.uk> + * Copyright (C) 2008-2012 Andrzej Zaborowski <balrogg@gmail.com> + * + * This work is licensed under the terms of the GNU GPL, version 2 or + * later. See the COPYING file in the top-level directory. + */ +#ifndef QEMU_TMP105_MSGS_H +#define QEMU_TMP105_MSGS_H + +/** + * TMP105Reg: + * @TMP105_REG_TEMPERATURE: Temperature register + * @TMP105_REG_CONFIG: Configuration register + * @TMP105_REG_T_LOW: Low temperature register (also known as T_hyst) + * @TMP105_REG_T_HIGH: High temperature register (also known as T_OS) + * + * The following temperature sensors are + * compatible with the TMP105 registers: + * - adt75 + * - ds1775 + * - ds75 + * - lm75 + * - lm75a + * - max6625 + * - max6626 + * - mcp980x + * - stds75 + * - tcn75 + * - tmp100 + * - tmp101 + * - tmp105 + * - tmp175 + * - tmp275 + * - tmp75 + **/ +typedef enum TMP105Reg { +    TMP105_REG_TEMPERATURE = 0, +    TMP105_REG_CONFIG, +    TMP105_REG_T_LOW, +    TMP105_REG_T_HIGH, +} TMP105Reg; + +#endif diff --git a/include/hw/net/allwinner_emac.h b/include/hw/net/allwinner_emac.h new file mode 100644 index 00000000..9f21aa7e --- /dev/null +++ b/include/hw/net/allwinner_emac.h @@ -0,0 +1,173 @@ +/* + * Emulation of Allwinner EMAC Fast Ethernet controller and + * Realtek RTL8201CP PHY + * + * Copyright (C) 2014 Beniamino Galvani <b.galvani@gmail.com> + * + * Allwinner EMAC register definitions from Linux kernel are: + *   Copyright 2012 Stefan Roese <sr@denx.de> + *   Copyright 2013 Maxime Ripard <maxime.ripard@free-electrons.com> + *   Copyright 1997 Sten Wang + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ +#ifndef AW_EMAC_H +#define AW_EMAC_H + +#include "net/net.h" +#include "qemu/fifo8.h" +#include "hw/net/mii.h" + +#define TYPE_AW_EMAC "allwinner-emac" +#define AW_EMAC(obj) OBJECT_CHECK(AwEmacState, (obj), TYPE_AW_EMAC) + +/* + * Allwinner EMAC register list + */ +#define EMAC_CTL_REG            0x00 + +#define EMAC_TX_MODE_REG        0x04 +#define EMAC_TX_FLOW_REG        0x08 +#define EMAC_TX_CTL0_REG        0x0C +#define EMAC_TX_CTL1_REG        0x10 +#define EMAC_TX_INS_REG         0x14 +#define EMAC_TX_PL0_REG         0x18 +#define EMAC_TX_PL1_REG         0x1C +#define EMAC_TX_STA_REG         0x20 +#define EMAC_TX_IO_DATA_REG     0x24 +#define EMAC_TX_IO_DATA1_REG    0x28 +#define EMAC_TX_TSVL0_REG       0x2C +#define EMAC_TX_TSVH0_REG       0x30 +#define EMAC_TX_TSVL1_REG       0x34 +#define EMAC_TX_TSVH1_REG       0x38 + +#define EMAC_RX_CTL_REG         0x3C +#define EMAC_RX_HASH0_REG       0x40 +#define EMAC_RX_HASH1_REG       0x44 +#define EMAC_RX_STA_REG         0x48 +#define EMAC_RX_IO_DATA_REG     0x4C +#define EMAC_RX_FBC_REG         0x50 + +#define EMAC_INT_CTL_REG        0x54 +#define EMAC_INT_STA_REG        0x58 + +#define EMAC_MAC_CTL0_REG       0x5C +#define EMAC_MAC_CTL1_REG       0x60 +#define EMAC_MAC_IPGT_REG       0x64 +#define EMAC_MAC_IPGR_REG       0x68 +#define EMAC_MAC_CLRT_REG       0x6C +#define EMAC_MAC_MAXF_REG       0x70 +#define EMAC_MAC_SUPP_REG       0x74 +#define EMAC_MAC_TEST_REG       0x78 +#define EMAC_MAC_MCFG_REG       0x7C +#define EMAC_MAC_MCMD_REG       0x80 +#define EMAC_MAC_MADR_REG       0x84 +#define EMAC_MAC_MWTD_REG       0x88 +#define EMAC_MAC_MRDD_REG       0x8C +#define EMAC_MAC_MIND_REG       0x90 +#define EMAC_MAC_SSRR_REG       0x94 +#define EMAC_MAC_A0_REG         0x98 +#define EMAC_MAC_A1_REG         0x9C +#define EMAC_MAC_A2_REG         0xA0 + +#define EMAC_SAFX_L_REG0        0xA4 +#define EMAC_SAFX_H_REG0        0xA8 +#define EMAC_SAFX_L_REG1        0xAC +#define EMAC_SAFX_H_REG1        0xB0 +#define EMAC_SAFX_L_REG2        0xB4 +#define EMAC_SAFX_H_REG2        0xB8 +#define EMAC_SAFX_L_REG3        0xBC +#define EMAC_SAFX_H_REG3        0xC0 + +/* CTL register fields */ +#define EMAC_CTL_RESET                  (1 << 0) +#define EMAC_CTL_TX_EN                  (1 << 1) +#define EMAC_CTL_RX_EN                  (1 << 2) + +/* TX MODE register fields */ +#define EMAC_TX_MODE_ABORTED_FRAME_EN   (1 << 0) +#define EMAC_TX_MODE_DMA_EN             (1 << 1) + +/* RX CTL register fields */ +#define EMAC_RX_CTL_AUTO_DRQ_EN         (1 << 1) +#define EMAC_RX_CTL_DMA_EN              (1 << 2) +#define EMAC_RX_CTL_PASS_ALL_EN         (1 << 4) +#define EMAC_RX_CTL_PASS_CTL_EN         (1 << 5) +#define EMAC_RX_CTL_PASS_CRC_ERR_EN     (1 << 6) +#define EMAC_RX_CTL_PASS_LEN_ERR_EN     (1 << 7) +#define EMAC_RX_CTL_PASS_LEN_OOR_EN     (1 << 8) +#define EMAC_RX_CTL_ACCEPT_UNICAST_EN   (1 << 16) +#define EMAC_RX_CTL_DA_FILTER_EN        (1 << 17) +#define EMAC_RX_CTL_ACCEPT_MULTICAST_EN (1 << 20) +#define EMAC_RX_CTL_HASH_FILTER_EN      (1 << 21) +#define EMAC_RX_CTL_ACCEPT_BROADCAST_EN (1 << 22) +#define EMAC_RX_CTL_SA_FILTER_EN        (1 << 24) +#define EMAC_RX_CTL_SA_FILTER_INVERT_EN (1 << 25) + +/* RX IO DATA register fields */ +#define EMAC_RX_HEADER(len, status)     (((len) & 0xffff) | ((status) << 16)) +#define EMAC_RX_IO_DATA_STATUS_CRC_ERR  (1 << 4) +#define EMAC_RX_IO_DATA_STATUS_LEN_ERR  (3 << 5) +#define EMAC_RX_IO_DATA_STATUS_OK       (1 << 7) +#define EMAC_UNDOCUMENTED_MAGIC         0x0143414d  /* header for RX frames */ + +/* INT CTL and INT STA registers fields */ +#define EMAC_INT_TX_CHAN(x) (1 << (x)) +#define EMAC_INT_RX         (1 << 8) + +/* Due to lack of specifications, size of fifos is chosen arbitrarily */ +#define TX_FIFO_SIZE        (4 * 1024) +#define RX_FIFO_SIZE        (32 * 1024) + +#define NUM_TX_FIFOS        2 +#define RX_HDR_SIZE         8 +#define CRC_SIZE            4 + +#define PHY_REG_SHIFT       0 +#define PHY_ADDR_SHIFT      8 + +typedef struct RTL8201CPState { +    uint16_t bmcr; +    uint16_t bmsr; +    uint16_t anar; +    uint16_t anlpar; +} RTL8201CPState; + +typedef struct AwEmacState { +    /*< private >*/ +    SysBusDevice  parent_obj; +    /*< public >*/ + +    MemoryRegion   iomem; +    qemu_irq       irq; +    NICState       *nic; +    NICConf        conf; +    RTL8201CPState mii; +    uint8_t        phy_addr; + +    uint32_t       ctl; +    uint32_t       tx_mode; +    uint32_t       rx_ctl; +    uint32_t       int_ctl; +    uint32_t       int_sta; +    uint32_t       phy_target; + +    Fifo8          rx_fifo; +    uint32_t       rx_num_packets; +    uint32_t       rx_packet_size; +    uint32_t       rx_packet_pos; + +    Fifo8          tx_fifo[NUM_TX_FIFOS]; +    uint32_t       tx_length[NUM_TX_FIFOS]; +    uint32_t       tx_channel; +} AwEmacState; + +#endif diff --git a/include/hw/net/cadence_gem.h b/include/hw/net/cadence_gem.h new file mode 100644 index 00000000..f2e08e35 --- /dev/null +++ b/include/hw/net/cadence_gem.h @@ -0,0 +1,73 @@ +/* + * QEMU Cadence GEM emulation + * + * Copyright (c) 2011 Xilinx, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * 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 OTHER + * 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. + */ + +#ifndef CADENCE_GEM_H + +#define TYPE_CADENCE_GEM "cadence_gem" +#define CADENCE_GEM(obj) OBJECT_CHECK(CadenceGEMState, (obj), TYPE_CADENCE_GEM) + +#include "net/net.h" +#include "hw/sysbus.h" + +#define CADENCE_GEM_MAXREG        (0x00000640/4) /* Last valid GEM address */ + +typedef struct CadenceGEMState { +    /*< private >*/ +    SysBusDevice parent_obj; + +    /*< public >*/ +    MemoryRegion iomem; +    NICState *nic; +    NICConf conf; +    qemu_irq irq; + +    /* GEM registers backing store */ +    uint32_t regs[CADENCE_GEM_MAXREG]; +    /* Mask of register bits which are write only */ +    uint32_t regs_wo[CADENCE_GEM_MAXREG]; +    /* Mask of register bits which are read only */ +    uint32_t regs_ro[CADENCE_GEM_MAXREG]; +    /* Mask of register bits which are clear on read */ +    uint32_t regs_rtc[CADENCE_GEM_MAXREG]; +    /* Mask of register bits which are write 1 to clear */ +    uint32_t regs_w1c[CADENCE_GEM_MAXREG]; + +    /* PHY registers backing store */ +    uint16_t phy_regs[32]; + +    uint8_t phy_loop; /* Are we in phy loopback? */ + +    /* The current DMA descriptor pointers */ +    uint32_t rx_desc_addr; +    uint32_t tx_desc_addr; + +    uint8_t can_rx_state; /* Debug only */ + +    unsigned rx_desc[2]; + +    bool sar_active[4]; +} CadenceGEMState; + +#define CADENCE_GEM_H +#endif diff --git a/include/hw/net/mii.h b/include/hw/net/mii.h new file mode 100644 index 00000000..9fdd7bbe --- /dev/null +++ b/include/hw/net/mii.h @@ -0,0 +1,76 @@ +/* + * Common network MII address and register definitions. + * + * Copyright (C) 2014 Beniamino Galvani <b.galvani@gmail.com> + * + * Allwinner EMAC register definitions from Linux kernel are: + *   Copyright 2012 Stefan Roese <sr@denx.de> + *   Copyright 2013 Maxime Ripard <maxime.ripard@free-electrons.com> + *   Copyright 1997 Sten Wang + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ +#ifndef MII_H +#define MII_H + +/* PHY registers */ +#define MII_BMCR            0 +#define MII_BMSR            1 +#define MII_PHYID1          2 +#define MII_PHYID2          3 +#define MII_ANAR            4 +#define MII_ANLPAR          5 +#define MII_ANER            6 +#define MII_NSR             16 +#define MII_LBREMR          17 +#define MII_REC             18 +#define MII_SNRDR           19 +#define MII_TEST            25 + +/* PHY registers fields */ +#define MII_BMCR_RESET      (1 << 15) +#define MII_BMCR_LOOPBACK   (1 << 14) +#define MII_BMCR_SPEED      (1 << 13) +#define MII_BMCR_AUTOEN     (1 << 12) +#define MII_BMCR_FD         (1 << 8) + +#define MII_BMSR_100TX_FD   (1 << 14) +#define MII_BMSR_100TX_HD   (1 << 13) +#define MII_BMSR_10T_FD     (1 << 12) +#define MII_BMSR_10T_HD     (1 << 11) +#define MII_BMSR_MFPS       (1 << 6) +#define MII_BMSR_AN_COMP    (1 << 5) +#define MII_BMSR_AUTONEG    (1 << 3) +#define MII_BMSR_LINK_ST    (1 << 2) + +#define MII_ANAR_TXFD       (1 << 8) +#define MII_ANAR_TX         (1 << 7) +#define MII_ANAR_10FD       (1 << 6) +#define MII_ANAR_10         (1 << 5) +#define MII_ANAR_CSMACD     (1 << 0) + +#define MII_ANLPAR_ACK      (1 << 14) +#define MII_ANLPAR_TXFD     (1 << 8) +#define MII_ANLPAR_TX       (1 << 7) +#define MII_ANLPAR_10FD     (1 << 6) +#define MII_ANLPAR_10       (1 << 5) +#define MII_ANLPAR_CSMACD   (1 << 0) + +/* List of vendor identifiers */ +/* RealTek 8201 */ +#define RTL8201CP_PHYID1    0x0000 +#define RTL8201CP_PHYID2    0x8201 + +/* National Semiconductor DP83848 */ +#define DP83848_PHYID1      0x2000 +#define DP83848_PHYID2      0x5c90 + +#endif /* MII_H */ diff --git a/include/hw/nmi.h b/include/hw/nmi.h new file mode 100644 index 00000000..f4cec625 --- /dev/null +++ b/include/hw/nmi.h @@ -0,0 +1,50 @@ +/* + *  NMI monitor handler class and helpers definitions. + * + *  Copyright IBM Corp., 2014 + * + *  Author: Alexey Kardashevskiy <aik@ozlabs.ru> + * + *  This program is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 2 of the License, + *  or (at your option) any later version. + * + *  This program is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef NMI_H +#define NMI_H 1 + +#include "qemu-common.h" +#include "qom/object.h" + +#define TYPE_NMI "nmi" + +#define NMI_CLASS(klass) \ +     OBJECT_CLASS_CHECK(NMIClass, (klass), TYPE_NMI) +#define NMI_GET_CLASS(obj) \ +    OBJECT_GET_CLASS(NMIClass, (obj), TYPE_NMI) +#define NMI(obj) \ +     INTERFACE_CHECK(NMI, (obj), TYPE_NMI) + +typedef struct NMIState { +    Object parent_obj; +} NMIState; + +typedef struct NMIClass { +    InterfaceClass parent_class; + +    void (*nmi_monitor_handler)(NMIState *n, int cpu_index, Error **errp); +} NMIClass; + +void nmi_monitor_handle(int cpu_index, Error **errp); +void inject_nmi(void); + +#endif /* NMI_H */ diff --git a/include/hw/nvram/eeprom93xx.h b/include/hw/nvram/eeprom93xx.h new file mode 100644 index 00000000..8ba0e287 --- /dev/null +++ b/include/hw/nvram/eeprom93xx.h @@ -0,0 +1,40 @@ +/* + * QEMU EEPROM 93xx emulation + * + * Copyright (c) 2006-2007 Stefan Weil + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef EEPROM93XX_H +#define EEPROM93XX_H + +typedef struct _eeprom_t eeprom_t; + +/* Create a new EEPROM with (nwords * 2) bytes. */ +eeprom_t *eeprom93xx_new(DeviceState *dev, uint16_t nwords); + +/* Destroy an existing EEPROM. */ +void eeprom93xx_free(DeviceState *dev, eeprom_t *eeprom); + +/* Read from the EEPROM. */ +uint16_t eeprom93xx_read(eeprom_t *eeprom); + +/* Write to the EEPROM. */ +void eeprom93xx_write(eeprom_t *eeprom, int eecs, int eesk, int eedi); + +/* Get EEPROM data array. */ +uint16_t *eeprom93xx_data(eeprom_t *eeprom); + +#endif /* EEPROM93XX_H */ diff --git a/include/hw/nvram/fw_cfg.h b/include/hw/nvram/fw_cfg.h new file mode 100644 index 00000000..e60d3ca2 --- /dev/null +++ b/include/hw/nvram/fw_cfg.h @@ -0,0 +1,89 @@ +#ifndef FW_CFG_H +#define FW_CFG_H + +#ifndef NO_QEMU_PROTOS +#include <stdint.h> +#include <stddef.h> + +#include "exec/hwaddr.h" +#include "qemu/typedefs.h" +#endif + +#define FW_CFG_SIGNATURE        0x00 +#define FW_CFG_ID               0x01 +#define FW_CFG_UUID             0x02 +#define FW_CFG_RAM_SIZE         0x03 +#define FW_CFG_NOGRAPHIC        0x04 +#define FW_CFG_NB_CPUS          0x05 +#define FW_CFG_MACHINE_ID       0x06 +#define FW_CFG_KERNEL_ADDR      0x07 +#define FW_CFG_KERNEL_SIZE      0x08 +#define FW_CFG_KERNEL_CMDLINE   0x09 +#define FW_CFG_INITRD_ADDR      0x0a +#define FW_CFG_INITRD_SIZE      0x0b +#define FW_CFG_BOOT_DEVICE      0x0c +#define FW_CFG_NUMA             0x0d +#define FW_CFG_BOOT_MENU        0x0e +#define FW_CFG_MAX_CPUS         0x0f +#define FW_CFG_KERNEL_ENTRY     0x10 +#define FW_CFG_KERNEL_DATA      0x11 +#define FW_CFG_INITRD_DATA      0x12 +#define FW_CFG_CMDLINE_ADDR     0x13 +#define FW_CFG_CMDLINE_SIZE     0x14 +#define FW_CFG_CMDLINE_DATA     0x15 +#define FW_CFG_SETUP_ADDR       0x16 +#define FW_CFG_SETUP_SIZE       0x17 +#define FW_CFG_SETUP_DATA       0x18 +#define FW_CFG_FILE_DIR         0x19 + +#define FW_CFG_FILE_FIRST       0x20 +#define FW_CFG_FILE_SLOTS       0x10 +#define FW_CFG_MAX_ENTRY        (FW_CFG_FILE_FIRST+FW_CFG_FILE_SLOTS) + +#define FW_CFG_WRITE_CHANNEL    0x4000 +#define FW_CFG_ARCH_LOCAL       0x8000 +#define FW_CFG_ENTRY_MASK       ~(FW_CFG_WRITE_CHANNEL | FW_CFG_ARCH_LOCAL) + +#define FW_CFG_INVALID          0xffff + +#define FW_CFG_MAX_FILE_PATH    56 + +#ifndef NO_QEMU_PROTOS +typedef struct FWCfgFile { +    uint32_t  size;        /* file size */ +    uint16_t  select;      /* write this to 0x510 to read it */ +    uint16_t  reserved; +    char      name[FW_CFG_MAX_FILE_PATH]; +} FWCfgFile; + +typedef struct FWCfgFiles { +    uint32_t  count; +    FWCfgFile f[]; +} FWCfgFiles; + +typedef void (*FWCfgCallback)(void *opaque, uint8_t *data); +typedef void (*FWCfgReadCallback)(void *opaque, uint32_t offset); + +void fw_cfg_add_bytes(FWCfgState *s, uint16_t key, void *data, size_t len); +void fw_cfg_add_string(FWCfgState *s, uint16_t key, const char *value); +void fw_cfg_add_i16(FWCfgState *s, uint16_t key, uint16_t value); +void fw_cfg_modify_i16(FWCfgState *s, uint16_t key, uint16_t value); +void fw_cfg_add_i32(FWCfgState *s, uint16_t key, uint32_t value); +void fw_cfg_add_i64(FWCfgState *s, uint16_t key, uint64_t value); +void fw_cfg_add_file(FWCfgState *s, const char *filename, void *data, +                     size_t len); +void fw_cfg_add_file_callback(FWCfgState *s, const char *filename, +                              FWCfgReadCallback callback, void *callback_opaque, +                              void *data, size_t len); +void *fw_cfg_modify_file(FWCfgState *s, const char *filename, void *data, +                         size_t len); +FWCfgState *fw_cfg_init_io(uint32_t iobase); +FWCfgState *fw_cfg_init_mem(hwaddr ctl_addr, hwaddr data_addr); +FWCfgState *fw_cfg_init_mem_wide(hwaddr ctl_addr, hwaddr data_addr, +                                 uint32_t data_width); + +FWCfgState *fw_cfg_find(void); + +#endif /* NO_QEMU_PROTOS */ + +#endif diff --git a/include/hw/nvram/openbios_firmware_abi.h b/include/hw/nvram/openbios_firmware_abi.h new file mode 100644 index 00000000..c66ee226 --- /dev/null +++ b/include/hw/nvram/openbios_firmware_abi.h @@ -0,0 +1,75 @@ +#ifndef FIRMWARE_ABI_H +#define FIRMWARE_ABI_H + +/* OpenBIOS NVRAM partition */ +struct OpenBIOS_nvpart_v1 { +    uint8_t signature; +    uint8_t checksum; +    uint16_t len; // BE, length divided by 16 +    char name[12]; +}; + +#define OPENBIOS_PART_SYSTEM 0x70 +#define OPENBIOS_PART_FREE 0x7f + +static inline void +OpenBIOS_finish_partition(struct OpenBIOS_nvpart_v1 *header, uint32_t size) +{ +    unsigned int i, sum; +    uint8_t *tmpptr; + +    // Length divided by 16 +    header->len = cpu_to_be16(size >> 4); + +    // Checksum +    tmpptr = (uint8_t *)header; +    sum = *tmpptr; +    for (i = 0; i < 14; i++) { +        sum += tmpptr[2 + i]; +        sum = (sum + ((sum & 0xff00) >> 8)) & 0xff; +    } +    header->checksum = sum & 0xff; +} + +static inline uint32_t +OpenBIOS_set_var(uint8_t *nvram, uint32_t addr, const char *str) +{ +    uint32_t len; + +    len = strlen(str) + 1; +    memcpy(&nvram[addr], str, len); + +    return addr + len; +} + +/* Sun IDPROM structure at the end of NVRAM */ +/* from http://www.squirrel.com/squirrel/sun-nvram-hostid.faq.html */ +struct Sun_nvram { +    uint8_t type;       /* always 01 */ +    uint8_t machine_id; /* first byte of host id (machine type) */ +    uint8_t macaddr[6]; /* 6 byte ethernet address (first 3 bytes 08, 00, 20) */ +    uint8_t date[4];    /* date of manufacture */ +    uint8_t hostid[3];  /* remaining 3 bytes of host id (serial number) */ +    uint8_t checksum;   /* bitwise xor of previous bytes */ +}; + +static inline void +Sun_init_header(struct Sun_nvram *header, const uint8_t *macaddr, int machine_id) +{ +    uint8_t tmp, *tmpptr; +    unsigned int i; + +    header->type = 1; +    header->machine_id = machine_id & 0xff; +    memcpy(&header->macaddr, macaddr, 6); +    memcpy(&header->hostid , &macaddr[3], 3); + +    /* Calculate checksum */ +    tmp = 0; +    tmpptr = (uint8_t *)header; +    for (i = 0; i < 15; i++) +        tmp ^= tmpptr[i]; + +    header->checksum = tmp; +} +#endif /* FIRMWARE_ABI_H */ diff --git a/include/hw/pci-host/apb.h b/include/hw/pci-host/apb.h new file mode 100644 index 00000000..736db611 --- /dev/null +++ b/include/hw/pci-host/apb.h @@ -0,0 +1,10 @@ +#ifndef APB_PCI_H +#define APB_PCI_H + +#include "qemu-common.h" + +PCIBus *pci_apb_init(hwaddr special_base, +                     hwaddr mem_base, +                     qemu_irq *ivec_irqs, PCIBus **bus2, PCIBus **bus3, +                     qemu_irq **pbm_irqs); +#endif diff --git a/include/hw/pci-host/gpex.h b/include/hw/pci-host/gpex.h new file mode 100644 index 00000000..68c93488 --- /dev/null +++ b/include/hw/pci-host/gpex.h @@ -0,0 +1,56 @@ +/* + * QEMU Generic PCI Express Bridge Emulation + * + * Copyright (C) 2015 Alexander Graf <agraf@suse.de> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/> + */ + +#ifndef HW_GPEX_H +#define HW_GPEX_H + +#include "hw/hw.h" +#include "hw/sysbus.h" +#include "hw/pci/pci.h" +#include "hw/pci/pcie_host.h" + +#define TYPE_GPEX_HOST "gpex-pcihost" +#define GPEX_HOST(obj) \ +     OBJECT_CHECK(GPEXHost, (obj), TYPE_GPEX_HOST) + +#define TYPE_GPEX_ROOT_DEVICE "gpex-root" +#define MCH_PCI_DEVICE(obj) \ +     OBJECT_CHECK(GPEXRootState, (obj), TYPE_GPEX_ROOT_DEVICE) + +#define GPEX_NUM_IRQS 4 + +typedef struct GPEXRootState { +    /*< private >*/ +    PCIDevice parent_obj; +    /*< public >*/ +} GPEXRootState; + +typedef struct GPEXHost { +    /*< private >*/ +    PCIExpressHost parent_obj; +    /*< public >*/ + +    GPEXRootState gpex_root; + +    MemoryRegion io_ioport; +    MemoryRegion io_mmio; +    qemu_irq irq[GPEX_NUM_IRQS]; +} GPEXHost; + +#endif /* HW_GPEX_H */ diff --git a/include/hw/pci-host/pam.h b/include/hw/pci-host/pam.h new file mode 100644 index 00000000..6116c638 --- /dev/null +++ b/include/hw/pci-host/pam.h @@ -0,0 +1,93 @@ +#ifndef QEMU_PAM_H +#define QEMU_PAM_H + +/* + * Copyright (c) 2006 Fabrice Bellard + * Copyright (c) 2011 Isaku Yamahata <yamahata at valinux co jp> + *               VA Linux Systems Japan K.K. + * Copyright (c) 2012 Jason Baron <jbaron@redhat.com> + * + * Split out from piix.c + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * 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 OTHER + * 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. + */ + +/* + * SMRAM memory area and PAM memory area in Legacy address range for PC. + * PAM: Programmable Attribute Map registers + * + * 0xa0000 - 0xbffff compatible SMRAM + * + * 0xc0000 - 0xc3fff Expansion area memory segments + * 0xc4000 - 0xc7fff + * 0xc8000 - 0xcbfff + * 0xcc000 - 0xcffff + * 0xd0000 - 0xd3fff + * 0xd4000 - 0xd7fff + * 0xd8000 - 0xdbfff + * 0xdc000 - 0xdffff + * 0xe0000 - 0xe3fff Extended System BIOS Area Memory Segments + * 0xe4000 - 0xe7fff + * 0xe8000 - 0xebfff + * 0xec000 - 0xeffff + * + * 0xf0000 - 0xfffff System BIOS Area Memory Segments + */ + +#include "qemu-common.h" +#include "exec/memory.h" + +#define SMRAM_C_BASE    0xa0000 +#define SMRAM_C_END     0xc0000 +#define SMRAM_C_SIZE    0x20000 + +#define PAM_EXPAN_BASE  0xc0000 +#define PAM_EXPAN_SIZE  0x04000 + +#define PAM_EXBIOS_BASE 0xe0000 +#define PAM_EXBIOS_SIZE 0x04000 + +#define PAM_BIOS_BASE   0xf0000 +#define PAM_BIOS_END    0xfffff +/* 64KB: Intel 3 series express chipset family p. 58*/ +#define PAM_BIOS_SIZE   0x10000 + +/* PAM registers: log nibble and high nibble*/ +#define PAM_ATTR_WE     ((uint8_t)2) +#define PAM_ATTR_RE     ((uint8_t)1) +#define PAM_ATTR_MASK   ((uint8_t)3) + +/* SMRAM register */ +#define SMRAM_D_OPEN           ((uint8_t)(1 << 6)) +#define SMRAM_D_CLS            ((uint8_t)(1 << 5)) +#define SMRAM_D_LCK            ((uint8_t)(1 << 4)) +#define SMRAM_G_SMRAME         ((uint8_t)(1 << 3)) +#define SMRAM_C_BASE_SEG_MASK  ((uint8_t)0x7) +#define SMRAM_C_BASE_SEG       ((uint8_t)0x2)  /* hardwired to b010 */ + +typedef struct PAMMemoryRegion { +    MemoryRegion alias[4];  /* index = PAM value */ +    unsigned current; +} PAMMemoryRegion; + +void init_pam(DeviceState *dev, MemoryRegion *ram, MemoryRegion *system, +              MemoryRegion *pci, PAMMemoryRegion *mem, uint32_t start, uint32_t size); +void pam_update(PAMMemoryRegion *mem, int idx, uint8_t val); + +#endif /* QEMU_PAM_H */ diff --git a/include/hw/pci-host/ppce500.h b/include/hw/pci-host/ppce500.h new file mode 100644 index 00000000..61f773ef --- /dev/null +++ b/include/hw/pci-host/ppce500.h @@ -0,0 +1,9 @@ +#ifndef PPCE500_PCI_H +#define PPCE500_PCI_H + +static inline int ppce500_pci_map_irq_slot(int devno, int irq_num) +{ +    return (devno + irq_num) % 4; +} + +#endif diff --git a/include/hw/pci-host/q35.h b/include/hw/pci-host/q35.h new file mode 100644 index 00000000..dbe6dc05 --- /dev/null +++ b/include/hw/pci-host/q35.h @@ -0,0 +1,179 @@ +/* + * q35.h + * + * Copyright (c) 2009 Isaku Yamahata <yamahata at valinux co jp> + *                    VA Linux Systems Japan K.K. + * Copyright (C) 2012 Jason Baron <jbaron@redhat.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/> + */ + +#ifndef HW_Q35_H +#define HW_Q35_H + +#include "hw/hw.h" +#include "hw/isa/isa.h" +#include "hw/sysbus.h" +#include "hw/i386/pc.h" +#include "hw/isa/apm.h" +#include "hw/pci/pci.h" +#include "hw/pci/pcie_host.h" +#include "hw/acpi/acpi.h" +#include "hw/acpi/ich9.h" +#include "hw/pci-host/pam.h" +#include "hw/i386/intel_iommu.h" + +#define TYPE_Q35_HOST_DEVICE "q35-pcihost" +#define Q35_HOST_DEVICE(obj) \ +     OBJECT_CHECK(Q35PCIHost, (obj), TYPE_Q35_HOST_DEVICE) + +#define TYPE_MCH_PCI_DEVICE "mch" +#define MCH_PCI_DEVICE(obj) \ +     OBJECT_CHECK(MCHPCIState, (obj), TYPE_MCH_PCI_DEVICE) + +typedef struct MCHPCIState { +    /*< private >*/ +    PCIDevice parent_obj; +    /*< public >*/ + +    MemoryRegion *ram_memory; +    MemoryRegion *pci_address_space; +    MemoryRegion *system_memory; +    MemoryRegion *address_space_io; +    PAMMemoryRegion pam_regions[13]; +    MemoryRegion smram_region, open_high_smram; +    MemoryRegion smram, low_smram, high_smram; +    MemoryRegion tseg_blackhole, tseg_window; +    PcPciInfo pci_info; +    ram_addr_t below_4g_mem_size; +    ram_addr_t above_4g_mem_size; +    uint64_t pci_hole64_size; +    PcGuestInfo *guest_info; +    uint32_t short_root_bus; +    IntelIOMMUState *iommu; +} MCHPCIState; + +typedef struct Q35PCIHost { +    /*< private >*/ +    PCIExpressHost parent_obj; +    /*< public >*/ + +    MCHPCIState mch; +} Q35PCIHost; + +#define Q35_MASK(bit, ms_bit, ls_bit) \ +((uint##bit##_t)(((1ULL << ((ms_bit) + 1)) - 1) & ~((1ULL << ls_bit) - 1))) + +/* + * gmch part + */ + +/* PCI configuration */ +#define MCH_HOST_BRIDGE                        "MCH" + +#define MCH_HOST_BRIDGE_CONFIG_ADDR            0xcf8 +#define MCH_HOST_BRIDGE_CONFIG_DATA            0xcfc + +/* D0:F0 configuration space */ +#define MCH_HOST_BRIDGE_REVISION_DEFAULT       0x0 + +#define MCH_HOST_BRIDGE_PCIEXBAR               0x60    /* 64bit register */ +#define MCH_HOST_BRIDGE_PCIEXBAR_SIZE          8       /* 64bit register */ +#define MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT       0xb0000000 +#define MCH_HOST_BRIDGE_PCIEXBAR_MAX           (0x10000000) /* 256M */ +#define MCH_HOST_BRIDGE_PCIEXBAR_ADMSK         Q35_MASK(64, 35, 28) +#define MCH_HOST_BRIDGE_PCIEXBAR_128ADMSK      ((uint64_t)(1 << 26)) +#define MCH_HOST_BRIDGE_PCIEXBAR_64ADMSK       ((uint64_t)(1 << 25)) +#define MCH_HOST_BRIDGE_PCIEXBAR_LENGTH_MASK   ((uint64_t)(0x3 << 1)) +#define MCH_HOST_BRIDGE_PCIEXBAR_LENGTH_256M   ((uint64_t)(0x0 << 1)) +#define MCH_HOST_BRIDGE_PCIEXBAR_LENGTH_128M   ((uint64_t)(0x1 << 1)) +#define MCH_HOST_BRIDGE_PCIEXBAR_LENGTH_64M    ((uint64_t)(0x2 << 1)) +#define MCH_HOST_BRIDGE_PCIEXBAR_LENGTH_RVD    ((uint64_t)(0x3 << 1)) +#define MCH_HOST_BRIDGE_PCIEXBAREN             ((uint64_t)1) + +#define MCH_HOST_BRIDGE_PAM_NB                 7 +#define MCH_HOST_BRIDGE_PAM_SIZE               7 +#define MCH_HOST_BRIDGE_PAM0                   0x90 +#define MCH_HOST_BRIDGE_PAM_BIOS_AREA          0xf0000 +#define MCH_HOST_BRIDGE_PAM_AREA_SIZE          0x10000 /* 16KB */ +#define MCH_HOST_BRIDGE_PAM1                   0x91 +#define MCH_HOST_BRIDGE_PAM_EXPAN_AREA         0xc0000 +#define MCH_HOST_BRIDGE_PAM_EXPAN_SIZE         0x04000 +#define MCH_HOST_BRIDGE_PAM2                   0x92 +#define MCH_HOST_BRIDGE_PAM3                   0x93 +#define MCH_HOST_BRIDGE_PAM4                   0x94 +#define MCH_HOST_BRIDGE_PAM_EXBIOS_AREA        0xe0000 +#define MCH_HOST_BRIDGE_PAM_EXBIOS_SIZE        0x04000 +#define MCH_HOST_BRIDGE_PAM5                   0x95 +#define MCH_HOST_BRIDGE_PAM6                   0x96 +#define MCH_HOST_BRIDGE_PAM_WE_HI              ((uint8_t)(0x2 << 4)) +#define MCH_HOST_BRIDGE_PAM_RE_HI              ((uint8_t)(0x1 << 4)) +#define MCH_HOST_BRIDGE_PAM_HI_MASK            ((uint8_t)(0x3 << 4)) +#define MCH_HOST_BRIDGE_PAM_WE_LO              ((uint8_t)0x2) +#define MCH_HOST_BRIDGE_PAM_RE_LO              ((uint8_t)0x1) +#define MCH_HOST_BRIDGE_PAM_LO_MASK            ((uint8_t)0x3) +#define MCH_HOST_BRIDGE_PAM_WE                 ((uint8_t)0x2) +#define MCH_HOST_BRIDGE_PAM_RE                 ((uint8_t)0x1) +#define MCH_HOST_BRIDGE_PAM_MASK               ((uint8_t)0x3) + +#define MCH_HOST_BRIDGE_SMRAM                  0x9d +#define MCH_HOST_BRIDGE_SMRAM_SIZE             2 +#define MCH_HOST_BRIDGE_SMRAM_D_OPEN           ((uint8_t)(1 << 6)) +#define MCH_HOST_BRIDGE_SMRAM_D_CLS            ((uint8_t)(1 << 5)) +#define MCH_HOST_BRIDGE_SMRAM_D_LCK            ((uint8_t)(1 << 4)) +#define MCH_HOST_BRIDGE_SMRAM_G_SMRAME         ((uint8_t)(1 << 3)) +#define MCH_HOST_BRIDGE_SMRAM_C_BASE_SEG_MASK  ((uint8_t)0x7) +#define MCH_HOST_BRIDGE_SMRAM_C_BASE_SEG       ((uint8_t)0x2)  /* hardwired to b010 */ +#define MCH_HOST_BRIDGE_SMRAM_C_BASE           0xa0000 +#define MCH_HOST_BRIDGE_SMRAM_C_END            0xc0000 +#define MCH_HOST_BRIDGE_SMRAM_C_SIZE           0x20000 +#define MCH_HOST_BRIDGE_UPPER_SYSTEM_BIOS_END  0x100000 +#define MCH_HOST_BRIDGE_SMRAM_DEFAULT           \ +    MCH_HOST_BRIDGE_SMRAM_C_BASE_SEG +#define MCH_HOST_BRIDGE_SMRAM_WMASK             \ +    (MCH_HOST_BRIDGE_SMRAM_D_OPEN |             \ +     MCH_HOST_BRIDGE_SMRAM_D_CLS |              \ +     MCH_HOST_BRIDGE_SMRAM_D_LCK |              \ +     MCH_HOST_BRIDGE_SMRAM_G_SMRAME) +#define MCH_HOST_BRIDGE_SMRAM_WMASK_LCK         \ +    MCH_HOST_BRIDGE_SMRAM_D_CLS + +#define MCH_HOST_BRIDGE_ESMRAMC                0x9e +#define MCH_HOST_BRIDGE_ESMRAMC_H_SMRAME       ((uint8_t)(1 << 7)) +#define MCH_HOST_BRIDGE_ESMRAMC_E_SMERR        ((uint8_t)(1 << 6)) +#define MCH_HOST_BRIDGE_ESMRAMC_SM_CACHE       ((uint8_t)(1 << 5)) +#define MCH_HOST_BRIDGE_ESMRAMC_SM_L1          ((uint8_t)(1 << 4)) +#define MCH_HOST_BRIDGE_ESMRAMC_SM_L2          ((uint8_t)(1 << 3)) +#define MCH_HOST_BRIDGE_ESMRAMC_TSEG_SZ_MASK   ((uint8_t)(0x3 << 1)) +#define MCH_HOST_BRIDGE_ESMRAMC_TSEG_SZ_1MB    ((uint8_t)(0x0 << 1)) +#define MCH_HOST_BRIDGE_ESMRAMC_TSEG_SZ_2MB    ((uint8_t)(0x1 << 1)) +#define MCH_HOST_BRIDGE_ESMRAMC_TSEG_SZ_8MB    ((uint8_t)(0x2 << 1)) +#define MCH_HOST_BRIDGE_ESMRAMC_T_EN           ((uint8_t)1) +#define MCH_HOST_BRIDGE_ESMRAMC_DEFAULT \ +    (MCH_HOST_BRIDGE_ESMRAMC_SM_CACHE | \ +     MCH_HOST_BRIDGE_ESMRAMC_SM_L1 |    \ +     MCH_HOST_BRIDGE_ESMRAMC_SM_L2) +#define MCH_HOST_BRIDGE_ESMRAMC_WMASK               \ +    (MCH_HOST_BRIDGE_ESMRAMC_H_SMRAME |             \ +     MCH_HOST_BRIDGE_ESMRAMC_TSEG_SZ_MASK |         \ +     MCH_HOST_BRIDGE_ESMRAMC_T_EN) +#define MCH_HOST_BRIDGE_ESMRAMC_WMASK_LCK     0 + +/* D1:F0 PCIE* port*/ +#define MCH_PCIE_DEV                           1 +#define MCH_PCIE_FUNC                          0 + +uint64_t mch_mcfg_base(void); + +#endif /* HW_Q35_H */ diff --git a/include/hw/pci-host/spapr.h b/include/hw/pci-host/spapr.h new file mode 100644 index 00000000..5322b560 --- /dev/null +++ b/include/hw/pci-host/spapr.h @@ -0,0 +1,141 @@ +/* + * QEMU SPAPR PCI BUS definitions + * + * Copyright (c) 2011 Alexey Kardashevskiy <aik@au1.ibm.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ +#if !defined(__HW_SPAPR_H__) +#error Please include spapr.h before this file! +#endif + +#if !defined(__HW_SPAPR_PCI_H__) +#define __HW_SPAPR_PCI_H__ + +#include "hw/pci/pci.h" +#include "hw/pci/pci_host.h" +#include "hw/ppc/xics.h" + +#define TYPE_SPAPR_PCI_HOST_BRIDGE "spapr-pci-host-bridge" +#define TYPE_SPAPR_PCI_VFIO_HOST_BRIDGE "spapr-pci-vfio-host-bridge" + +#define SPAPR_PCI_HOST_BRIDGE(obj) \ +    OBJECT_CHECK(sPAPRPHBState, (obj), TYPE_SPAPR_PCI_HOST_BRIDGE) + +#define SPAPR_PCI_VFIO_HOST_BRIDGE(obj) \ +    OBJECT_CHECK(sPAPRPHBVFIOState, (obj), TYPE_SPAPR_PCI_VFIO_HOST_BRIDGE) + +#define SPAPR_PCI_HOST_BRIDGE_CLASS(klass) \ +     OBJECT_CLASS_CHECK(sPAPRPHBClass, (klass), TYPE_SPAPR_PCI_HOST_BRIDGE) +#define SPAPR_PCI_HOST_BRIDGE_GET_CLASS(obj) \ +     OBJECT_GET_CLASS(sPAPRPHBClass, (obj), TYPE_SPAPR_PCI_HOST_BRIDGE) + +typedef struct sPAPRPHBClass sPAPRPHBClass; +typedef struct sPAPRPHBState sPAPRPHBState; +typedef struct sPAPRPHBVFIOState sPAPRPHBVFIOState; + +struct sPAPRPHBClass { +    PCIHostBridgeClass parent_class; + +    void (*finish_realize)(sPAPRPHBState *sphb, Error **errp); +    int (*eeh_set_option)(sPAPRPHBState *sphb, unsigned int addr, int option); +    int (*eeh_get_state)(sPAPRPHBState *sphb, int *state); +    int (*eeh_reset)(sPAPRPHBState *sphb, int option); +    int (*eeh_configure)(sPAPRPHBState *sphb); +}; + +typedef struct spapr_pci_msi { +    uint32_t first_irq; +    uint32_t num; +} spapr_pci_msi; + +typedef struct spapr_pci_msi_mig { +    uint32_t key; +    spapr_pci_msi value; +} spapr_pci_msi_mig; + +struct sPAPRPHBState { +    PCIHostState parent_obj; + +    uint32_t index; +    uint64_t buid; +    char *dtbusname; +    bool dr_enabled; + +    MemoryRegion memspace, iospace; +    hwaddr mem_win_addr, mem_win_size, io_win_addr, io_win_size; +    MemoryRegion memwindow, iowindow, msiwindow; + +    uint32_t dma_liobn; +    AddressSpace iommu_as; +    MemoryRegion iommu_root; + +    struct spapr_pci_lsi { +        uint32_t irq; +    } lsi_table[PCI_NUM_PINS]; + +    GHashTable *msi; +    /* Temporary cache for migration purposes */ +    int32_t msi_devs_num; +    spapr_pci_msi_mig *msi_devs; + +    QLIST_ENTRY(sPAPRPHBState) list; +}; + +struct sPAPRPHBVFIOState { +    sPAPRPHBState phb; + +    int32_t iommugroupid; +}; + +#define SPAPR_PCI_MAX_INDEX          255 + +#define SPAPR_PCI_BASE_BUID          0x800000020000000ULL + +#define SPAPR_PCI_MEM_WIN_BUS_OFFSET 0x80000000ULL + +#define SPAPR_PCI_WINDOW_BASE        0x10000000000ULL +#define SPAPR_PCI_WINDOW_SPACING     0x1000000000ULL +#define SPAPR_PCI_MMIO_WIN_OFF       0xA0000000 +#define SPAPR_PCI_MMIO_WIN_SIZE      (SPAPR_PCI_WINDOW_SPACING - \ +                                     SPAPR_PCI_MEM_WIN_BUS_OFFSET) +#define SPAPR_PCI_IO_WIN_OFF         0x80000000 +#define SPAPR_PCI_IO_WIN_SIZE        0x10000 + +#define SPAPR_PCI_MSI_WINDOW         0x40000000000ULL + +#define SPAPR_PCI_DMA32_SIZE         0x40000000 + +static inline qemu_irq spapr_phb_lsi_qirq(struct sPAPRPHBState *phb, int pin) +{ +    sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine()); + +    return xics_get_qirq(spapr->icp, phb->lsi_table[pin].irq); +} + +PCIHostState *spapr_create_phb(sPAPRMachineState *spapr, int index); + +int spapr_populate_pci_dt(sPAPRPHBState *phb, +                          uint32_t xics_phandle, +                          void *fdt); + +void spapr_pci_msi_init(sPAPRMachineState *spapr, hwaddr addr); + +void spapr_pci_rtas_init(void); + +sPAPRPHBState *spapr_pci_find_phb(sPAPRMachineState *spapr, uint64_t buid); +PCIDevice *spapr_pci_find_dev(sPAPRMachineState *spapr, uint64_t buid, +                              uint32_t config_addr); + +#endif /* __HW_SPAPR_PCI_H__ */ diff --git a/include/hw/pci/msi.h b/include/hw/pci/msi.h new file mode 100644 index 00000000..50e452bd --- /dev/null +++ b/include/hw/pci/msi.h @@ -0,0 +1,51 @@ +/* + * msi.h + * + * Copyright (c) 2010 Isaku Yamahata <yamahata at valinux co jp> + *                    VA Linux Systems Japan K.K. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along + * with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef QEMU_MSI_H +#define QEMU_MSI_H + +#include "qemu-common.h" +#include "hw/pci/pci.h" + +struct MSIMessage { +    uint64_t address; +    uint32_t data; +}; + +extern bool msi_supported; + +void msi_set_message(PCIDevice *dev, MSIMessage msg); +MSIMessage msi_get_message(PCIDevice *dev, unsigned int vector); +bool msi_enabled(const PCIDevice *dev); +int msi_init(struct PCIDevice *dev, uint8_t offset, +             unsigned int nr_vectors, bool msi64bit, bool msi_per_vector_mask); +void msi_uninit(struct PCIDevice *dev); +void msi_reset(PCIDevice *dev); +void msi_notify(PCIDevice *dev, unsigned int vector); +void msi_send_message(PCIDevice *dev, MSIMessage msg); +void msi_write_config(PCIDevice *dev, uint32_t addr, uint32_t val, int len); +unsigned int msi_nr_vectors_allocated(const PCIDevice *dev); + +static inline bool msi_present(const PCIDevice *dev) +{ +    return dev->cap_present & QEMU_PCI_CAP_MSI; +} + +#endif /* QEMU_MSI_H */ diff --git a/include/hw/pci/msix.h b/include/hw/pci/msix.h new file mode 100644 index 00000000..954d82b3 --- /dev/null +++ b/include/hw/pci/msix.h @@ -0,0 +1,57 @@ +#ifndef QEMU_MSIX_H +#define QEMU_MSIX_H + +#include "qemu-common.h" +#include "hw/pci/pci.h" + +void msix_set_message(PCIDevice *dev, int vector, MSIMessage msg); +MSIMessage msix_get_message(PCIDevice *dev, unsigned int vector); +int msix_init(PCIDevice *dev, unsigned short nentries, +              MemoryRegion *table_bar, uint8_t table_bar_nr, +              unsigned table_offset, MemoryRegion *pba_bar, +              uint8_t pba_bar_nr, unsigned pba_offset, uint8_t cap_pos); +int msix_init_exclusive_bar(PCIDevice *dev, unsigned short nentries, +                            uint8_t bar_nr); + +void msix_write_config(PCIDevice *dev, uint32_t address, uint32_t val, int len); + +void msix_uninit(PCIDevice *dev, MemoryRegion *table_bar, +                 MemoryRegion *pba_bar); +void msix_uninit_exclusive_bar(PCIDevice *dev); + +unsigned int msix_nr_vectors_allocated(const PCIDevice *dev); + +void msix_save(PCIDevice *dev, QEMUFile *f); +void msix_load(PCIDevice *dev, QEMUFile *f); + +int msix_enabled(PCIDevice *dev); +int msix_present(PCIDevice *dev); + +bool msix_is_masked(PCIDevice *dev, unsigned vector); +void msix_set_pending(PCIDevice *dev, unsigned vector); + +int msix_vector_use(PCIDevice *dev, unsigned vector); +void msix_vector_unuse(PCIDevice *dev, unsigned vector); +void msix_unuse_all_vectors(PCIDevice *dev); + +void msix_notify(PCIDevice *dev, unsigned vector); + +void msix_reset(PCIDevice *dev); + +int msix_set_vector_notifiers(PCIDevice *dev, +                              MSIVectorUseNotifier use_notifier, +                              MSIVectorReleaseNotifier release_notifier, +                              MSIVectorPollNotifier poll_notifier); +void msix_unset_vector_notifiers(PCIDevice *dev); + +extern const VMStateDescription vmstate_msix; + +#define VMSTATE_MSIX(_field, _state) {                               \ +    .name       = (stringify(_field)),                               \ +    .size       = sizeof(PCIDevice),                                 \ +    .vmsd       = &vmstate_msix,                                     \ +    .flags      = VMS_STRUCT,                                        \ +    .offset     = vmstate_offset_value(_state, _field, PCIDevice),   \ +} + +#endif diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h new file mode 100644 index 00000000..551cb3d6 --- /dev/null +++ b/include/hw/pci/pci.h @@ -0,0 +1,766 @@ +#ifndef QEMU_PCI_H +#define QEMU_PCI_H + +#include "qemu-common.h" + +#include "hw/qdev.h" +#include "exec/memory.h" +#include "sysemu/dma.h" +#include "qapi/error.h" + +/* PCI includes legacy ISA access.  */ +#include "hw/isa/isa.h" + +#include "hw/pci/pcie.h" + +/* PCI bus */ + +#define PCI_DEVFN(slot, func)   ((((slot) & 0x1f) << 3) | ((func) & 0x07)) +#define PCI_SLOT(devfn)         (((devfn) >> 3) & 0x1f) +#define PCI_FUNC(devfn)         ((devfn) & 0x07) +#define PCI_SLOT_MAX            32 +#define PCI_FUNC_MAX            8 + +/* Class, Vendor and Device IDs from Linux's pci_ids.h */ +#include "hw/pci/pci_ids.h" + +/* QEMU-specific Vendor and Device ID definitions */ + +/* IBM (0x1014) */ +#define PCI_DEVICE_ID_IBM_440GX          0x027f +#define PCI_DEVICE_ID_IBM_OPENPIC2       0xffff + +/* Hitachi (0x1054) */ +#define PCI_VENDOR_ID_HITACHI            0x1054 +#define PCI_DEVICE_ID_HITACHI_SH7751R    0x350e + +/* Apple (0x106b) */ +#define PCI_DEVICE_ID_APPLE_343S1201     0x0010 +#define PCI_DEVICE_ID_APPLE_UNI_N_I_PCI  0x001e +#define PCI_DEVICE_ID_APPLE_UNI_N_PCI    0x001f +#define PCI_DEVICE_ID_APPLE_UNI_N_KEYL   0x0022 +#define PCI_DEVICE_ID_APPLE_IPID_USB     0x003f + +/* Realtek (0x10ec) */ +#define PCI_DEVICE_ID_REALTEK_8029       0x8029 + +/* Xilinx (0x10ee) */ +#define PCI_DEVICE_ID_XILINX_XC2VP30     0x0300 + +/* Marvell (0x11ab) */ +#define PCI_DEVICE_ID_MARVELL_GT6412X    0x4620 + +/* QEMU/Bochs VGA (0x1234) */ +#define PCI_VENDOR_ID_QEMU               0x1234 +#define PCI_DEVICE_ID_QEMU_VGA           0x1111 + +/* VMWare (0x15ad) */ +#define PCI_VENDOR_ID_VMWARE             0x15ad +#define PCI_DEVICE_ID_VMWARE_SVGA2       0x0405 +#define PCI_DEVICE_ID_VMWARE_SVGA        0x0710 +#define PCI_DEVICE_ID_VMWARE_NET         0x0720 +#define PCI_DEVICE_ID_VMWARE_SCSI        0x0730 +#define PCI_DEVICE_ID_VMWARE_PVSCSI      0x07C0 +#define PCI_DEVICE_ID_VMWARE_IDE         0x1729 +#define PCI_DEVICE_ID_VMWARE_VMXNET3     0x07B0 + +/* Intel (0x8086) */ +#define PCI_DEVICE_ID_INTEL_82551IT      0x1209 +#define PCI_DEVICE_ID_INTEL_82557        0x1229 +#define PCI_DEVICE_ID_INTEL_82801IR      0x2922 + +/* Red Hat / Qumranet (for QEMU) -- see pci-ids.txt */ +#define PCI_VENDOR_ID_REDHAT_QUMRANET    0x1af4 +#define PCI_SUBVENDOR_ID_REDHAT_QUMRANET 0x1af4 +#define PCI_SUBDEVICE_ID_QEMU            0x1100 + +#define PCI_DEVICE_ID_VIRTIO_NET         0x1000 +#define PCI_DEVICE_ID_VIRTIO_BLOCK       0x1001 +#define PCI_DEVICE_ID_VIRTIO_BALLOON     0x1002 +#define PCI_DEVICE_ID_VIRTIO_CONSOLE     0x1003 +#define PCI_DEVICE_ID_VIRTIO_SCSI        0x1004 +#define PCI_DEVICE_ID_VIRTIO_RNG         0x1005 +#define PCI_DEVICE_ID_VIRTIO_9P          0x1009 + +#define PCI_VENDOR_ID_REDHAT             0x1b36 +#define PCI_DEVICE_ID_REDHAT_BRIDGE      0x0001 +#define PCI_DEVICE_ID_REDHAT_SERIAL      0x0002 +#define PCI_DEVICE_ID_REDHAT_SERIAL2     0x0003 +#define PCI_DEVICE_ID_REDHAT_SERIAL4     0x0004 +#define PCI_DEVICE_ID_REDHAT_TEST        0x0005 +#define PCI_DEVICE_ID_REDHAT_ROCKER      0x0006 +#define PCI_DEVICE_ID_REDHAT_SDHCI       0x0007 +#define PCI_DEVICE_ID_REDHAT_PCIE_HOST   0x0008 +#define PCI_DEVICE_ID_REDHAT_PXB         0x0009 +#define PCI_DEVICE_ID_REDHAT_BRIDGE_SEAT 0x000a +#define PCI_DEVICE_ID_REDHAT_QXL         0x0100 + +#define FMT_PCIBUS                      PRIx64 + +typedef void PCIConfigWriteFunc(PCIDevice *pci_dev, +                                uint32_t address, uint32_t data, int len); +typedef uint32_t PCIConfigReadFunc(PCIDevice *pci_dev, +                                   uint32_t address, int len); +typedef void PCIMapIORegionFunc(PCIDevice *pci_dev, int region_num, +                                pcibus_t addr, pcibus_t size, int type); +typedef void PCIUnregisterFunc(PCIDevice *pci_dev); + +typedef struct PCIIORegion { +    pcibus_t addr; /* current PCI mapping address. -1 means not mapped */ +#define PCI_BAR_UNMAPPED (~(pcibus_t)0) +    pcibus_t size; +    uint8_t type; +    MemoryRegion *memory; +    MemoryRegion *address_space; +} PCIIORegion; + +#define PCI_ROM_SLOT 6 +#define PCI_NUM_REGIONS 7 + +enum { +    QEMU_PCI_VGA_MEM, +    QEMU_PCI_VGA_IO_LO, +    QEMU_PCI_VGA_IO_HI, +    QEMU_PCI_VGA_NUM_REGIONS, +}; + +#define QEMU_PCI_VGA_MEM_BASE 0xa0000 +#define QEMU_PCI_VGA_MEM_SIZE 0x20000 +#define QEMU_PCI_VGA_IO_LO_BASE 0x3b0 +#define QEMU_PCI_VGA_IO_LO_SIZE 0xc +#define QEMU_PCI_VGA_IO_HI_BASE 0x3c0 +#define QEMU_PCI_VGA_IO_HI_SIZE 0x20 + +#include "hw/pci/pci_regs.h" + +/* PCI HEADER_TYPE */ +#define  PCI_HEADER_TYPE_MULTI_FUNCTION 0x80 + +/* Size of the standard PCI config header */ +#define PCI_CONFIG_HEADER_SIZE 0x40 +/* Size of the standard PCI config space */ +#define PCI_CONFIG_SPACE_SIZE 0x100 +/* Size of the standard PCIe config space: 4KB */ +#define PCIE_CONFIG_SPACE_SIZE  0x1000 + +#define PCI_NUM_PINS 4 /* A-D */ + +/* Bits in cap_present field. */ +enum { +    QEMU_PCI_CAP_MSI = 0x1, +    QEMU_PCI_CAP_MSIX = 0x2, +    QEMU_PCI_CAP_EXPRESS = 0x4, + +    /* multifunction capable device */ +#define QEMU_PCI_CAP_MULTIFUNCTION_BITNR        3 +    QEMU_PCI_CAP_MULTIFUNCTION = (1 << QEMU_PCI_CAP_MULTIFUNCTION_BITNR), + +    /* command register SERR bit enabled */ +#define QEMU_PCI_CAP_SERR_BITNR 4 +    QEMU_PCI_CAP_SERR = (1 << QEMU_PCI_CAP_SERR_BITNR), +    /* Standard hot plug controller. */ +#define QEMU_PCI_SHPC_BITNR 5 +    QEMU_PCI_CAP_SHPC = (1 << QEMU_PCI_SHPC_BITNR), +#define QEMU_PCI_SLOTID_BITNR 6 +    QEMU_PCI_CAP_SLOTID = (1 << QEMU_PCI_SLOTID_BITNR), +    /* PCI Express capability - Power Controller Present */ +#define QEMU_PCIE_SLTCAP_PCP_BITNR 7 +    QEMU_PCIE_SLTCAP_PCP = (1 << QEMU_PCIE_SLTCAP_PCP_BITNR), +}; + +#define TYPE_PCI_DEVICE "pci-device" +#define PCI_DEVICE(obj) \ +     OBJECT_CHECK(PCIDevice, (obj), TYPE_PCI_DEVICE) +#define PCI_DEVICE_CLASS(klass) \ +     OBJECT_CLASS_CHECK(PCIDeviceClass, (klass), TYPE_PCI_DEVICE) +#define PCI_DEVICE_GET_CLASS(obj) \ +     OBJECT_GET_CLASS(PCIDeviceClass, (obj), TYPE_PCI_DEVICE) + +typedef struct PCIINTxRoute { +    enum { +        PCI_INTX_ENABLED, +        PCI_INTX_INVERTED, +        PCI_INTX_DISABLED, +    } mode; +    int irq; +} PCIINTxRoute; + +typedef struct PCIDeviceClass { +    DeviceClass parent_class; + +    void (*realize)(PCIDevice *dev, Error **errp); +    int (*init)(PCIDevice *dev);/* TODO convert to realize() and remove */ +    PCIUnregisterFunc *exit; +    PCIConfigReadFunc *config_read; +    PCIConfigWriteFunc *config_write; + +    uint16_t vendor_id; +    uint16_t device_id; +    uint8_t revision; +    uint16_t class_id; +    uint16_t subsystem_vendor_id;       /* only for header type = 0 */ +    uint16_t subsystem_id;              /* only for header type = 0 */ + +    /* +     * pci-to-pci bridge or normal device. +     * This doesn't mean pci host switch. +     * When card bus bridge is supported, this would be enhanced. +     */ +    int is_bridge; + +    /* pcie stuff */ +    int is_express;   /* is this device pci express? */ + +    /* rom bar */ +    const char *romfile; +} PCIDeviceClass; + +typedef void (*PCIINTxRoutingNotifier)(PCIDevice *dev); +typedef int (*MSIVectorUseNotifier)(PCIDevice *dev, unsigned int vector, +                                      MSIMessage msg); +typedef void (*MSIVectorReleaseNotifier)(PCIDevice *dev, unsigned int vector); +typedef void (*MSIVectorPollNotifier)(PCIDevice *dev, +                                      unsigned int vector_start, +                                      unsigned int vector_end); + +struct PCIDevice { +    DeviceState qdev; + +    /* PCI config space */ +    uint8_t *config; + +    /* Used to enable config checks on load. Note that writable bits are +     * never checked even if set in cmask. */ +    uint8_t *cmask; + +    /* Used to implement R/W bytes */ +    uint8_t *wmask; + +    /* Used to implement RW1C(Write 1 to Clear) bytes */ +    uint8_t *w1cmask; + +    /* Used to allocate config space for capabilities. */ +    uint8_t *used; + +    /* the following fields are read only */ +    PCIBus *bus; +    int32_t devfn; +    char name[64]; +    PCIIORegion io_regions[PCI_NUM_REGIONS]; +    AddressSpace bus_master_as; +    MemoryRegion bus_master_enable_region; + +    /* do not access the following fields */ +    PCIConfigReadFunc *config_read; +    PCIConfigWriteFunc *config_write; + +    /* Legacy PCI VGA regions */ +    MemoryRegion *vga_regions[QEMU_PCI_VGA_NUM_REGIONS]; +    bool has_vga; + +    /* Current IRQ levels.  Used internally by the generic PCI code.  */ +    uint8_t irq_state; + +    /* Capability bits */ +    uint32_t cap_present; + +    /* Offset of MSI-X capability in config space */ +    uint8_t msix_cap; + +    /* MSI-X entries */ +    int msix_entries_nr; + +    /* Space to store MSIX table & pending bit array */ +    uint8_t *msix_table; +    uint8_t *msix_pba; +    /* MemoryRegion container for msix exclusive BAR setup */ +    MemoryRegion msix_exclusive_bar; +    /* Memory Regions for MSIX table and pending bit entries. */ +    MemoryRegion msix_table_mmio; +    MemoryRegion msix_pba_mmio; +    /* Reference-count for entries actually in use by driver. */ +    unsigned *msix_entry_used; +    /* MSIX function mask set or MSIX disabled */ +    bool msix_function_masked; +    /* Version id needed for VMState */ +    int32_t version_id; + +    /* Offset of MSI capability in config space */ +    uint8_t msi_cap; + +    /* PCI Express */ +    PCIExpressDevice exp; + +    /* SHPC */ +    SHPCDevice *shpc; + +    /* Location of option rom */ +    char *romfile; +    bool has_rom; +    MemoryRegion rom; +    uint32_t rom_bar; + +    /* INTx routing notifier */ +    PCIINTxRoutingNotifier intx_routing_notifier; + +    /* MSI-X notifiers */ +    MSIVectorUseNotifier msix_vector_use_notifier; +    MSIVectorReleaseNotifier msix_vector_release_notifier; +    MSIVectorPollNotifier msix_vector_poll_notifier; +}; + +void pci_register_bar(PCIDevice *pci_dev, int region_num, +                      uint8_t attr, MemoryRegion *memory); +void pci_register_vga(PCIDevice *pci_dev, MemoryRegion *mem, +                      MemoryRegion *io_lo, MemoryRegion *io_hi); +void pci_unregister_vga(PCIDevice *pci_dev); +pcibus_t pci_get_bar_addr(PCIDevice *pci_dev, int region_num); + +int pci_add_capability(PCIDevice *pdev, uint8_t cap_id, +                       uint8_t offset, uint8_t size); +int pci_add_capability2(PCIDevice *pdev, uint8_t cap_id, +                       uint8_t offset, uint8_t size, +                       Error **errp); + +void pci_del_capability(PCIDevice *pci_dev, uint8_t cap_id, uint8_t cap_size); + +uint8_t pci_find_capability(PCIDevice *pci_dev, uint8_t cap_id); + + +uint32_t pci_default_read_config(PCIDevice *d, +                                 uint32_t address, int len); +void pci_default_write_config(PCIDevice *d, +                              uint32_t address, uint32_t val, int len); +void pci_device_save(PCIDevice *s, QEMUFile *f); +int pci_device_load(PCIDevice *s, QEMUFile *f); +MemoryRegion *pci_address_space(PCIDevice *dev); +MemoryRegion *pci_address_space_io(PCIDevice *dev); + +/* + * Should not normally be used by devices. For use by sPAPR target + * where QEMU emulates firmware. + */ +int pci_bar(PCIDevice *d, int reg); + +typedef void (*pci_set_irq_fn)(void *opaque, int irq_num, int level); +typedef int (*pci_map_irq_fn)(PCIDevice *pci_dev, int irq_num); +typedef PCIINTxRoute (*pci_route_irq_fn)(void *opaque, int pin); + +#define TYPE_PCI_BUS "PCI" +#define PCI_BUS(obj) OBJECT_CHECK(PCIBus, (obj), TYPE_PCI_BUS) +#define PCI_BUS_CLASS(klass) OBJECT_CLASS_CHECK(PCIBusClass, (klass), TYPE_PCI_BUS) +#define PCI_BUS_GET_CLASS(obj) OBJECT_GET_CLASS(PCIBusClass, (obj), TYPE_PCI_BUS) +#define TYPE_PCIE_BUS "PCIE" + +bool pci_bus_is_express(PCIBus *bus); +bool pci_bus_is_root(PCIBus *bus); +void pci_bus_new_inplace(PCIBus *bus, size_t bus_size, DeviceState *parent, +                         const char *name, +                         MemoryRegion *address_space_mem, +                         MemoryRegion *address_space_io, +                         uint8_t devfn_min, const char *typename); +PCIBus *pci_bus_new(DeviceState *parent, const char *name, +                    MemoryRegion *address_space_mem, +                    MemoryRegion *address_space_io, +                    uint8_t devfn_min, const char *typename); +void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq, +                  void *irq_opaque, int nirq); +int pci_bus_get_irq_level(PCIBus *bus, int irq_num); +/* 0 <= pin <= 3 0 = INTA, 1 = INTB, 2 = INTC, 3 = INTD */ +int pci_swizzle_map_irq_fn(PCIDevice *pci_dev, int pin); +PCIBus *pci_register_bus(DeviceState *parent, const char *name, +                         pci_set_irq_fn set_irq, pci_map_irq_fn map_irq, +                         void *irq_opaque, +                         MemoryRegion *address_space_mem, +                         MemoryRegion *address_space_io, +                         uint8_t devfn_min, int nirq, const char *typename); +void pci_bus_set_route_irq_fn(PCIBus *, pci_route_irq_fn); +PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin); +bool pci_intx_route_changed(PCIINTxRoute *old, PCIINTxRoute *new); +void pci_bus_fire_intx_routing_notifier(PCIBus *bus); +void pci_device_set_intx_routing_notifier(PCIDevice *dev, +                                          PCIINTxRoutingNotifier notifier); +void pci_device_reset(PCIDevice *dev); + +PCIDevice *pci_nic_init_nofail(NICInfo *nd, PCIBus *rootbus, +                               const char *default_model, +                               const char *default_devaddr); + +PCIDevice *pci_vga_init(PCIBus *bus); + +int pci_bus_num(PCIBus *s); +int pci_bus_numa_node(PCIBus *bus); +void pci_for_each_device(PCIBus *bus, int bus_num, +                         void (*fn)(PCIBus *bus, PCIDevice *d, void *opaque), +                         void *opaque); +void pci_for_each_bus_depth_first(PCIBus *bus, +                                  void *(*begin)(PCIBus *bus, void *parent_state), +                                  void (*end)(PCIBus *bus, void *state), +                                  void *parent_state); + +/* Use this wrapper when specific scan order is not required. */ +static inline +void pci_for_each_bus(PCIBus *bus, +                      void (*fn)(PCIBus *bus, void *opaque), +                      void *opaque) +{ +    pci_for_each_bus_depth_first(bus, NULL, fn, opaque); +} + +PCIBus *pci_find_primary_bus(void); +PCIBus *pci_device_root_bus(const PCIDevice *d); +const char *pci_root_bus_path(PCIDevice *dev); +PCIDevice *pci_find_device(PCIBus *bus, int bus_num, uint8_t devfn); +int pci_qdev_find_device(const char *id, PCIDevice **pdev); +void pci_bus_get_w64_range(PCIBus *bus, Range *range); + +void pci_device_deassert_intx(PCIDevice *dev); + +typedef AddressSpace *(*PCIIOMMUFunc)(PCIBus *, void *, int); + +AddressSpace *pci_device_iommu_address_space(PCIDevice *dev); +void pci_setup_iommu(PCIBus *bus, PCIIOMMUFunc fn, void *opaque); + +static inline void +pci_set_byte(uint8_t *config, uint8_t val) +{ +    *config = val; +} + +static inline uint8_t +pci_get_byte(const uint8_t *config) +{ +    return *config; +} + +static inline void +pci_set_word(uint8_t *config, uint16_t val) +{ +    stw_le_p(config, val); +} + +static inline uint16_t +pci_get_word(const uint8_t *config) +{ +    return lduw_le_p(config); +} + +static inline void +pci_set_long(uint8_t *config, uint32_t val) +{ +    stl_le_p(config, val); +} + +static inline uint32_t +pci_get_long(const uint8_t *config) +{ +    return ldl_le_p(config); +} + +static inline void +pci_set_quad(uint8_t *config, uint64_t val) +{ +    cpu_to_le64w((uint64_t *)config, val); +} + +static inline uint64_t +pci_get_quad(const uint8_t *config) +{ +    return le64_to_cpup((const uint64_t *)config); +} + +static inline void +pci_config_set_vendor_id(uint8_t *pci_config, uint16_t val) +{ +    pci_set_word(&pci_config[PCI_VENDOR_ID], val); +} + +static inline void +pci_config_set_device_id(uint8_t *pci_config, uint16_t val) +{ +    pci_set_word(&pci_config[PCI_DEVICE_ID], val); +} + +static inline void +pci_config_set_revision(uint8_t *pci_config, uint8_t val) +{ +    pci_set_byte(&pci_config[PCI_REVISION_ID], val); +} + +static inline void +pci_config_set_class(uint8_t *pci_config, uint16_t val) +{ +    pci_set_word(&pci_config[PCI_CLASS_DEVICE], val); +} + +static inline void +pci_config_set_prog_interface(uint8_t *pci_config, uint8_t val) +{ +    pci_set_byte(&pci_config[PCI_CLASS_PROG], val); +} + +static inline void +pci_config_set_interrupt_pin(uint8_t *pci_config, uint8_t val) +{ +    pci_set_byte(&pci_config[PCI_INTERRUPT_PIN], val); +} + +/* + * helper functions to do bit mask operation on configuration space. + * Just to set bit, use test-and-set and discard returned value. + * Just to clear bit, use test-and-clear and discard returned value. + * NOTE: They aren't atomic. + */ +static inline uint8_t +pci_byte_test_and_clear_mask(uint8_t *config, uint8_t mask) +{ +    uint8_t val = pci_get_byte(config); +    pci_set_byte(config, val & ~mask); +    return val & mask; +} + +static inline uint8_t +pci_byte_test_and_set_mask(uint8_t *config, uint8_t mask) +{ +    uint8_t val = pci_get_byte(config); +    pci_set_byte(config, val | mask); +    return val & mask; +} + +static inline uint16_t +pci_word_test_and_clear_mask(uint8_t *config, uint16_t mask) +{ +    uint16_t val = pci_get_word(config); +    pci_set_word(config, val & ~mask); +    return val & mask; +} + +static inline uint16_t +pci_word_test_and_set_mask(uint8_t *config, uint16_t mask) +{ +    uint16_t val = pci_get_word(config); +    pci_set_word(config, val | mask); +    return val & mask; +} + +static inline uint32_t +pci_long_test_and_clear_mask(uint8_t *config, uint32_t mask) +{ +    uint32_t val = pci_get_long(config); +    pci_set_long(config, val & ~mask); +    return val & mask; +} + +static inline uint32_t +pci_long_test_and_set_mask(uint8_t *config, uint32_t mask) +{ +    uint32_t val = pci_get_long(config); +    pci_set_long(config, val | mask); +    return val & mask; +} + +static inline uint64_t +pci_quad_test_and_clear_mask(uint8_t *config, uint64_t mask) +{ +    uint64_t val = pci_get_quad(config); +    pci_set_quad(config, val & ~mask); +    return val & mask; +} + +static inline uint64_t +pci_quad_test_and_set_mask(uint8_t *config, uint64_t mask) +{ +    uint64_t val = pci_get_quad(config); +    pci_set_quad(config, val | mask); +    return val & mask; +} + +/* Access a register specified by a mask */ +static inline void +pci_set_byte_by_mask(uint8_t *config, uint8_t mask, uint8_t reg) +{ +    uint8_t val = pci_get_byte(config); +    uint8_t rval = reg << ctz32(mask); +    pci_set_byte(config, (~mask & val) | (mask & rval)); +} + +static inline uint8_t +pci_get_byte_by_mask(uint8_t *config, uint8_t mask) +{ +    uint8_t val = pci_get_byte(config); +    return (val & mask) >> ctz32(mask); +} + +static inline void +pci_set_word_by_mask(uint8_t *config, uint16_t mask, uint16_t reg) +{ +    uint16_t val = pci_get_word(config); +    uint16_t rval = reg << ctz32(mask); +    pci_set_word(config, (~mask & val) | (mask & rval)); +} + +static inline uint16_t +pci_get_word_by_mask(uint8_t *config, uint16_t mask) +{ +    uint16_t val = pci_get_word(config); +    return (val & mask) >> ctz32(mask); +} + +static inline void +pci_set_long_by_mask(uint8_t *config, uint32_t mask, uint32_t reg) +{ +    uint32_t val = pci_get_long(config); +    uint32_t rval = reg << ctz32(mask); +    pci_set_long(config, (~mask & val) | (mask & rval)); +} + +static inline uint32_t +pci_get_long_by_mask(uint8_t *config, uint32_t mask) +{ +    uint32_t val = pci_get_long(config); +    return (val & mask) >> ctz32(mask); +} + +static inline void +pci_set_quad_by_mask(uint8_t *config, uint64_t mask, uint64_t reg) +{ +    uint64_t val = pci_get_quad(config); +    uint64_t rval = reg << ctz32(mask); +    pci_set_quad(config, (~mask & val) | (mask & rval)); +} + +static inline uint64_t +pci_get_quad_by_mask(uint8_t *config, uint64_t mask) +{ +    uint64_t val = pci_get_quad(config); +    return (val & mask) >> ctz32(mask); +} + +PCIDevice *pci_create_multifunction(PCIBus *bus, int devfn, bool multifunction, +                                    const char *name); +PCIDevice *pci_create_simple_multifunction(PCIBus *bus, int devfn, +                                           bool multifunction, +                                           const char *name); +PCIDevice *pci_create(PCIBus *bus, int devfn, const char *name); +PCIDevice *pci_create_simple(PCIBus *bus, int devfn, const char *name); + +qemu_irq pci_allocate_irq(PCIDevice *pci_dev); +void pci_set_irq(PCIDevice *pci_dev, int level); + +static inline void pci_irq_assert(PCIDevice *pci_dev) +{ +    pci_set_irq(pci_dev, 1); +} + +static inline void pci_irq_deassert(PCIDevice *pci_dev) +{ +    pci_set_irq(pci_dev, 0); +} + +/* + * FIXME: PCI does not work this way. + * All the callers to this method should be fixed. + */ +static inline void pci_irq_pulse(PCIDevice *pci_dev) +{ +    pci_irq_assert(pci_dev); +    pci_irq_deassert(pci_dev); +} + +static inline int pci_is_express(const PCIDevice *d) +{ +    return d->cap_present & QEMU_PCI_CAP_EXPRESS; +} + +static inline uint32_t pci_config_size(const PCIDevice *d) +{ +    return pci_is_express(d) ? PCIE_CONFIG_SPACE_SIZE : PCI_CONFIG_SPACE_SIZE; +} + +/* DMA access functions */ +static inline AddressSpace *pci_get_address_space(PCIDevice *dev) +{ +    return &dev->bus_master_as; +} + +static inline int pci_dma_rw(PCIDevice *dev, dma_addr_t addr, +                             void *buf, dma_addr_t len, DMADirection dir) +{ +    dma_memory_rw(pci_get_address_space(dev), addr, buf, len, dir); +    return 0; +} + +static inline int pci_dma_read(PCIDevice *dev, dma_addr_t addr, +                               void *buf, dma_addr_t len) +{ +    return pci_dma_rw(dev, addr, buf, len, DMA_DIRECTION_TO_DEVICE); +} + +static inline int pci_dma_write(PCIDevice *dev, dma_addr_t addr, +                                const void *buf, dma_addr_t len) +{ +    return pci_dma_rw(dev, addr, (void *) buf, len, DMA_DIRECTION_FROM_DEVICE); +} + +#define PCI_DMA_DEFINE_LDST(_l, _s, _bits)                              \ +    static inline uint##_bits##_t ld##_l##_pci_dma(PCIDevice *dev,      \ +                                                   dma_addr_t addr)     \ +    {                                                                   \ +        return ld##_l##_dma(pci_get_address_space(dev), addr);          \ +    }                                                                   \ +    static inline void st##_s##_pci_dma(PCIDevice *dev,                 \ +                                        dma_addr_t addr, uint##_bits##_t val) \ +    {                                                                   \ +        st##_s##_dma(pci_get_address_space(dev), addr, val);            \ +    } + +PCI_DMA_DEFINE_LDST(ub, b, 8); +PCI_DMA_DEFINE_LDST(uw_le, w_le, 16) +PCI_DMA_DEFINE_LDST(l_le, l_le, 32); +PCI_DMA_DEFINE_LDST(q_le, q_le, 64); +PCI_DMA_DEFINE_LDST(uw_be, w_be, 16) +PCI_DMA_DEFINE_LDST(l_be, l_be, 32); +PCI_DMA_DEFINE_LDST(q_be, q_be, 64); + +#undef PCI_DMA_DEFINE_LDST + +static inline void *pci_dma_map(PCIDevice *dev, dma_addr_t addr, +                                dma_addr_t *plen, DMADirection dir) +{ +    void *buf; + +    buf = dma_memory_map(pci_get_address_space(dev), addr, plen, dir); +    return buf; +} + +static inline void pci_dma_unmap(PCIDevice *dev, void *buffer, dma_addr_t len, +                                 DMADirection dir, dma_addr_t access_len) +{ +    dma_memory_unmap(pci_get_address_space(dev), buffer, len, dir, access_len); +} + +static inline void pci_dma_sglist_init(QEMUSGList *qsg, PCIDevice *dev, +                                       int alloc_hint) +{ +    qemu_sglist_init(qsg, DEVICE(dev), alloc_hint, pci_get_address_space(dev)); +} + +extern const VMStateDescription vmstate_pci_device; + +#define VMSTATE_PCI_DEVICE(_field, _state) {                         \ +    .name       = (stringify(_field)),                               \ +    .size       = sizeof(PCIDevice),                                 \ +    .vmsd       = &vmstate_pci_device,                               \ +    .flags      = VMS_STRUCT,                                        \ +    .offset     = vmstate_offset_value(_state, _field, PCIDevice),   \ +} + +#define VMSTATE_PCI_DEVICE_POINTER(_field, _state) {                 \ +    .name       = (stringify(_field)),                               \ +    .size       = sizeof(PCIDevice),                                 \ +    .vmsd       = &vmstate_pci_device,                               \ +    .flags      = VMS_STRUCT|VMS_POINTER,                            \ +    .offset     = vmstate_offset_pointer(_state, _field, PCIDevice), \ +} + +#endif diff --git a/include/hw/pci/pci_bridge.h b/include/hw/pci/pci_bridge.h new file mode 100644 index 00000000..93b621ce --- /dev/null +++ b/include/hw/pci/pci_bridge.h @@ -0,0 +1,70 @@ +/* + * QEMU PCI bridge + * + * Copyright (c) 2004 Fabrice Bellard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA. + * + * split out pci bus specific stuff from pci.[hc] to pci_bridge.[hc] + * Copyright (c) 2009 Isaku Yamahata <yamahata at valinux co jp> + *                    VA Linux Systems Japan K.K. + * + */ + +#ifndef QEMU_PCI_BRIDGE_H +#define QEMU_PCI_BRIDGE_H + +#include "hw/pci/pci.h" + +#define PCI_BRIDGE_DEV_PROP_CHASSIS_NR "chassis_nr" +#define PCI_BRIDGE_DEV_PROP_MSI        "msi" +#define PCI_BRIDGE_DEV_PROP_SHPC       "shpc" + +int pci_bridge_ssvid_init(PCIDevice *dev, uint8_t offset, +                          uint16_t svid, uint16_t ssid); + +PCIDevice *pci_bridge_get_device(PCIBus *bus); +PCIBus *pci_bridge_get_sec_bus(PCIBridge *br); + +pcibus_t pci_bridge_get_base(const PCIDevice *bridge, uint8_t type); +pcibus_t pci_bridge_get_limit(const PCIDevice *bridge, uint8_t type); + +void pci_bridge_update_mappings(PCIBridge *br); +void pci_bridge_write_config(PCIDevice *d, +                             uint32_t address, uint32_t val, int len); +void pci_bridge_disable_base_limit(PCIDevice *dev); +void pci_bridge_reset_reg(PCIDevice *dev); +void pci_bridge_reset(DeviceState *qdev); + +int pci_bridge_initfn(PCIDevice *pci_dev, const char *typename); +void pci_bridge_exitfn(PCIDevice *pci_dev); + + +/* + * before qdev initialization(qdev_init()), this function sets bus_name and + * map_irq callback which are necessry for pci_bridge_initfn() to + * initialize bus. + */ +void pci_bridge_map_irq(PCIBridge *br, const char* bus_name, +                        pci_map_irq_fn map_irq); + +/* TODO: add this define to pci_regs.h in linux and then in qemu. */ +#define  PCI_BRIDGE_CTL_VGA_16BIT	0x10	/* VGA 16-bit decode */ +#define  PCI_BRIDGE_CTL_DISCARD		0x100	/* Primary discard timer */ +#define  PCI_BRIDGE_CTL_SEC_DISCARD	0x200	/* Secondary discard timer */ +#define  PCI_BRIDGE_CTL_DISCARD_STATUS	0x400	/* Discard timer status */ +#define  PCI_BRIDGE_CTL_DISCARD_SERR	0x800	/* Discard timer SERR# enable */ + +#endif  /* QEMU_PCI_BRIDGE_H */ diff --git a/include/hw/pci/pci_bus.h b/include/hw/pci/pci_bus.h new file mode 100644 index 00000000..403fec6e --- /dev/null +++ b/include/hw/pci/pci_bus.h @@ -0,0 +1,91 @@ +#ifndef QEMU_PCI_BUS_H +#define QEMU_PCI_BUS_H + +/* + * PCI Bus and Bridge datastructures. + * + * Do not access the following members directly; + * use accessor functions in pci.h, pci_bridge.h + */ + +typedef struct PCIBusClass { +    /*< private >*/ +    BusClass parent_class; +    /*< public >*/ + +    bool (*is_root)(PCIBus *bus); +    int (*bus_num)(PCIBus *bus); +    uint16_t (*numa_node)(PCIBus *bus); +} PCIBusClass; + +struct PCIBus { +    BusState qbus; +    PCIIOMMUFunc iommu_fn; +    void *iommu_opaque; +    uint8_t devfn_min; +    pci_set_irq_fn set_irq; +    pci_map_irq_fn map_irq; +    pci_route_irq_fn route_intx_to_irq; +    void *irq_opaque; +    PCIDevice *devices[PCI_SLOT_MAX * PCI_FUNC_MAX]; +    PCIDevice *parent_dev; +    MemoryRegion *address_space_mem; +    MemoryRegion *address_space_io; + +    QLIST_HEAD(, PCIBus) child; /* this will be replaced by qdev later */ +    QLIST_ENTRY(PCIBus) sibling;/* this will be replaced by qdev later */ + +    /* The bus IRQ state is the logical OR of the connected devices. +       Keep a count of the number of devices with raised IRQs.  */ +    int nirq; +    int *irq_count; +}; + +typedef struct PCIBridgeWindows PCIBridgeWindows; + +/* + * Aliases for each of the address space windows that the bridge + * can forward. Mapped into the bridge's parent's address space, + * as subregions. + */ +struct PCIBridgeWindows { +    MemoryRegion alias_pref_mem; +    MemoryRegion alias_mem; +    MemoryRegion alias_io; +    /* +     * When bridge control VGA forwarding is enabled, bridges will +     * provide positive decode on the PCI VGA defined I/O port and +     * MMIO ranges.  When enabled forwarding is only qualified on the +     * I/O and memory enable bits in the bridge command register. +     */ +    MemoryRegion alias_vga[QEMU_PCI_VGA_NUM_REGIONS]; +}; + +#define TYPE_PCI_BRIDGE "base-pci-bridge" +#define PCI_BRIDGE(obj) OBJECT_CHECK(PCIBridge, (obj), TYPE_PCI_BRIDGE) + +struct PCIBridge { +    /*< private >*/ +    PCIDevice parent_obj; +    /*< public >*/ + +    /* private member */ +    PCIBus sec_bus; +    /* +     * Memory regions for the bridge's address spaces.  These regions are not +     * directly added to system_memory/system_io or its descendants. +     * Bridge's secondary bus points to these, so that devices +     * under the bridge see these regions as its address spaces. +     * The regions are as large as the entire address space - +     * they don't take into account any windows. +     */ +    MemoryRegion address_space_mem; +    MemoryRegion address_space_io; + +    PCIBridgeWindows *windows; + +    pci_map_irq_fn map_irq; +    const char *bus_name; +}; + +#endif /* QEMU_PCI_BUS_H */ diff --git a/include/hw/pci/pci_host.h b/include/hw/pci/pci_host.h new file mode 100644 index 00000000..ba31595f --- /dev/null +++ b/include/hw/pci/pci_host.h @@ -0,0 +1,73 @@ +/* + * QEMU Common PCI Host bridge configuration data space access routines. + * + * Copyright (c) 2006 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * 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 OTHER + * 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. + */ + +/* Worker routines for a PCI host controller that uses an {address,data} +   register pair to access PCI configuration space.  */ + +#ifndef PCI_HOST_H +#define PCI_HOST_H + +#include "hw/sysbus.h" + +#define TYPE_PCI_HOST_BRIDGE "pci-host-bridge" +#define PCI_HOST_BRIDGE(obj) \ +    OBJECT_CHECK(PCIHostState, (obj), TYPE_PCI_HOST_BRIDGE) +#define PCI_HOST_BRIDGE_CLASS(klass) \ +     OBJECT_CLASS_CHECK(PCIHostBridgeClass, (klass), TYPE_PCI_HOST_BRIDGE) +#define PCI_HOST_BRIDGE_GET_CLASS(obj) \ +     OBJECT_GET_CLASS(PCIHostBridgeClass, (obj), TYPE_PCI_HOST_BRIDGE) + +struct PCIHostState { +    SysBusDevice busdev; + +    MemoryRegion conf_mem; +    MemoryRegion data_mem; +    MemoryRegion mmcfg; +    uint32_t config_reg; +    PCIBus *bus; + +    QLIST_ENTRY(PCIHostState) next; +}; + +typedef struct PCIHostBridgeClass { +    SysBusDeviceClass parent_class; + +    const char *(*root_bus_path)(PCIHostState *, PCIBus *); +} PCIHostBridgeClass; + +/* common internal helpers for PCI/PCIe hosts, cut off overflows */ +void pci_host_config_write_common(PCIDevice *pci_dev, uint32_t addr, +                                  uint32_t limit, uint32_t val, uint32_t len); +uint32_t pci_host_config_read_common(PCIDevice *pci_dev, uint32_t addr, +                                     uint32_t limit, uint32_t len); + +void pci_data_write(PCIBus *s, uint32_t addr, uint32_t val, int len); +uint32_t pci_data_read(PCIBus *s, uint32_t addr, int len); + +extern const MemoryRegionOps pci_host_conf_le_ops; +extern const MemoryRegionOps pci_host_conf_be_ops; +extern const MemoryRegionOps pci_host_data_le_ops; +extern const MemoryRegionOps pci_host_data_be_ops; + +#endif /* PCI_HOST_H */ diff --git a/include/hw/pci/pci_ids.h b/include/hw/pci/pci_ids.h new file mode 100644 index 00000000..d98e6c91 --- /dev/null +++ b/include/hw/pci/pci_ids.h @@ -0,0 +1,168 @@ +/* + *      PCI Class, Vendor and Device IDs + * + *      Please keep sorted. + * + *      Abbreviated version of linux/pci_ids.h + * + *      QEMU-specific definitions belong in pci.h + */ +#ifndef HW_PCI_IDS_H +#define HW_PCI_IDS_H 1 + +/* Device classes and subclasses */ + +#define PCI_BASE_CLASS_STORAGE           0x01 +#define PCI_BASE_CLASS_NETWORK           0x02 + +#define PCI_CLASS_STORAGE_SCSI           0x0100 +#define PCI_CLASS_STORAGE_IDE            0x0101 +#define PCI_CLASS_STORAGE_RAID           0x0104 +#define PCI_CLASS_STORAGE_SATA           0x0106 +#define PCI_CLASS_STORAGE_EXPRESS        0x0108 +#define PCI_CLASS_STORAGE_OTHER          0x0180 + +#define PCI_CLASS_NETWORK_ETHERNET       0x0200 +#define PCI_CLASS_NETWORK_OTHER          0x0280 + +#define PCI_CLASS_DISPLAY_VGA            0x0300 +#define PCI_CLASS_DISPLAY_OTHER          0x0380 + +#define PCI_CLASS_MULTIMEDIA_AUDIO       0x0401 + +#define PCI_CLASS_MEMORY_RAM             0x0500 + +#define PCI_CLASS_SYSTEM_SDHCI           0x0805 +#define PCI_CLASS_SYSTEM_OTHER           0x0880 + +#define PCI_CLASS_SERIAL_USB             0x0c03 +#define PCI_CLASS_SERIAL_SMBUS           0x0c05 + +#define PCI_CLASS_BRIDGE_HOST            0x0600 +#define PCI_CLASS_BRIDGE_ISA             0x0601 +#define PCI_CLASS_BRIDGE_PCI             0x0604 +#define PCI_CLASS_BRIDGE_PCI_INF_SUB     0x01 +#define PCI_CLASS_BRIDGE_OTHER           0x0680 + +#define PCI_CLASS_COMMUNICATION_SERIAL   0x0700 +#define PCI_CLASS_COMMUNICATION_OTHER    0x0780 + +#define PCI_CLASS_INPUT_KEYBOARD         0x0900 +#define PCI_CLASS_INPUT_PEN              0x0901 +#define PCI_CLASS_INPUT_MOUSE            0x0902 +#define PCI_CLASS_INPUT_SCANNER          0x0903 +#define PCI_CLASS_INPUT_GAMEPORT         0x0904 +#define PCI_CLASS_INPUT_OTHER            0x0980 + +#define PCI_CLASS_PROCESSOR_CO           0x0b40 +#define PCI_CLASS_PROCESSOR_POWERPC      0x0b20 + +#define PCI_CLASS_OTHERS                 0xff + +/* Vendors and devices.  Sort key: vendor first, device next. */ + +#define PCI_VENDOR_ID_LSI_LOGIC          0x1000 +#define PCI_DEVICE_ID_LSI_53C810         0x0001 +#define PCI_DEVICE_ID_LSI_53C895A        0x0012 +#define PCI_DEVICE_ID_LSI_SAS1078        0x0060 +#define PCI_DEVICE_ID_LSI_SAS0079        0x0079 + +#define PCI_VENDOR_ID_DEC                0x1011 +#define PCI_DEVICE_ID_DEC_21154          0x0026 + +#define PCI_VENDOR_ID_CIRRUS             0x1013 + +#define PCI_VENDOR_ID_IBM                0x1014 + +#define PCI_VENDOR_ID_AMD                0x1022 +#define PCI_DEVICE_ID_AMD_LANCE          0x2000 +#define PCI_DEVICE_ID_AMD_SCSI           0x2020 + +#define PCI_VENDOR_ID_TI                 0x104c + +#define PCI_VENDOR_ID_MOTOROLA           0x1057 +#define PCI_DEVICE_ID_MOTOROLA_MPC106    0x0002 +#define PCI_DEVICE_ID_MOTOROLA_RAVEN     0x4801 + +#define PCI_VENDOR_ID_APPLE              0x106b +#define PCI_DEVICE_ID_APPLE_UNI_N_AGP    0x0020 +#define PCI_DEVICE_ID_APPLE_U3_AGP       0x004b + +#define PCI_VENDOR_ID_SUN                0x108e +#define PCI_DEVICE_ID_SUN_EBUS           0x1000 +#define PCI_DEVICE_ID_SUN_SIMBA          0x5000 +#define PCI_DEVICE_ID_SUN_SABRE          0xa000 + +#define PCI_VENDOR_ID_CMD                0x1095 +#define PCI_DEVICE_ID_CMD_646            0x0646 + +#define PCI_VENDOR_ID_REALTEK            0x10ec +#define PCI_DEVICE_ID_REALTEK_8139       0x8139 + +#define PCI_VENDOR_ID_XILINX             0x10ee + +#define PCI_VENDOR_ID_VIA                0x1106 +#define PCI_DEVICE_ID_VIA_ISA_BRIDGE     0x0686 +#define PCI_DEVICE_ID_VIA_IDE            0x0571 +#define PCI_DEVICE_ID_VIA_UHCI           0x3038 +#define PCI_DEVICE_ID_VIA_ACPI           0x3057 +#define PCI_DEVICE_ID_VIA_AC97           0x3058 +#define PCI_DEVICE_ID_VIA_MC97           0x3068 + +#define PCI_VENDOR_ID_MARVELL            0x11ab + +#define PCI_VENDOR_ID_ENSONIQ            0x1274 +#define PCI_DEVICE_ID_ENSONIQ_ES1370     0x5000 + +#define PCI_VENDOR_ID_CHELSIO            0x1425 + +#define PCI_VENDOR_ID_FREESCALE          0x1957 +#define PCI_DEVICE_ID_MPC8533E           0x0030 + +#define PCI_VENDOR_ID_INTEL              0x8086 +#define PCI_DEVICE_ID_INTEL_82378        0x0484 +#define PCI_DEVICE_ID_INTEL_82441        0x1237 +#define PCI_DEVICE_ID_INTEL_82801AA_5    0x2415 +#define PCI_DEVICE_ID_INTEL_82801BA_11   0x244e +#define PCI_DEVICE_ID_INTEL_82801D       0x24CD +#define PCI_DEVICE_ID_INTEL_ESB_9        0x25ab +#define PCI_DEVICE_ID_INTEL_82371SB_0    0x7000 +#define PCI_DEVICE_ID_INTEL_82371SB_1    0x7010 +#define PCI_DEVICE_ID_INTEL_82371SB_2    0x7020 +#define PCI_DEVICE_ID_INTEL_82371AB_0    0x7110 +#define PCI_DEVICE_ID_INTEL_82371AB      0x7111 +#define PCI_DEVICE_ID_INTEL_82371AB_2    0x7112 +#define PCI_DEVICE_ID_INTEL_82371AB_3    0x7113 + +#define PCI_DEVICE_ID_INTEL_ICH9_0       0x2910 +#define PCI_DEVICE_ID_INTEL_ICH9_1       0x2917 +#define PCI_DEVICE_ID_INTEL_ICH9_2       0x2912 +#define PCI_DEVICE_ID_INTEL_ICH9_3       0x2913 +#define PCI_DEVICE_ID_INTEL_ICH9_4       0x2914 +#define PCI_DEVICE_ID_INTEL_ICH9_5       0x2919 +#define PCI_DEVICE_ID_INTEL_ICH9_6       0x2930 +#define PCI_DEVICE_ID_INTEL_ICH9_7       0x2916 +#define PCI_DEVICE_ID_INTEL_ICH9_8       0x2918 + +#define PCI_DEVICE_ID_INTEL_82801I_UHCI1 0x2934 +#define PCI_DEVICE_ID_INTEL_82801I_UHCI2 0x2935 +#define PCI_DEVICE_ID_INTEL_82801I_UHCI3 0x2936 +#define PCI_DEVICE_ID_INTEL_82801I_UHCI4 0x2937 +#define PCI_DEVICE_ID_INTEL_82801I_UHCI5 0x2938 +#define PCI_DEVICE_ID_INTEL_82801I_UHCI6 0x2939 +#define PCI_DEVICE_ID_INTEL_82801I_EHCI1 0x293a +#define PCI_DEVICE_ID_INTEL_82801I_EHCI2 0x293c +#define PCI_DEVICE_ID_INTEL_82599_SFP_VF 0x10ed + +#define PCI_DEVICE_ID_INTEL_Q35_MCH      0x29c0 + +#define PCI_VENDOR_ID_XEN                0x5853 +#define PCI_DEVICE_ID_XEN_PLATFORM       0x0001 + +#define PCI_VENDOR_ID_NEC                0x1033 +#define PCI_DEVICE_ID_NEC_UPD720200      0x0194 + +#define PCI_VENDOR_ID_TEWS               0x1498 +#define PCI_DEVICE_ID_TEWS_TPCI200       0x30C8 + +#endif diff --git a/include/hw/pci/pci_regs.h b/include/hw/pci/pci_regs.h new file mode 100644 index 00000000..ba8cbe92 --- /dev/null +++ b/include/hw/pci/pci_regs.h @@ -0,0 +1 @@ +#include "standard-headers/linux/pci_regs.h" diff --git a/include/hw/pci/pcie.h b/include/hw/pci/pcie.h new file mode 100644 index 00000000..b48a7a2c --- /dev/null +++ b/include/hw/pci/pcie.h @@ -0,0 +1,133 @@ +/* + * pcie.h + * + * Copyright (c) 2010 Isaku Yamahata <yamahata at valinux co jp> + *                    VA Linux Systems Japan K.K. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef QEMU_PCIE_H +#define QEMU_PCIE_H + +#include "hw/hw.h" +#include "hw/pci/pci_regs.h" +#include "hw/pci/pcie_regs.h" +#include "hw/pci/pcie_aer.h" +#include "hw/hotplug.h" + +typedef enum { +    /* for attention and power indicator */ +    PCI_EXP_HP_IND_RESERVED     = PCI_EXP_SLTCTL_IND_RESERVED, +    PCI_EXP_HP_IND_ON           = PCI_EXP_SLTCTL_IND_ON, +    PCI_EXP_HP_IND_BLINK        = PCI_EXP_SLTCTL_IND_BLINK, +    PCI_EXP_HP_IND_OFF          = PCI_EXP_SLTCTL_IND_OFF, +} PCIExpressIndicator; + +typedef enum { +    /* these bits must match the bits in Slot Control/Status registers. +     * PCI_EXP_HP_EV_xxx = PCI_EXP_SLTCTL_xxxE = PCI_EXP_SLTSTA_xxx +     * +     * Not all the bits of slot control register match with the ones of +     * slot status. Not some bits of slot status register is used to +     * show status, not to report event occurrence. +     * So such bits must be masked out when checking the software +     * notification condition. +     */ +    PCI_EXP_HP_EV_ABP           = PCI_EXP_SLTCTL_ABPE, +                                        /* attention button pressed */ +    PCI_EXP_HP_EV_PDC           = PCI_EXP_SLTCTL_PDCE, +                                        /* presence detect changed */ +    PCI_EXP_HP_EV_CCI           = PCI_EXP_SLTCTL_CCIE, +                                        /* command completed */ + +    PCI_EXP_HP_EV_SUPPORTED     = PCI_EXP_HP_EV_ABP | +                                  PCI_EXP_HP_EV_PDC | +                                  PCI_EXP_HP_EV_CCI, +                                                /* supported event mask  */ + +    /* events not listed aren't supported */ +} PCIExpressHotPlugEvent; + +struct PCIExpressDevice { +    /* Offset of express capability in config space */ +    uint8_t exp_cap; + +    /* SLOT */ +    bool hpev_notified; /* Logical AND of conditions for hot plug event. +                         Following 6.7.3.4: +                         Software Notification of Hot-Plug Events, an interrupt +                         is sent whenever the logical and of these conditions +                         transitions from false to true. */ + +    /* AER */ +    uint16_t aer_cap; +    PCIEAERLog aer_log; +}; + +#define COMPAT_PROP_PCP "power_controller_present" + +/* PCI express capability helper functions */ +int pcie_cap_init(PCIDevice *dev, uint8_t offset, uint8_t type, uint8_t port); +int pcie_endpoint_cap_init(PCIDevice *dev, uint8_t offset); +void pcie_cap_exit(PCIDevice *dev); +uint8_t pcie_cap_get_type(const PCIDevice *dev); +void pcie_cap_flags_set_vector(PCIDevice *dev, uint8_t vector); +uint8_t pcie_cap_flags_get_vector(PCIDevice *dev); + +void pcie_cap_deverr_init(PCIDevice *dev); +void pcie_cap_deverr_reset(PCIDevice *dev); + +void pcie_cap_slot_init(PCIDevice *dev, uint16_t slot); +void pcie_cap_slot_reset(PCIDevice *dev); +void pcie_cap_slot_write_config(PCIDevice *dev, +                                uint32_t addr, uint32_t val, int len); +int pcie_cap_slot_post_load(void *opaque, int version_id); +void pcie_cap_slot_push_attention_button(PCIDevice *dev); + +void pcie_cap_root_init(PCIDevice *dev); +void pcie_cap_root_reset(PCIDevice *dev); + +void pcie_cap_flr_init(PCIDevice *dev); +void pcie_cap_flr_write_config(PCIDevice *dev, +                           uint32_t addr, uint32_t val, int len); + +/* ARI forwarding capability and control */ +void pcie_cap_arifwd_init(PCIDevice *dev); +void pcie_cap_arifwd_reset(PCIDevice *dev); +bool pcie_cap_is_arifwd_enabled(const PCIDevice *dev); + +/* PCI express extended capability helper functions */ +uint16_t pcie_find_capability(PCIDevice *dev, uint16_t cap_id); +void pcie_add_capability(PCIDevice *dev, +                         uint16_t cap_id, uint8_t cap_ver, +                         uint16_t offset, uint16_t size); + +void pcie_ari_init(PCIDevice *dev, uint16_t offset, uint16_t nextfn); + +extern const VMStateDescription vmstate_pcie_device; + +#define VMSTATE_PCIE_DEVICE(_field, _state) {                        \ +    .name       = (stringify(_field)),                               \ +    .size       = sizeof(PCIDevice),                                 \ +    .vmsd       = &vmstate_pcie_device,                              \ +    .flags      = VMS_STRUCT,                                        \ +    .offset     = vmstate_offset_value(_state, _field, PCIDevice),   \ +} + +void pcie_cap_slot_hotplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, +                              Error **errp); +void pcie_cap_slot_hot_unplug_request_cb(HotplugHandler *hotplug_dev, +                                         DeviceState *dev, Error **errp); +#endif /* QEMU_PCIE_H */ diff --git a/include/hw/pci/pcie_aer.h b/include/hw/pci/pcie_aer.h new file mode 100644 index 00000000..2fb83882 --- /dev/null +++ b/include/hw/pci/pcie_aer.h @@ -0,0 +1,106 @@ +/* + * pcie_aer.h + * + * Copyright (c) 2010 Isaku Yamahata <yamahata at valinux co jp> + *                    VA Linux Systems Japan K.K. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef QEMU_PCIE_AER_H +#define QEMU_PCIE_AER_H + +#include "hw/hw.h" + +/* definitions which PCIExpressDevice uses */ + +/* AER log */ +struct PCIEAERLog { +    /* This structure is saved/loaded. +       So explicitly size them instead of unsigned int */ + +    /* the number of currently recorded log in log member */ +    uint16_t log_num; + +    /* +     * The maximum number of the log. Errors can be logged up to this. +     * +     * This is configurable property. +     * The specified value will be clipped down to PCIE_AER_LOG_MAX_LIMIT +     * to avoid unreasonable memory usage. +     * I bet that 128 log size would be big enough, otherwise too many errors +     * for system to function normaly. But could consecutive errors occur? +     */ +#define PCIE_AER_LOG_MAX_DEFAULT        8 +#define PCIE_AER_LOG_MAX_LIMIT          128 +#define PCIE_AER_LOG_MAX_UNSET          0xffff +    uint16_t log_max; + +    /* Error log. log_max-sized array */ +    PCIEAERErr *log; +}; + +/* aer error message: error signaling message has only error severity and +   source id. See 2.2.8.3 error signaling messages */ +struct PCIEAERMsg { +    /* +     * PCI_ERR_ROOT_CMD_{COR, NONFATAL, FATAL}_EN +     * = PCI_EXP_DEVCTL_{CERE, NFERE, FERE} +     */ +    uint32_t severity; + +    uint16_t source_id; /* bdf */ +}; + +static inline bool +pcie_aer_msg_is_uncor(const PCIEAERMsg *msg) +{ +    return msg->severity == PCI_ERR_ROOT_CMD_NONFATAL_EN || +        msg->severity == PCI_ERR_ROOT_CMD_FATAL_EN; +} + +/* error */ +struct PCIEAERErr { +    uint32_t status;    /* error status bits */ +    uint16_t source_id; /* bdf */ + +#define PCIE_AER_ERR_IS_CORRECTABLE     0x1     /* correctable/uncorrectable */ +#define PCIE_AER_ERR_MAYBE_ADVISORY     0x2     /* maybe advisory non-fatal */ +#define PCIE_AER_ERR_HEADER_VALID       0x4     /* TLP header is logged */ +#define PCIE_AER_ERR_TLP_PREFIX_PRESENT 0x8     /* TLP Prefix is logged */ +    uint16_t flags; + +    uint32_t header[4]; /* TLP header */ +    uint32_t prefix[4]; /* TLP header prefix */ +}; + +extern const VMStateDescription vmstate_pcie_aer_log; + +int pcie_aer_init(PCIDevice *dev, uint16_t offset); +void pcie_aer_exit(PCIDevice *dev); +void pcie_aer_write_config(PCIDevice *dev, +                           uint32_t addr, uint32_t val, int len); + +/* aer root port */ +void pcie_aer_root_set_vector(PCIDevice *dev, unsigned int vector); +void pcie_aer_root_init(PCIDevice *dev); +void pcie_aer_root_reset(PCIDevice *dev); +void pcie_aer_root_write_config(PCIDevice *dev, +                                uint32_t addr, uint32_t val, int len, +                                uint32_t root_cmd_prev); + +/* error injection */ +int pcie_aer_inject_error(PCIDevice *dev, const PCIEAERErr *err); + +#endif /* QEMU_PCIE_AER_H */ diff --git a/include/hw/pci/pcie_host.h b/include/hw/pci/pcie_host.h new file mode 100644 index 00000000..4d23c807 --- /dev/null +++ b/include/hw/pci/pcie_host.h @@ -0,0 +1,81 @@ +/* + * pcie_host.h + * + * Copyright (c) 2009 Isaku Yamahata <yamahata at valinux co jp> + *                    VA Linux Systems Japan K.K. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along + * with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef PCIE_HOST_H +#define PCIE_HOST_H + +#include "hw/pci/pci_host.h" +#include "exec/memory.h" + +#define TYPE_PCIE_HOST_BRIDGE "pcie-host-bridge" +#define PCIE_HOST_BRIDGE(obj) \ +    OBJECT_CHECK(PCIExpressHost, (obj), TYPE_PCIE_HOST_BRIDGE) + +#define PCIE_HOST_MCFG_BASE "MCFG" +#define PCIE_HOST_MCFG_SIZE "mcfg_size" + +/* pcie_host::base_addr == PCIE_BASE_ADDR_UNMAPPED when it isn't mapped. */ +#define PCIE_BASE_ADDR_UNMAPPED  ((hwaddr)-1ULL) + +struct PCIExpressHost { +    PCIHostState pci; + +    /* express part */ + +    /* base address where MMCONFIG area is mapped. */ +    hwaddr  base_addr; + +    /* the size of MMCONFIG area. It's host bridge dependent */ +    hwaddr  size; + +    /* MMCONFIG mmio area */ +    MemoryRegion mmio; +}; + +void pcie_host_mmcfg_unmap(PCIExpressHost *e); +void pcie_host_mmcfg_init(PCIExpressHost *e, uint32_t size); +void pcie_host_mmcfg_map(PCIExpressHost *e, hwaddr addr, uint32_t size); +void pcie_host_mmcfg_update(PCIExpressHost *e, +                            int enable, +                            hwaddr addr, +                            uint32_t size); + +/* + * PCI express ECAM (Enhanced Configuration Address Mapping) format. + * AKA mmcfg address + * bit 20 - 28: bus number + * bit 15 - 19: device number + * bit 12 - 14: function number + * bit  0 - 11: offset in configuration space of a given device + */ +#define PCIE_MMCFG_SIZE_MAX             (1ULL << 28) +#define PCIE_MMCFG_SIZE_MIN             (1ULL << 20) +#define PCIE_MMCFG_BUS_BIT              20 +#define PCIE_MMCFG_BUS_MASK             0x1ff +#define PCIE_MMCFG_DEVFN_BIT            12 +#define PCIE_MMCFG_DEVFN_MASK           0xff +#define PCIE_MMCFG_CONFOFFSET_MASK      0xfff +#define PCIE_MMCFG_BUS(addr)            (((addr) >> PCIE_MMCFG_BUS_BIT) & \ +                                         PCIE_MMCFG_BUS_MASK) +#define PCIE_MMCFG_DEVFN(addr)          (((addr) >> PCIE_MMCFG_DEVFN_BIT) & \ +                                         PCIE_MMCFG_DEVFN_MASK) +#define PCIE_MMCFG_CONFOFFSET(addr)     ((addr) & PCIE_MMCFG_CONFOFFSET_MASK) + +#endif /* PCIE_HOST_H */ diff --git a/include/hw/pci/pcie_port.h b/include/hw/pci/pcie_port.h new file mode 100644 index 00000000..e167bf75 --- /dev/null +++ b/include/hw/pci/pcie_port.h @@ -0,0 +1,61 @@ +/* + * pcie_port.h + * + * Copyright (c) 2010 Isaku Yamahata <yamahata at valinux co jp> + *                    VA Linux Systems Japan K.K. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef QEMU_PCIE_PORT_H +#define QEMU_PCIE_PORT_H + +#include "hw/pci/pci_bridge.h" +#include "hw/pci/pci_bus.h" + +#define TYPE_PCIE_PORT "pcie-port" +#define PCIE_PORT(obj) OBJECT_CHECK(PCIEPort, (obj), TYPE_PCIE_PORT) + +struct PCIEPort { +    /*< private >*/ +    PCIBridge   parent_obj; +    /*< public >*/ + +    /* pci express switch port */ +    uint8_t     port; +}; + +void pcie_port_init_reg(PCIDevice *d); + +#define TYPE_PCIE_SLOT "pcie-slot" +#define PCIE_SLOT(obj) OBJECT_CHECK(PCIESlot, (obj), TYPE_PCIE_SLOT) + +struct PCIESlot { +    /*< private >*/ +    PCIEPort    parent_obj; +    /*< public >*/ + +    /* pci express switch port with slot */ +    uint8_t     chassis; +    uint16_t    slot; +    QLIST_ENTRY(PCIESlot) next; +}; + +void pcie_chassis_create(uint8_t chassis_number); +void pcie_main_chassis_create(void); +PCIESlot *pcie_chassis_find_slot(uint8_t chassis, uint16_t slot); +int pcie_chassis_add_slot(struct PCIESlot *slot); +void pcie_chassis_del_slot(PCIESlot *s); + +#endif /* QEMU_PCIE_PORT_H */ diff --git a/include/hw/pci/pcie_regs.h b/include/hw/pci/pcie_regs.h new file mode 100644 index 00000000..6a28b33e --- /dev/null +++ b/include/hw/pci/pcie_regs.h @@ -0,0 +1,158 @@ +/* + * constants for pcie configurations space from pci express spec. + * + * TODO: + * Those constants and macros should go to Linux pci_regs.h + * Once they're merged, they will go away. + */ +#ifndef QEMU_PCIE_REGS_H +#define QEMU_PCIE_REGS_H + + +/* express capability */ + +#define PCI_EXP_VER2_SIZEOF             0x3c /* express capability of ver. 2 */ +#define PCI_EXT_CAP_VER_SHIFT           16 +#define PCI_EXT_CAP_NEXT_SHIFT          20 +#define PCI_EXT_CAP_NEXT_MASK           (0xffc << PCI_EXT_CAP_NEXT_SHIFT) + +#define PCI_EXT_CAP(id, ver, next)                                      \ +    ((id) |                                                             \ +     ((ver) << PCI_EXT_CAP_VER_SHIFT) |                                 \ +     ((next) << PCI_EXT_CAP_NEXT_SHIFT)) + +#define PCI_EXT_CAP_ALIGN               4 +#define PCI_EXT_CAP_ALIGNUP(x)                                  \ +    (((x) + PCI_EXT_CAP_ALIGN - 1) & ~(PCI_EXT_CAP_ALIGN - 1)) + +/* PCI_EXP_FLAGS */ +#define PCI_EXP_FLAGS_VER2              2 /* for now, supports only ver. 2 */ +#define PCI_EXP_FLAGS_IRQ_SHIFT         ctz32(PCI_EXP_FLAGS_IRQ) +#define PCI_EXP_FLAGS_TYPE_SHIFT        ctz32(PCI_EXP_FLAGS_TYPE) + + +/* PCI_EXP_LINK{CAP, STA} */ +/* link speed */ +#define PCI_EXP_LNK_LS_25               1 + +#define PCI_EXP_LNK_MLW_SHIFT           ctz32(PCI_EXP_LNKCAP_MLW) +#define PCI_EXP_LNK_MLW_1               (1 << PCI_EXP_LNK_MLW_SHIFT) + +/* PCI_EXP_LINKCAP */ +#define PCI_EXP_LNKCAP_ASPMS_SHIFT      ctz32(PCI_EXP_LNKCAP_ASPMS) +#define PCI_EXP_LNKCAP_ASPMS_0S         (1 << PCI_EXP_LNKCAP_ASPMS_SHIFT) + +#define PCI_EXP_LNKCAP_PN_SHIFT         ctz32(PCI_EXP_LNKCAP_PN) + +#define PCI_EXP_SLTCAP_PSN_SHIFT        ctz32(PCI_EXP_SLTCAP_PSN) + +#define PCI_EXP_SLTCTL_IND_RESERVED     0x0 +#define PCI_EXP_SLTCTL_IND_ON           0x1 +#define PCI_EXP_SLTCTL_IND_BLINK        0x2 +#define PCI_EXP_SLTCTL_IND_OFF          0x3 +#define PCI_EXP_SLTCTL_AIC_SHIFT        ctz32(PCI_EXP_SLTCTL_AIC) +#define PCI_EXP_SLTCTL_AIC_OFF                          \ +    (PCI_EXP_SLTCTL_IND_OFF << PCI_EXP_SLTCTL_AIC_SHIFT) + +#define PCI_EXP_SLTCTL_PIC_SHIFT        ctz32(PCI_EXP_SLTCTL_PIC) +#define PCI_EXP_SLTCTL_PIC_OFF                          \ +    (PCI_EXP_SLTCTL_IND_OFF << PCI_EXP_SLTCTL_PIC_SHIFT) +#define PCI_EXP_SLTCTL_PIC_ON                          \ +    (PCI_EXP_SLTCTL_IND_ON << PCI_EXP_SLTCTL_PIC_SHIFT) + +#define PCI_EXP_SLTCTL_SUPPORTED        \ +            (PCI_EXP_SLTCTL_ABPE |      \ +             PCI_EXP_SLTCTL_PDCE |      \ +             PCI_EXP_SLTCTL_CCIE |      \ +             PCI_EXP_SLTCTL_HPIE |      \ +             PCI_EXP_SLTCTL_AIC |       \ +             PCI_EXP_SLTCTL_PCC |       \ +             PCI_EXP_SLTCTL_EIC) + +#define PCI_EXP_DEVCAP2_EFF             0x100000 +#define PCI_EXP_DEVCAP2_EETLPP          0x200000 + +#define PCI_EXP_DEVCTL2_EETLPPB         0x8000 + +/* ARI */ +#define PCI_ARI_VER                     1 +#define PCI_ARI_SIZEOF                  8 + +/* AER */ +#define PCI_ERR_VER                     2 +#define PCI_ERR_SIZEOF                  0x48 + +#define PCI_ERR_UNC_SDN                 0x00000020      /* surprise down */ +#define PCI_ERR_UNC_ACSV                0x00200000      /* ACS Violation */ +#define PCI_ERR_UNC_INTN                0x00400000      /* Internal Error */ +#define PCI_ERR_UNC_MCBTLP              0x00800000      /* MC Blcoked TLP */ +#define PCI_ERR_UNC_ATOP_EBLOCKED       0x01000000      /* atomic op egress blocked */ +#define PCI_ERR_UNC_TLP_PRF_BLOCKED     0x02000000      /* TLP Prefix Blocked */ +#define PCI_ERR_COR_ADV_NONFATAL        0x00002000      /* Advisory Non-Fatal */ +#define PCI_ERR_COR_INTERNAL            0x00004000      /* Corrected Internal */ +#define PCI_ERR_COR_HL_OVERFLOW         0x00008000      /* Header Long Overflow */ +#define PCI_ERR_CAP_FEP_MASK            0x0000001f +#define PCI_ERR_CAP_MHRC                0x00000200 +#define PCI_ERR_CAP_MHRE                0x00000400 +#define PCI_ERR_CAP_TLP                 0x00000800 + +#define PCI_ERR_HEADER_LOG_SIZE         16 +#define PCI_ERR_TLP_PREFIX_LOG          0x38 +#define PCI_ERR_TLP_PREFIX_LOG_SIZE     16 + +#define PCI_SEC_STATUS_RCV_SYSTEM_ERROR         0x4000 + +/* aer root error command/status */ +#define PCI_ERR_ROOT_CMD_EN_MASK        (PCI_ERR_ROOT_CMD_COR_EN |      \ +                                         PCI_ERR_ROOT_CMD_NONFATAL_EN | \ +                                         PCI_ERR_ROOT_CMD_FATAL_EN) + +#define PCI_ERR_ROOT_IRQ_MAX            32 +#define PCI_ERR_ROOT_IRQ                0xf8000000 +#define PCI_ERR_ROOT_IRQ_SHIFT          ctz32(PCI_ERR_ROOT_IRQ) +#define PCI_ERR_ROOT_STATUS_REPORT_MASK (PCI_ERR_ROOT_COR_RCV |         \ +                                         PCI_ERR_ROOT_MULTI_COR_RCV |   \ +                                         PCI_ERR_ROOT_UNCOR_RCV |       \ +                                         PCI_ERR_ROOT_MULTI_UNCOR_RCV | \ +                                         PCI_ERR_ROOT_FIRST_FATAL |     \ +                                         PCI_ERR_ROOT_NONFATAL_RCV |    \ +                                         PCI_ERR_ROOT_FATAL_RCV) + +#define PCI_ERR_UNC_SUPPORTED           (PCI_ERR_UNC_DLP |              \ +                                         PCI_ERR_UNC_SDN |              \ +                                         PCI_ERR_UNC_POISON_TLP |       \ +                                         PCI_ERR_UNC_FCP |              \ +                                         PCI_ERR_UNC_COMP_TIME |        \ +                                         PCI_ERR_UNC_COMP_ABORT |       \ +                                         PCI_ERR_UNC_UNX_COMP |         \ +                                         PCI_ERR_UNC_RX_OVER |          \ +                                         PCI_ERR_UNC_MALF_TLP |         \ +                                         PCI_ERR_UNC_ECRC |             \ +                                         PCI_ERR_UNC_UNSUP |            \ +                                         PCI_ERR_UNC_ACSV |             \ +                                         PCI_ERR_UNC_INTN |             \ +                                         PCI_ERR_UNC_MCBTLP |           \ +                                         PCI_ERR_UNC_ATOP_EBLOCKED |    \ +                                         PCI_ERR_UNC_TLP_PRF_BLOCKED) + +#define PCI_ERR_UNC_SEVERITY_DEFAULT    (PCI_ERR_UNC_DLP |              \ +                                         PCI_ERR_UNC_SDN |              \ +                                         PCI_ERR_UNC_FCP |              \ +                                         PCI_ERR_UNC_RX_OVER |          \ +                                         PCI_ERR_UNC_MALF_TLP |         \ +                                         PCI_ERR_UNC_INTN) + +#define PCI_ERR_COR_SUPPORTED           (PCI_ERR_COR_RCVR |             \ +                                         PCI_ERR_COR_BAD_TLP |          \ +                                         PCI_ERR_COR_BAD_DLLP |         \ +                                         PCI_ERR_COR_REP_ROLL |         \ +                                         PCI_ERR_COR_REP_TIMER |        \ +                                         PCI_ERR_COR_ADV_NONFATAL |     \ +                                         PCI_ERR_COR_INTERNAL |         \ +                                         PCI_ERR_COR_HL_OVERFLOW) + +#define PCI_ERR_COR_MASK_DEFAULT        (PCI_ERR_COR_ADV_NONFATAL |     \ +                                         PCI_ERR_COR_INTERNAL |         \ +                                         PCI_ERR_COR_HL_OVERFLOW) + +#endif /* QEMU_PCIE_REGS_H */ diff --git a/include/hw/pci/shpc.h b/include/hw/pci/shpc.h new file mode 100644 index 00000000..2c871b94 --- /dev/null +++ b/include/hw/pci/shpc.h @@ -0,0 +1,64 @@ +#ifndef SHPC_H +#define SHPC_H + +#include "qemu-common.h" +#include "exec/memory.h" +#include "migration/vmstate.h" +#include "qapi/error.h" +#include "hw/hotplug.h" +#include "hw/pci/pci.h" + +struct SHPCDevice { +    /* Capability offset in device's config space */ +    int cap; + +    /* # of hot-pluggable slots */ +    int nslots; + +    /* SHPC WRS: working register set */ +    uint8_t *config; + +    /* Used to enable checks on load. Note that writable bits are +     * never checked even if set in cmask. */ +    uint8_t *cmask; + +    /* Used to implement R/W bytes */ +    uint8_t *wmask; + +    /* Used to implement RW1C(Write 1 to Clear) bytes */ +    uint8_t *w1cmask; + +    /* MMIO for the SHPC BAR */ +    MemoryRegion mmio; + +    /* Bus controlled by this SHPC */ +    PCIBus *sec_bus; + +    /* MSI already requested for this event */ +    int msi_requested; +}; + +void shpc_reset(PCIDevice *d); +int shpc_bar_size(PCIDevice *dev); +int shpc_init(PCIDevice *dev, PCIBus *sec_bus, MemoryRegion *bar, unsigned off); +void shpc_cleanup(PCIDevice *dev, MemoryRegion *bar); +void shpc_free(PCIDevice *dev); +void shpc_cap_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int len); + + +void shpc_device_hotplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, +                            Error **errp); +void shpc_device_hot_unplug_request_cb(HotplugHandler *hotplug_dev, +                                       DeviceState *dev, Error **errp); + +extern VMStateInfo shpc_vmstate_info; +#define SHPC_VMSTATE(_field, _type,  _test) \ +    VMSTATE_BUFFER_UNSAFE_INFO_TEST(_field, _type, _test, 0, \ +                                    shpc_vmstate_info, 0) + +static inline bool shpc_present(const PCIDevice *dev) +{ +    return dev->cap_present & QEMU_PCI_CAP_SHPC; +} + +#endif diff --git a/include/hw/pci/slotid_cap.h b/include/hw/pci/slotid_cap.h new file mode 100644 index 00000000..70db0470 --- /dev/null +++ b/include/hw/pci/slotid_cap.h @@ -0,0 +1,11 @@ +#ifndef PCI_SLOTID_CAP_H +#define PCI_SLOTID_CAP_H + +#include "qemu-common.h" + +int slotid_cap_init(PCIDevice *dev, int nslots, +                    uint8_t chassis, +                    unsigned offset); +void slotid_cap_cleanup(PCIDevice *dev); + +#endif diff --git a/include/hw/pcmcia.h b/include/hw/pcmcia.h new file mode 100644 index 00000000..98406ffb --- /dev/null +++ b/include/hw/pcmcia.h @@ -0,0 +1,70 @@ +#ifndef HW_PCMCIA_H +#define HW_PCMCIA_H 1 + +/* PCMCIA/Cardbus */ + +#include "hw/qdev.h" + +typedef struct PCMCIASocket { +    qemu_irq irq; +    bool attached; +} PCMCIASocket; + +#define TYPE_PCMCIA_CARD "pcmcia-card" +#define PCMCIA_CARD(obj) \ +    OBJECT_CHECK(PCMCIACardState, (obj), TYPE_PCMCIA_CARD) +#define PCMCIA_CARD_GET_CLASS(obj) \ +    OBJECT_GET_CLASS(PCMCIACardClass, obj, TYPE_PCMCIA_CARD) +#define PCMCIA_CARD_CLASS(cls) \ +    OBJECT_CLASS_CHECK(PCMCIACardClass, cls, TYPE_PCMCIA_CARD) + +struct PCMCIACardState { +    /*< private >*/ +    DeviceState parent_obj; +    /*< public >*/ + +    PCMCIASocket *slot; +}; + +typedef struct PCMCIACardClass { +    /*< private >*/ +    DeviceClass parent_class; +    /*< public >*/ + +    int (*attach)(PCMCIACardState *state); +    int (*detach)(PCMCIACardState *state); + +    const uint8_t *cis; +    int cis_len; + +    /* Only valid if attached */ +    uint8_t (*attr_read)(PCMCIACardState *card, uint32_t address); +    void (*attr_write)(PCMCIACardState *card, uint32_t address, uint8_t value); +    uint16_t (*common_read)(PCMCIACardState *card, uint32_t address); +    void (*common_write)(PCMCIACardState *card, +                         uint32_t address, uint16_t value); +    uint16_t (*io_read)(PCMCIACardState *card, uint32_t address); +    void (*io_write)(PCMCIACardState *card, uint32_t address, uint16_t value); +} PCMCIACardClass; + +#define CISTPL_DEVICE		0x01	/* 5V Device Information Tuple */ +#define CISTPL_NO_LINK		0x14	/* No Link Tuple */ +#define CISTPL_VERS_1		0x15	/* Level 1 Version Tuple */ +#define CISTPL_JEDEC_C		0x18	/* JEDEC ID Tuple */ +#define CISTPL_JEDEC_A		0x19	/* JEDEC ID Tuple */ +#define CISTPL_CONFIG		0x1a	/* Configuration Tuple */ +#define CISTPL_CFTABLE_ENTRY	0x1b	/* 16-bit PCCard Configuration */ +#define CISTPL_DEVICE_OC	0x1c	/* Additional Device Information */ +#define CISTPL_DEVICE_OA	0x1d	/* Additional Device Information */ +#define CISTPL_DEVICE_GEO	0x1e	/* Additional Device Information */ +#define CISTPL_DEVICE_GEO_A	0x1f	/* Additional Device Information */ +#define CISTPL_MANFID		0x20	/* Manufacture ID Tuple */ +#define CISTPL_FUNCID		0x21	/* Function ID Tuple */ +#define CISTPL_FUNCE		0x22	/* Function Extension Tuple */ +#define CISTPL_END		0xff	/* Tuple End */ +#define CISTPL_ENDMARK		0xff + +/* dscm1xxxx.c */ +PCMCIACardState *dscm1xxxx_init(DriveInfo *bdrv); + +#endif diff --git a/include/hw/platform-bus.h b/include/hw/platform-bus.h new file mode 100644 index 00000000..bd42b838 --- /dev/null +++ b/include/hw/platform-bus.h @@ -0,0 +1,57 @@ +#ifndef HW_PLATFORM_BUS_H +#define HW_PLATFORM_BUS_H 1 + +/* + *  Platform Bus device to support dynamic Sysbus devices + * + * Copyright (C) 2014 Freescale Semiconductor, Inc. All rights reserved. + * + * Author: Alexander Graf, <agraf@suse.de> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ + +#include "hw/sysbus.h" + +typedef struct PlatformBusDevice PlatformBusDevice; + +#define TYPE_PLATFORM_BUS_DEVICE "platform-bus-device" +#define PLATFORM_BUS_DEVICE(obj) \ +     OBJECT_CHECK(PlatformBusDevice, (obj), TYPE_PLATFORM_BUS_DEVICE) +#define PLATFORM_BUS_DEVICE_CLASS(klass) \ +     OBJECT_CLASS_CHECK(PlatformBusDeviceClass, (klass), TYPE_PLATFORM_BUS_DEVICE) +#define PLATFORM_BUS_DEVICE_GET_CLASS(obj) \ +     OBJECT_GET_CLASS(PlatformBusDeviceClass, (obj), TYPE_PLATFORM_BUS_DEVICE) + +struct PlatformBusDevice { +    /*< private >*/ +    SysBusDevice parent_obj; +    Notifier notifier; +    bool done_gathering; + +    /*< public >*/ +    uint32_t mmio_size; +    MemoryRegion mmio; + +    uint32_t num_irqs; +    qemu_irq *irqs; +    unsigned long *used_irqs; +}; + +int platform_bus_get_irqn(PlatformBusDevice *platform_bus, SysBusDevice *sbdev, +                          int n); +hwaddr platform_bus_get_mmio_addr(PlatformBusDevice *pbus, SysBusDevice *sbdev, +                                  int n); + +#endif /* !HW_PLATFORM_BUS_H */ diff --git a/include/hw/ppc/mac_dbdma.h b/include/hw/ppc/mac_dbdma.h new file mode 100644 index 00000000..c6870212 --- /dev/null +++ b/include/hw/ppc/mac_dbdma.h @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2009 Laurent Vivier + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * 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 OTHER + * 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. + */ +#ifndef HW_MAC_DBDMA_H +#define HW_MAC_DBDMA_H 1 + +#include "exec/memory.h" + +typedef struct DBDMA_io DBDMA_io; + +typedef void (*DBDMA_flush)(DBDMA_io *io); +typedef void (*DBDMA_rw)(DBDMA_io *io); +typedef void (*DBDMA_end)(DBDMA_io *io); +struct DBDMA_io { +    void *opaque; +    void *channel; +    hwaddr addr; +    int len; +    int is_last; +    int is_dma_out; +    DBDMA_end dma_end; +    /* DMA is in progress, don't start another one */ +    bool processing; +    /* unaligned last sector of a request */ +    uint8_t head_remainder[0x200]; +    uint8_t tail_remainder[0x200]; +    QEMUIOVector iov; +}; + +/* + * DBDMA control/status registers.  All little-endian. + */ + +#define DBDMA_CONTROL         0x00 +#define DBDMA_STATUS          0x01 +#define DBDMA_CMDPTR_HI       0x02 +#define DBDMA_CMDPTR_LO       0x03 +#define DBDMA_INTR_SEL        0x04 +#define DBDMA_BRANCH_SEL      0x05 +#define DBDMA_WAIT_SEL        0x06 +#define DBDMA_XFER_MODE       0x07 +#define DBDMA_DATA2PTR_HI     0x08 +#define DBDMA_DATA2PTR_LO     0x09 +#define DBDMA_RES1            0x0A +#define DBDMA_ADDRESS_HI      0x0B +#define DBDMA_BRANCH_ADDR_HI  0x0C +#define DBDMA_RES2            0x0D +#define DBDMA_RES3            0x0E +#define DBDMA_RES4            0x0F + +#define DBDMA_REGS            16 +#define DBDMA_SIZE            (DBDMA_REGS * sizeof(uint32_t)) + +#define DBDMA_CHANNEL_SHIFT   7 +#define DBDMA_CHANNEL_SIZE    (1 << DBDMA_CHANNEL_SHIFT) + +#define DBDMA_CHANNELS        (0x1000 >> DBDMA_CHANNEL_SHIFT) + +/* Bits in control and status registers */ + +#define RUN        0x8000 +#define PAUSE      0x4000 +#define FLUSH      0x2000 +#define WAKE       0x1000 +#define DEAD       0x0800 +#define ACTIVE     0x0400 +#define BT         0x0100 +#define DEVSTAT    0x00ff + +/* + * DBDMA command structure.  These fields are all little-endian! + */ + +typedef struct dbdma_cmd { +    uint16_t req_count;          /* requested byte transfer count */ +    uint16_t command;            /* command word (has bit-fields) */ +    uint32_t phy_addr;           /* physical data address */ +    uint32_t cmd_dep;            /* command-dependent field */ +    uint16_t res_count;          /* residual count after completion */ +    uint16_t xfer_status;        /* transfer status */ +} dbdma_cmd; + +/* DBDMA command values in command field */ + +#define COMMAND_MASK    0xf000 +#define OUTPUT_MORE     0x0000        /* transfer memory data to stream */ +#define OUTPUT_LAST     0x1000        /* ditto followed by end marker */ +#define INPUT_MORE      0x2000        /* transfer stream data to memory */ +#define INPUT_LAST      0x3000        /* ditto, expect end marker */ +#define STORE_WORD      0x4000        /* write word (4 bytes) to device reg */ +#define LOAD_WORD       0x5000        /* read word (4 bytes) from device reg */ +#define DBDMA_NOP       0x6000        /* do nothing */ +#define DBDMA_STOP      0x7000        /* suspend processing */ + +/* Key values in command field */ + +#define KEY_MASK        0x0700 +#define KEY_STREAM0     0x0000        /* usual data stream */ +#define KEY_STREAM1     0x0100        /* control/status stream */ +#define KEY_STREAM2     0x0200        /* device-dependent stream */ +#define KEY_STREAM3     0x0300        /* device-dependent stream */ +#define KEY_STREAM4     0x0400        /* reserved */ +#define KEY_REGS        0x0500        /* device register space */ +#define KEY_SYSTEM      0x0600        /* system memory-mapped space */ +#define KEY_DEVICE      0x0700        /* device memory-mapped space */ + +/* Interrupt control values in command field */ + +#define INTR_MASK       0x0030 +#define INTR_NEVER      0x0000        /* don't interrupt */ +#define INTR_IFSET      0x0010        /* intr if condition bit is 1 */ +#define INTR_IFCLR      0x0020        /* intr if condition bit is 0 */ +#define INTR_ALWAYS     0x0030        /* always interrupt */ + +/* Branch control values in command field */ + +#define BR_MASK         0x000c +#define BR_NEVER        0x0000        /* don't branch */ +#define BR_IFSET        0x0004        /* branch if condition bit is 1 */ +#define BR_IFCLR        0x0008        /* branch if condition bit is 0 */ +#define BR_ALWAYS       0x000c        /* always branch */ + +/* Wait control values in command field */ + +#define WAIT_MASK       0x0003 +#define WAIT_NEVER      0x0000        /* don't wait */ +#define WAIT_IFSET      0x0001        /* wait if condition bit is 1 */ +#define WAIT_IFCLR      0x0002        /* wait if condition bit is 0 */ +#define WAIT_ALWAYS     0x0003        /* always wait */ + +typedef struct DBDMA_channel { +    int channel; +    uint32_t regs[DBDMA_REGS]; +    qemu_irq irq; +    DBDMA_io io; +    DBDMA_rw rw; +    DBDMA_flush flush; +    dbdma_cmd current; +} DBDMA_channel; + +typedef struct { +    MemoryRegion mem; +    DBDMA_channel channels[DBDMA_CHANNELS]; +    QEMUBH *bh; +} DBDMAState; + +/* Externally callable functions */ + +void DBDMA_register_channel(void *dbdma, int nchan, qemu_irq irq, +                            DBDMA_rw rw, DBDMA_flush flush, +                            void *opaque); +void DBDMA_kick(DBDMAState *dbdma); +void* DBDMA_init (MemoryRegion **dbdma_mem); + +#endif diff --git a/include/hw/ppc/openpic.h b/include/hw/ppc/openpic.h new file mode 100644 index 00000000..ee67098c --- /dev/null +++ b/include/hw/ppc/openpic.h @@ -0,0 +1,32 @@ +#if !defined(__OPENPIC_H__) +#define __OPENPIC_H__ + +#include "qemu-common.h" +#include "hw/qdev.h" + +#define TYPE_OPENPIC "openpic" + +/* OpenPIC have 5 outputs per CPU connected and one IRQ out single output */ +enum { +    OPENPIC_OUTPUT_INT = 0, /* IRQ                       */ +    OPENPIC_OUTPUT_CINT,    /* critical IRQ              */ +    OPENPIC_OUTPUT_MCK,     /* Machine check event       */ +    OPENPIC_OUTPUT_DEBUG,   /* Inconditional debug event */ +    OPENPIC_OUTPUT_RESET,   /* Core reset event          */ +    OPENPIC_OUTPUT_NB, +}; + +#define OPENPIC_MODEL_RAVEN       0 +#define OPENPIC_MODEL_FSL_MPIC_20 1 +#define OPENPIC_MODEL_FSL_MPIC_42 2 + +#define OPENPIC_MAX_SRC     256 +#define OPENPIC_MAX_TMR     4 +#define OPENPIC_MAX_IPI     4 +#define OPENPIC_MAX_IRQ     (OPENPIC_MAX_SRC + OPENPIC_MAX_IPI + \ +                             OPENPIC_MAX_TMR) + +#define TYPE_KVM_OPENPIC "kvm-openpic" +int kvm_openpic_connect_vcpu(DeviceState *d, CPUState *cs); + +#endif /* __OPENPIC_H__ */ diff --git a/include/hw/ppc/ppc.h b/include/hw/ppc/ppc.h new file mode 100644 index 00000000..14efd0ca --- /dev/null +++ b/include/hw/ppc/ppc.h @@ -0,0 +1,103 @@ +#ifndef HW_PPC_H +#define HW_PPC_H 1 + +void ppc_set_irq(PowerPCCPU *cpu, int n_IRQ, int level); + +/* PowerPC hardware exceptions management helpers */ +typedef void (*clk_setup_cb)(void *opaque, uint32_t freq); +typedef struct clk_setup_t clk_setup_t; +struct clk_setup_t { +    clk_setup_cb cb; +    void *opaque; +}; +static inline void clk_setup (clk_setup_t *clk, uint32_t freq) +{ +    if (clk->cb != NULL) +        (*clk->cb)(clk->opaque, freq); +} + +struct ppc_tb_t { +    /* Time base management */ +    int64_t  tb_offset;    /* Compensation                    */ +    int64_t  atb_offset;   /* Compensation                    */ +    uint32_t tb_freq;      /* TB frequency                    */ +    /* Decrementer management */ +    uint64_t decr_next;    /* Tick for next decr interrupt    */ +    uint32_t decr_freq;    /* decrementer frequency           */ +    QEMUTimer *decr_timer; +    /* Hypervisor decrementer management */ +    uint64_t hdecr_next;    /* Tick for next hdecr interrupt  */ +    QEMUTimer *hdecr_timer; +    uint64_t purr_load; +    uint64_t purr_start; +    void *opaque; +    uint32_t flags; +}; + +/* PPC Timers flags */ +#define PPC_TIMER_BOOKE              (1 << 0) /* Enable Booke support */ +#define PPC_TIMER_E500               (1 << 1) /* Enable e500 support */ +#define PPC_DECR_UNDERFLOW_TRIGGERED (1 << 2) /* Decr interrupt triggered when +                                               * the most significant bit +                                               * changes from 0 to 1. +                                               */ +#define PPC_DECR_ZERO_TRIGGERED      (1 << 3) /* Decr interrupt triggered when +                                               * the decrementer reaches zero. +                                               */ +#define PPC_DECR_UNDERFLOW_LEVEL     (1 << 4) /* Decr interrupt active when +                                               * the most significant bit is 1. +                                               */ + +uint64_t cpu_ppc_get_tb(ppc_tb_t *tb_env, uint64_t vmclk, int64_t tb_offset); +clk_setup_cb cpu_ppc_tb_init (CPUPPCState *env, uint32_t freq); +/* Embedded PowerPC DCR management */ +typedef uint32_t (*dcr_read_cb)(void *opaque, int dcrn); +typedef void (*dcr_write_cb)(void *opaque, int dcrn, uint32_t val); +int ppc_dcr_init (CPUPPCState *env, int (*dcr_read_error)(int dcrn), +                  int (*dcr_write_error)(int dcrn)); +int ppc_dcr_register (CPUPPCState *env, int dcrn, void *opaque, +                      dcr_read_cb drc_read, dcr_write_cb dcr_write); +clk_setup_cb ppc_40x_timers_init (CPUPPCState *env, uint32_t freq, +                                  unsigned int decr_excp); + +/* Embedded PowerPC reset */ +void ppc40x_core_reset(PowerPCCPU *cpu); +void ppc40x_chip_reset(PowerPCCPU *cpu); +void ppc40x_system_reset(PowerPCCPU *cpu); +void PREP_debug_write (void *opaque, uint32_t addr, uint32_t val); + +extern CPUWriteMemoryFunc * const PPC_io_write[]; +extern CPUReadMemoryFunc * const PPC_io_read[]; +void PPC_debug_write (void *opaque, uint32_t addr, uint32_t val); + +void ppc40x_irq_init (CPUPPCState *env); +void ppce500_irq_init (CPUPPCState *env); +void ppc6xx_irq_init (CPUPPCState *env); +void ppc970_irq_init (CPUPPCState *env); +void ppcPOWER7_irq_init (CPUPPCState *env); + +/* PPC machines for OpenBIOS */ +enum { +    ARCH_PREP = 0, +    ARCH_MAC99, +    ARCH_HEATHROW, +    ARCH_MAC99_U3, +}; + +#define FW_CFG_PPC_WIDTH	(FW_CFG_ARCH_LOCAL + 0x00) +#define FW_CFG_PPC_HEIGHT	(FW_CFG_ARCH_LOCAL + 0x01) +#define FW_CFG_PPC_DEPTH	(FW_CFG_ARCH_LOCAL + 0x02) +#define FW_CFG_PPC_TBFREQ	(FW_CFG_ARCH_LOCAL + 0x03) +#define FW_CFG_PPC_CLOCKFREQ	(FW_CFG_ARCH_LOCAL + 0x04) +#define FW_CFG_PPC_IS_KVM       (FW_CFG_ARCH_LOCAL + 0x05) +#define FW_CFG_PPC_KVM_HC       (FW_CFG_ARCH_LOCAL + 0x06) +#define FW_CFG_PPC_KVM_PID      (FW_CFG_ARCH_LOCAL + 0x07) +#define FW_CFG_PPC_NVRAM_ADDR   (FW_CFG_ARCH_LOCAL + 0x08) +#define FW_CFG_PPC_BUSFREQ      (FW_CFG_ARCH_LOCAL + 0x09) + +#define PPC_SERIAL_MM_BAUDBASE 399193 + +/* ppc_booke.c */ +void ppc_booke_timers_init(PowerPCCPU *cpu, uint32_t freq, uint32_t flags); + +#endif diff --git a/include/hw/ppc/ppc4xx.h b/include/hw/ppc/ppc4xx.h new file mode 100644 index 00000000..91d84bad --- /dev/null +++ b/include/hw/ppc/ppc4xx.h @@ -0,0 +1,64 @@ +/* + * QEMU PowerPC 4xx emulation shared definitions + * + * Copyright (c) 2007 Jocelyn Mayer + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * 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 OTHER + * 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. + */ + +#if !defined(PPC_4XX_H) +#define PPC_4XX_H + +#include "hw/pci/pci.h" + +/* PowerPC 4xx core initialization */ +PowerPCCPU *ppc4xx_init(const char *cpu_model, +                        clk_setup_t *cpu_clk, clk_setup_t *tb_clk, +                        uint32_t sysclk); + +/* PowerPC 4xx universal interrupt controller */ +enum { +    PPCUIC_OUTPUT_INT = 0, +    PPCUIC_OUTPUT_CINT = 1, +    PPCUIC_OUTPUT_NB, +}; +qemu_irq *ppcuic_init (CPUPPCState *env, qemu_irq *irqs, +                       uint32_t dcr_base, int has_ssr, int has_vr); + +ram_addr_t ppc4xx_sdram_adjust(ram_addr_t ram_size, int nr_banks, +                               MemoryRegion ram_memories[], +                               hwaddr ram_bases[], +                               hwaddr ram_sizes[], +                               const unsigned int sdram_bank_sizes[]); + +void ppc4xx_sdram_init (CPUPPCState *env, qemu_irq irq, int nbanks, +                        MemoryRegion ram_memories[], +                        hwaddr *ram_bases, +                        hwaddr *ram_sizes, +                        int do_init); + +#define TYPE_PPC4xx_PCI_HOST_BRIDGE "ppc4xx-pcihost" + +PCIBus *ppc4xx_pci_init(CPUPPCState *env, qemu_irq pci_irqs[4], +                        hwaddr config_space, +                        hwaddr int_ack, +                        hwaddr special_cycle, +                        hwaddr registers); + +#endif /* !defined(PPC_4XX_H) */ diff --git a/include/hw/ppc/ppc_e500.h b/include/hw/ppc/ppc_e500.h new file mode 100644 index 00000000..b66c0e3e --- /dev/null +++ b/include/hw/ppc/ppc_e500.h @@ -0,0 +1,6 @@ +#ifndef HW_PPC_E500_H +#define HW_PPC_E500_H + +void ppce500_set_mpic_proxy(bool enabled); + +#endif diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h new file mode 100644 index 00000000..91a61abb --- /dev/null +++ b/include/hw/ppc/spapr.h @@ -0,0 +1,612 @@ +#if !defined(__HW_SPAPR_H__) +#define __HW_SPAPR_H__ + +#include "sysemu/dma.h" +#include "hw/boards.h" +#include "hw/ppc/xics.h" +#include "hw/ppc/spapr_drc.h" + +struct VIOsPAPRBus; +struct sPAPRPHBState; +struct sPAPRNVRAM; +typedef struct sPAPRConfigureConnectorState sPAPRConfigureConnectorState; +typedef struct sPAPREventLogEntry sPAPREventLogEntry; + +#define HPTE64_V_HPTE_DIRTY     0x0000000000000040ULL +#define SPAPR_ENTRY_POINT       0x100 + +typedef struct sPAPRMachineClass sPAPRMachineClass; +typedef struct sPAPRMachineState sPAPRMachineState; + +#define TYPE_SPAPR_MACHINE      "spapr-machine" +#define SPAPR_MACHINE(obj) \ +    OBJECT_CHECK(sPAPRMachineState, (obj), TYPE_SPAPR_MACHINE) +#define SPAPR_MACHINE_GET_CLASS(obj) \ +    OBJECT_GET_CLASS(sPAPRMachineClass, obj, TYPE_SPAPR_MACHINE) +#define SPAPR_MACHINE_CLASS(klass) \ +    OBJECT_CLASS_CHECK(sPAPRMachineClass, klass, TYPE_SPAPR_MACHINE) + +/** + * sPAPRMachineClass: + */ +struct sPAPRMachineClass { +    /*< private >*/ +    MachineClass parent_class; + +    /*< public >*/ +}; + +/** + * sPAPRMachineState: + */ +struct sPAPRMachineState { +    /*< private >*/ +    MachineState parent_obj; + +    struct VIOsPAPRBus *vio_bus; +    QLIST_HEAD(, sPAPRPHBState) phbs; +    struct sPAPRNVRAM *nvram; +    XICSState *icp; +    DeviceState *rtc; + +    void *htab; +    uint32_t htab_shift; +    hwaddr rma_size; +    int vrma_adjust; +    hwaddr fdt_addr, rtas_addr; +    ssize_t rtas_size; +    void *rtas_blob; +    void *fdt_skel; +    uint64_t rtc_offset; /* Now used only during incoming migration */ +    struct PPCTimebase tb; +    bool has_graphics; + +    uint32_t check_exception_irq; +    Notifier epow_notifier; +    QTAILQ_HEAD(, sPAPREventLogEntry) pending_events; + +    /* Migration state */ +    int htab_save_index; +    bool htab_first_pass; +    int htab_fd; +    bool htab_fd_stale; + +    /* RTAS state */ +    QTAILQ_HEAD(, sPAPRConfigureConnectorState) ccs_list; + +    /*< public >*/ +    char *kvm_type; +}; + +#define H_SUCCESS         0 +#define H_BUSY            1        /* Hardware busy -- retry later */ +#define H_CLOSED          2        /* Resource closed */ +#define H_NOT_AVAILABLE   3 +#define H_CONSTRAINED     4        /* Resource request constrained to max allowed */ +#define H_PARTIAL         5 +#define H_IN_PROGRESS     14       /* Kind of like busy */ +#define H_PAGE_REGISTERED 15 +#define H_PARTIAL_STORE   16 +#define H_PENDING         17       /* returned from H_POLL_PENDING */ +#define H_CONTINUE        18       /* Returned from H_Join on success */ +#define H_LONG_BUSY_START_RANGE         9900  /* Start of long busy range */ +#define H_LONG_BUSY_ORDER_1_MSEC        9900  /* Long busy, hint that 1msec \ +                                                 is a good time to retry */ +#define H_LONG_BUSY_ORDER_10_MSEC       9901  /* Long busy, hint that 10msec \ +                                                 is a good time to retry */ +#define H_LONG_BUSY_ORDER_100_MSEC      9902  /* Long busy, hint that 100msec \ +                                                 is a good time to retry */ +#define H_LONG_BUSY_ORDER_1_SEC         9903  /* Long busy, hint that 1sec \ +                                                 is a good time to retry */ +#define H_LONG_BUSY_ORDER_10_SEC        9904  /* Long busy, hint that 10sec \ +                                                 is a good time to retry */ +#define H_LONG_BUSY_ORDER_100_SEC       9905  /* Long busy, hint that 100sec \ +                                                 is a good time to retry */ +#define H_LONG_BUSY_END_RANGE           9905  /* End of long busy range */ +#define H_HARDWARE        -1       /* Hardware error */ +#define H_FUNCTION        -2       /* Function not supported */ +#define H_PRIVILEGE       -3       /* Caller not privileged */ +#define H_PARAMETER       -4       /* Parameter invalid, out-of-range or conflicting */ +#define H_BAD_MODE        -5       /* Illegal msr value */ +#define H_PTEG_FULL       -6       /* PTEG is full */ +#define H_NOT_FOUND       -7       /* PTE was not found" */ +#define H_RESERVED_DABR   -8       /* DABR address is reserved by the hypervisor on this processor" */ +#define H_NO_MEM          -9 +#define H_AUTHORITY       -10 +#define H_PERMISSION      -11 +#define H_DROPPED         -12 +#define H_SOURCE_PARM     -13 +#define H_DEST_PARM       -14 +#define H_REMOTE_PARM     -15 +#define H_RESOURCE        -16 +#define H_ADAPTER_PARM    -17 +#define H_RH_PARM         -18 +#define H_RCQ_PARM        -19 +#define H_SCQ_PARM        -20 +#define H_EQ_PARM         -21 +#define H_RT_PARM         -22 +#define H_ST_PARM         -23 +#define H_SIGT_PARM       -24 +#define H_TOKEN_PARM      -25 +#define H_MLENGTH_PARM    -27 +#define H_MEM_PARM        -28 +#define H_MEM_ACCESS_PARM -29 +#define H_ATTR_PARM       -30 +#define H_PORT_PARM       -31 +#define H_MCG_PARM        -32 +#define H_VL_PARM         -33 +#define H_TSIZE_PARM      -34 +#define H_TRACE_PARM      -35 + +#define H_MASK_PARM       -37 +#define H_MCG_FULL        -38 +#define H_ALIAS_EXIST     -39 +#define H_P_COUNTER       -40 +#define H_TABLE_FULL      -41 +#define H_ALT_TABLE       -42 +#define H_MR_CONDITION    -43 +#define H_NOT_ENOUGH_RESOURCES -44 +#define H_R_STATE         -45 +#define H_RESCINDEND      -46 +#define H_P2              -55 +#define H_P3              -56 +#define H_P4              -57 +#define H_P5              -58 +#define H_P6              -59 +#define H_P7              -60 +#define H_P8              -61 +#define H_P9              -62 +#define H_UNSUPPORTED_FLAG -256 +#define H_MULTI_THREADS_ACTIVE -9005 + + +/* Long Busy is a condition that can be returned by the firmware + * when a call cannot be completed now, but the identical call + * should be retried later.  This prevents calls blocking in the + * firmware for long periods of time.  Annoyingly the firmware can return + * a range of return codes, hinting at how long we should wait before + * retrying.  If you don't care for the hint, the macro below is a good + * way to check for the long_busy return codes + */ +#define H_IS_LONG_BUSY(x)  ((x >= H_LONG_BUSY_START_RANGE) \ +                            && (x <= H_LONG_BUSY_END_RANGE)) + +/* Flags */ +#define H_LARGE_PAGE      (1ULL<<(63-16)) +#define H_EXACT           (1ULL<<(63-24))       /* Use exact PTE or return H_PTEG_FULL */ +#define H_R_XLATE         (1ULL<<(63-25))       /* include a valid logical page num in the pte if the valid bit is set */ +#define H_READ_4          (1ULL<<(63-26))       /* Return 4 PTEs */ +#define H_PAGE_STATE_CHANGE (1ULL<<(63-28)) +#define H_PAGE_UNUSED     ((1ULL<<(63-29)) | (1ULL<<(63-30))) +#define H_PAGE_SET_UNUSED (H_PAGE_STATE_CHANGE | H_PAGE_UNUSED) +#define H_PAGE_SET_LOANED (H_PAGE_SET_UNUSED | (1ULL<<(63-31))) +#define H_PAGE_SET_ACTIVE H_PAGE_STATE_CHANGE +#define H_AVPN            (1ULL<<(63-32))       /* An avpn is provided as a sanity test */ +#define H_ANDCOND         (1ULL<<(63-33)) +#define H_ICACHE_INVALIDATE (1ULL<<(63-40))     /* icbi, etc.  (ignored for IO pages) */ +#define H_ICACHE_SYNCHRONIZE (1ULL<<(63-41))    /* dcbst, icbi, etc (ignored for IO pages */ +#define H_ZERO_PAGE       (1ULL<<(63-48))       /* zero the page before mapping (ignored for IO pages) */ +#define H_COPY_PAGE       (1ULL<<(63-49)) +#define H_N               (1ULL<<(63-61)) +#define H_PP1             (1ULL<<(63-62)) +#define H_PP2             (1ULL<<(63-63)) + +/* Values for 2nd argument to H_SET_MODE */ +#define H_SET_MODE_RESOURCE_SET_CIABR           1 +#define H_SET_MODE_RESOURCE_SET_DAWR            2 +#define H_SET_MODE_RESOURCE_ADDR_TRANS_MODE     3 +#define H_SET_MODE_RESOURCE_LE                  4 + +/* Flags for H_SET_MODE_RESOURCE_LE */ +#define H_SET_MODE_ENDIAN_BIG    0 +#define H_SET_MODE_ENDIAN_LITTLE 1 + +/* Flags for H_SET_MODE_RESOURCE_ADDR_TRANS_MODE */ +#define H_SET_MODE_ADDR_TRANS_NONE                  0 +#define H_SET_MODE_ADDR_TRANS_0001_8000             2 +#define H_SET_MODE_ADDR_TRANS_C000_0000_0000_4000   3 + +/* VASI States */ +#define H_VASI_INVALID    0 +#define H_VASI_ENABLED    1 +#define H_VASI_ABORTED    2 +#define H_VASI_SUSPENDING 3 +#define H_VASI_SUSPENDED  4 +#define H_VASI_RESUMED    5 +#define H_VASI_COMPLETED  6 + +/* DABRX flags */ +#define H_DABRX_HYPERVISOR (1ULL<<(63-61)) +#define H_DABRX_KERNEL     (1ULL<<(63-62)) +#define H_DABRX_USER       (1ULL<<(63-63)) + +/* Each control block has to be on a 4K boundary */ +#define H_CB_ALIGNMENT     4096 + +/* pSeries hypervisor opcodes */ +#define H_REMOVE                0x04 +#define H_ENTER                 0x08 +#define H_READ                  0x0c +#define H_CLEAR_MOD             0x10 +#define H_CLEAR_REF             0x14 +#define H_PROTECT               0x18 +#define H_GET_TCE               0x1c +#define H_PUT_TCE               0x20 +#define H_SET_SPRG0             0x24 +#define H_SET_DABR              0x28 +#define H_PAGE_INIT             0x2c +#define H_SET_ASR               0x30 +#define H_ASR_ON                0x34 +#define H_ASR_OFF               0x38 +#define H_LOGICAL_CI_LOAD       0x3c +#define H_LOGICAL_CI_STORE      0x40 +#define H_LOGICAL_CACHE_LOAD    0x44 +#define H_LOGICAL_CACHE_STORE   0x48 +#define H_LOGICAL_ICBI          0x4c +#define H_LOGICAL_DCBF          0x50 +#define H_GET_TERM_CHAR         0x54 +#define H_PUT_TERM_CHAR         0x58 +#define H_REAL_TO_LOGICAL       0x5c +#define H_HYPERVISOR_DATA       0x60 +#define H_EOI                   0x64 +#define H_CPPR                  0x68 +#define H_IPI                   0x6c +#define H_IPOLL                 0x70 +#define H_XIRR                  0x74 +#define H_PERFMON               0x7c +#define H_MIGRATE_DMA           0x78 +#define H_REGISTER_VPA          0xDC +#define H_CEDE                  0xE0 +#define H_CONFER                0xE4 +#define H_PROD                  0xE8 +#define H_GET_PPP               0xEC +#define H_SET_PPP               0xF0 +#define H_PURR                  0xF4 +#define H_PIC                   0xF8 +#define H_REG_CRQ               0xFC +#define H_FREE_CRQ              0x100 +#define H_VIO_SIGNAL            0x104 +#define H_SEND_CRQ              0x108 +#define H_COPY_RDMA             0x110 +#define H_REGISTER_LOGICAL_LAN  0x114 +#define H_FREE_LOGICAL_LAN      0x118 +#define H_ADD_LOGICAL_LAN_BUFFER 0x11C +#define H_SEND_LOGICAL_LAN      0x120 +#define H_BULK_REMOVE           0x124 +#define H_MULTICAST_CTRL        0x130 +#define H_SET_XDABR             0x134 +#define H_STUFF_TCE             0x138 +#define H_PUT_TCE_INDIRECT      0x13C +#define H_CHANGE_LOGICAL_LAN_MAC 0x14C +#define H_VTERM_PARTNER_INFO    0x150 +#define H_REGISTER_VTERM        0x154 +#define H_FREE_VTERM            0x158 +#define H_RESET_EVENTS          0x15C +#define H_ALLOC_RESOURCE        0x160 +#define H_FREE_RESOURCE         0x164 +#define H_MODIFY_QP             0x168 +#define H_QUERY_QP              0x16C +#define H_REREGISTER_PMR        0x170 +#define H_REGISTER_SMR          0x174 +#define H_QUERY_MR              0x178 +#define H_QUERY_MW              0x17C +#define H_QUERY_HCA             0x180 +#define H_QUERY_PORT            0x184 +#define H_MODIFY_PORT           0x188 +#define H_DEFINE_AQP1           0x18C +#define H_GET_TRACE_BUFFER      0x190 +#define H_DEFINE_AQP0           0x194 +#define H_RESIZE_MR             0x198 +#define H_ATTACH_MCQP           0x19C +#define H_DETACH_MCQP           0x1A0 +#define H_CREATE_RPT            0x1A4 +#define H_REMOVE_RPT            0x1A8 +#define H_REGISTER_RPAGES       0x1AC +#define H_DISABLE_AND_GETC      0x1B0 +#define H_ERROR_DATA            0x1B4 +#define H_GET_HCA_INFO          0x1B8 +#define H_GET_PERF_COUNT        0x1BC +#define H_MANAGE_TRACE          0x1C0 +#define H_FREE_LOGICAL_LAN_BUFFER 0x1D4 +#define H_QUERY_INT_STATE       0x1E4 +#define H_POLL_PENDING          0x1D8 +#define H_ILLAN_ATTRIBUTES      0x244 +#define H_MODIFY_HEA_QP         0x250 +#define H_QUERY_HEA_QP          0x254 +#define H_QUERY_HEA             0x258 +#define H_QUERY_HEA_PORT        0x25C +#define H_MODIFY_HEA_PORT       0x260 +#define H_REG_BCMC              0x264 +#define H_DEREG_BCMC            0x268 +#define H_REGISTER_HEA_RPAGES   0x26C +#define H_DISABLE_AND_GET_HEA   0x270 +#define H_GET_HEA_INFO          0x274 +#define H_ALLOC_HEA_RESOURCE    0x278 +#define H_ADD_CONN              0x284 +#define H_DEL_CONN              0x288 +#define H_JOIN                  0x298 +#define H_VASI_STATE            0x2A4 +#define H_ENABLE_CRQ            0x2B0 +#define H_GET_EM_PARMS          0x2B8 +#define H_SET_MPP               0x2D0 +#define H_GET_MPP               0x2D4 +#define H_XIRR_X                0x2FC +#define H_SET_MODE              0x31C +#define MAX_HCALL_OPCODE        H_SET_MODE + +/* The hcalls above are standardized in PAPR and implemented by pHyp + * as well. + * + * We also need some hcalls which are specific to qemu / KVM-on-POWER. + * So far we just need one for H_RTAS, but in future we'll need more + * for extensions like virtio.  We put those into the 0xf000-0xfffc + * range which is reserved by PAPR for "platform-specific" hcalls. + */ +#define KVMPPC_HCALL_BASE       0xf000 +#define KVMPPC_H_RTAS           (KVMPPC_HCALL_BASE + 0x0) +#define KVMPPC_H_LOGICAL_MEMOP  (KVMPPC_HCALL_BASE + 0x1) +/* Client Architecture support */ +#define KVMPPC_H_CAS            (KVMPPC_HCALL_BASE + 0x2) +#define KVMPPC_HCALL_MAX        KVMPPC_H_CAS + +typedef struct sPAPRDeviceTreeUpdateHeader { +    uint32_t version_id; +} sPAPRDeviceTreeUpdateHeader; + +/*#define DEBUG_SPAPR_HCALLS*/ + +#ifdef DEBUG_SPAPR_HCALLS +#define hcall_dprintf(fmt, ...) \ +    do { fprintf(stderr, "%s: " fmt, __func__, ## __VA_ARGS__); } while (0) +#else +#define hcall_dprintf(fmt, ...) \ +    do { } while (0) +#endif + +typedef target_ulong (*spapr_hcall_fn)(PowerPCCPU *cpu, sPAPRMachineState *sm, +                                       target_ulong opcode, +                                       target_ulong *args); + +void spapr_register_hypercall(target_ulong opcode, spapr_hcall_fn fn); +target_ulong spapr_hypercall(PowerPCCPU *cpu, target_ulong opcode, +                             target_ulong *args); + +int spapr_allocate_irq(int hint, bool lsi); +int spapr_allocate_irq_block(int num, bool lsi, bool msi); + +/* ibm,set-eeh-option */ +#define RTAS_EEH_DISABLE                 0 +#define RTAS_EEH_ENABLE                  1 +#define RTAS_EEH_THAW_IO                 2 +#define RTAS_EEH_THAW_DMA                3 + +/* ibm,get-config-addr-info2 */ +#define RTAS_GET_PE_ADDR                 0 +#define RTAS_GET_PE_MODE                 1 +#define RTAS_PE_MODE_NONE                0 +#define RTAS_PE_MODE_NOT_SHARED          1 +#define RTAS_PE_MODE_SHARED              2 + +/* ibm,read-slot-reset-state2 */ +#define RTAS_EEH_PE_STATE_NORMAL         0 +#define RTAS_EEH_PE_STATE_RESET          1 +#define RTAS_EEH_PE_STATE_STOPPED_IO_DMA 2 +#define RTAS_EEH_PE_STATE_STOPPED_DMA    4 +#define RTAS_EEH_PE_STATE_UNAVAIL        5 +#define RTAS_EEH_NOT_SUPPORT             0 +#define RTAS_EEH_SUPPORT                 1 +#define RTAS_EEH_PE_UNAVAIL_INFO         1000 +#define RTAS_EEH_PE_RECOVER_INFO         0 + +/* ibm,set-slot-reset */ +#define RTAS_SLOT_RESET_DEACTIVATE       0 +#define RTAS_SLOT_RESET_HOT              1 +#define RTAS_SLOT_RESET_FUNDAMENTAL      3 + +/* ibm,slot-error-detail */ +#define RTAS_SLOT_TEMP_ERR_LOG           1 +#define RTAS_SLOT_PERM_ERR_LOG           2 + +/* RTAS return codes */ +#define RTAS_OUT_SUCCESS            0 +#define RTAS_OUT_NO_ERRORS_FOUND    1 +#define RTAS_OUT_HW_ERROR           -1 +#define RTAS_OUT_BUSY               -2 +#define RTAS_OUT_PARAM_ERROR        -3 +#define RTAS_OUT_NOT_SUPPORTED      -3 +#define RTAS_OUT_NOT_AUTHORIZED     -9002 + +/* RTAS tokens */ +#define RTAS_TOKEN_BASE      0x2000 + +#define RTAS_DISPLAY_CHARACTER                  (RTAS_TOKEN_BASE + 0x00) +#define RTAS_GET_TIME_OF_DAY                    (RTAS_TOKEN_BASE + 0x01) +#define RTAS_SET_TIME_OF_DAY                    (RTAS_TOKEN_BASE + 0x02) +#define RTAS_POWER_OFF                          (RTAS_TOKEN_BASE + 0x03) +#define RTAS_SYSTEM_REBOOT                      (RTAS_TOKEN_BASE + 0x04) +#define RTAS_QUERY_CPU_STOPPED_STATE            (RTAS_TOKEN_BASE + 0x05) +#define RTAS_START_CPU                          (RTAS_TOKEN_BASE + 0x06) +#define RTAS_STOP_SELF                          (RTAS_TOKEN_BASE + 0x07) +#define RTAS_IBM_GET_SYSTEM_PARAMETER           (RTAS_TOKEN_BASE + 0x08) +#define RTAS_IBM_SET_SYSTEM_PARAMETER           (RTAS_TOKEN_BASE + 0x09) +#define RTAS_IBM_SET_XIVE                       (RTAS_TOKEN_BASE + 0x0A) +#define RTAS_IBM_GET_XIVE                       (RTAS_TOKEN_BASE + 0x0B) +#define RTAS_IBM_INT_OFF                        (RTAS_TOKEN_BASE + 0x0C) +#define RTAS_IBM_INT_ON                         (RTAS_TOKEN_BASE + 0x0D) +#define RTAS_CHECK_EXCEPTION                    (RTAS_TOKEN_BASE + 0x0E) +#define RTAS_EVENT_SCAN                         (RTAS_TOKEN_BASE + 0x0F) +#define RTAS_IBM_SET_TCE_BYPASS                 (RTAS_TOKEN_BASE + 0x10) +#define RTAS_QUIESCE                            (RTAS_TOKEN_BASE + 0x11) +#define RTAS_NVRAM_FETCH                        (RTAS_TOKEN_BASE + 0x12) +#define RTAS_NVRAM_STORE                        (RTAS_TOKEN_BASE + 0x13) +#define RTAS_READ_PCI_CONFIG                    (RTAS_TOKEN_BASE + 0x14) +#define RTAS_WRITE_PCI_CONFIG                   (RTAS_TOKEN_BASE + 0x15) +#define RTAS_IBM_READ_PCI_CONFIG                (RTAS_TOKEN_BASE + 0x16) +#define RTAS_IBM_WRITE_PCI_CONFIG               (RTAS_TOKEN_BASE + 0x17) +#define RTAS_IBM_QUERY_INTERRUPT_SOURCE_NUMBER  (RTAS_TOKEN_BASE + 0x18) +#define RTAS_IBM_CHANGE_MSI                     (RTAS_TOKEN_BASE + 0x19) +#define RTAS_SET_INDICATOR                      (RTAS_TOKEN_BASE + 0x1A) +#define RTAS_SET_POWER_LEVEL                    (RTAS_TOKEN_BASE + 0x1B) +#define RTAS_GET_POWER_LEVEL                    (RTAS_TOKEN_BASE + 0x1C) +#define RTAS_GET_SENSOR_STATE                   (RTAS_TOKEN_BASE + 0x1D) +#define RTAS_IBM_CONFIGURE_CONNECTOR            (RTAS_TOKEN_BASE + 0x1E) +#define RTAS_IBM_OS_TERM                        (RTAS_TOKEN_BASE + 0x1F) +#define RTAS_IBM_SET_EEH_OPTION                 (RTAS_TOKEN_BASE + 0x20) +#define RTAS_IBM_GET_CONFIG_ADDR_INFO2          (RTAS_TOKEN_BASE + 0x21) +#define RTAS_IBM_READ_SLOT_RESET_STATE2         (RTAS_TOKEN_BASE + 0x22) +#define RTAS_IBM_SET_SLOT_RESET                 (RTAS_TOKEN_BASE + 0x23) +#define RTAS_IBM_CONFIGURE_PE                   (RTAS_TOKEN_BASE + 0x24) +#define RTAS_IBM_SLOT_ERROR_DETAIL              (RTAS_TOKEN_BASE + 0x25) + +#define RTAS_TOKEN_MAX                          (RTAS_TOKEN_BASE + 0x26) + +/* RTAS ibm,get-system-parameter token values */ +#define RTAS_SYSPARM_SPLPAR_CHARACTERISTICS      20 +#define RTAS_SYSPARM_DIAGNOSTICS_RUN_MODE        42 +#define RTAS_SYSPARM_UUID                        48 + +/* RTAS indicator/sensor types + * + * as defined by PAPR+ 2.7 7.3.5.4, Table 41 + * + * NOTE: currently only DR-related sensors are implemented here + */ +#define RTAS_SENSOR_TYPE_ISOLATION_STATE        9001 +#define RTAS_SENSOR_TYPE_DR                     9002 +#define RTAS_SENSOR_TYPE_ALLOCATION_STATE       9003 +#define RTAS_SENSOR_TYPE_ENTITY_SENSE RTAS_SENSOR_TYPE_ALLOCATION_STATE + +/* Possible values for the platform-processor-diagnostics-run-mode parameter + * of the RTAS ibm,get-system-parameter call. + */ +#define DIAGNOSTICS_RUN_MODE_DISABLED  0 +#define DIAGNOSTICS_RUN_MODE_STAGGERED 1 +#define DIAGNOSTICS_RUN_MODE_IMMEDIATE 2 +#define DIAGNOSTICS_RUN_MODE_PERIODIC  3 + +static inline uint64_t ppc64_phys_to_real(uint64_t addr) +{ +    return addr & ~0xF000000000000000ULL; +} + +static inline uint32_t rtas_ld(target_ulong phys, int n) +{ +    return ldl_be_phys(&address_space_memory, ppc64_phys_to_real(phys + 4*n)); +} + +static inline void rtas_st(target_ulong phys, int n, uint32_t val) +{ +    stl_be_phys(&address_space_memory, ppc64_phys_to_real(phys + 4*n), val); +} + +static inline void rtas_st_buffer_direct(target_ulong phys, +                                         target_ulong phys_len, +                                         uint8_t *buffer, uint16_t buffer_len) +{ +    cpu_physical_memory_write(ppc64_phys_to_real(phys), buffer, +                              MIN(buffer_len, phys_len)); +} + +static inline void rtas_st_buffer(target_ulong phys, target_ulong phys_len, +                                  uint8_t *buffer, uint16_t buffer_len) +{ +    if (phys_len < 2) { +        return; +    } +    stw_be_phys(&address_space_memory, +                ppc64_phys_to_real(phys), buffer_len); +    rtas_st_buffer_direct(phys + 2, phys_len - 2, buffer, buffer_len); +} + +typedef void (*spapr_rtas_fn)(PowerPCCPU *cpu, sPAPRMachineState *sm, +                              uint32_t token, +                              uint32_t nargs, target_ulong args, +                              uint32_t nret, target_ulong rets); +void spapr_rtas_register(int token, const char *name, spapr_rtas_fn fn); +target_ulong spapr_rtas_call(PowerPCCPU *cpu, sPAPRMachineState *sm, +                             uint32_t token, uint32_t nargs, target_ulong args, +                             uint32_t nret, target_ulong rets); +int spapr_rtas_device_tree_setup(void *fdt, hwaddr rtas_addr, +                                 hwaddr rtas_size); + +#define SPAPR_TCE_PAGE_SHIFT   12 +#define SPAPR_TCE_PAGE_SIZE    (1ULL << SPAPR_TCE_PAGE_SHIFT) +#define SPAPR_TCE_PAGE_MASK    (SPAPR_TCE_PAGE_SIZE - 1) + +#define SPAPR_VIO_BASE_LIOBN    0x00000000 +#define SPAPR_VIO_LIOBN(reg)    (0x00000000 | (reg)) +#define SPAPR_PCI_LIOBN(phb_index, window_num) \ +    (0x80000000 | ((phb_index) << 8) | (window_num)) +#define SPAPR_IS_PCI_LIOBN(liobn)   (!!((liobn) & 0x80000000)) +#define SPAPR_PCI_DMA_WINDOW_NUM(liobn) ((liobn) & 0xff) + +#define RTAS_ERROR_LOG_MAX      2048 + +#define RTAS_EVENT_SCAN_RATE    1 + +typedef struct sPAPRTCETable sPAPRTCETable; + +#define TYPE_SPAPR_TCE_TABLE "spapr-tce-table" +#define SPAPR_TCE_TABLE(obj) \ +    OBJECT_CHECK(sPAPRTCETable, (obj), TYPE_SPAPR_TCE_TABLE) + +struct sPAPRTCETable { +    DeviceState parent; +    uint32_t liobn; +    uint32_t nb_table; +    uint64_t bus_offset; +    uint32_t page_shift; +    uint64_t *table; +    bool bypass; +    bool vfio_accel; +    int fd; +    MemoryRegion iommu; +    struct VIOsPAPRDevice *vdev; /* for @bypass migration compatibility only */ +    QLIST_ENTRY(sPAPRTCETable) list; +}; + +sPAPRTCETable *spapr_tce_find_by_liobn(target_ulong liobn); + +struct sPAPREventLogEntry { +    int log_type; +    bool exception; +    void *data; +    QTAILQ_ENTRY(sPAPREventLogEntry) next; +}; + +void spapr_events_init(sPAPRMachineState *sm); +void spapr_events_fdt_skel(void *fdt, uint32_t epow_irq); +int spapr_h_cas_compose_response(sPAPRMachineState *sm, +                                 target_ulong addr, target_ulong size); +sPAPRTCETable *spapr_tce_new_table(DeviceState *owner, uint32_t liobn, +                                   uint64_t bus_offset, +                                   uint32_t page_shift, +                                   uint32_t nb_table, +                                   bool vfio_accel); +MemoryRegion *spapr_tce_get_iommu(sPAPRTCETable *tcet); +int spapr_dma_dt(void *fdt, int node_off, const char *propname, +                 uint32_t liobn, uint64_t window, uint32_t size); +int spapr_tcet_dma_dt(void *fdt, int node_off, const char *propname, +                      sPAPRTCETable *tcet); +void spapr_pci_switch_vga(bool big_endian); +void spapr_hotplug_req_add_event(sPAPRDRConnector *drc); +void spapr_hotplug_req_remove_event(sPAPRDRConnector *drc); + +/* rtas-configure-connector state */ +struct sPAPRConfigureConnectorState { +    uint32_t drc_index; +    int fdt_offset; +    int fdt_depth; +    QTAILQ_ENTRY(sPAPRConfigureConnectorState) next; +}; + +void spapr_ccs_reset_hook(void *opaque); + +#define TYPE_SPAPR_RTC "spapr-rtc" + +void spapr_rtc_read(DeviceState *dev, struct tm *tm, uint32_t *ns); +int spapr_rtc_import_offset(DeviceState *dev, int64_t legacy_offset); + +#define SPAPR_MEMORY_BLOCK_SIZE (1 << 28) /* 256MB */ + +#endif /* !defined (__HW_SPAPR_H__) */ diff --git a/include/hw/ppc/spapr_drc.h b/include/hw/ppc/spapr_drc.h new file mode 100644 index 00000000..60cda35e --- /dev/null +++ b/include/hw/ppc/spapr_drc.h @@ -0,0 +1,201 @@ +/* + * QEMU SPAPR Dynamic Reconfiguration Connector Implementation + * + * Copyright IBM Corp. 2014 + * + * Authors: + *  Michael Roth      <mdroth@linux.vnet.ibm.com> + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ +#if !defined(__HW_SPAPR_DRC_H__) +#define __HW_SPAPR_DRC_H__ + +#include "qom/object.h" +#include "hw/qdev.h" +#include "libfdt.h" + +#define TYPE_SPAPR_DR_CONNECTOR "spapr-dr-connector" +#define SPAPR_DR_CONNECTOR_GET_CLASS(obj) \ +        OBJECT_GET_CLASS(sPAPRDRConnectorClass, obj, TYPE_SPAPR_DR_CONNECTOR) +#define SPAPR_DR_CONNECTOR_CLASS(klass) \ +        OBJECT_CLASS_CHECK(sPAPRDRConnectorClass, klass, \ +                           TYPE_SPAPR_DR_CONNECTOR) +#define SPAPR_DR_CONNECTOR(obj) OBJECT_CHECK(sPAPRDRConnector, (obj), \ +                                             TYPE_SPAPR_DR_CONNECTOR) + +/* + * Various hotplug types managed by sPAPRDRConnector + * + * these are somewhat arbitrary, but to make things easier + * when generating DRC indexes later we've aligned the bit + * positions with the values used to assign DRC indexes on + * pSeries. we use those values as bit shifts to allow for + * the OR'ing of these values in various QEMU routines, but + * for values exposed to the guest (via DRC indexes for + * instance) we will use the shift amounts. + */ +typedef enum { +    SPAPR_DR_CONNECTOR_TYPE_SHIFT_CPU = 1, +    SPAPR_DR_CONNECTOR_TYPE_SHIFT_PHB = 2, +    SPAPR_DR_CONNECTOR_TYPE_SHIFT_VIO = 3, +    SPAPR_DR_CONNECTOR_TYPE_SHIFT_PCI = 4, +    SPAPR_DR_CONNECTOR_TYPE_SHIFT_LMB = 8, +} sPAPRDRConnectorTypeShift; + +typedef enum { +    SPAPR_DR_CONNECTOR_TYPE_ANY = ~0, +    SPAPR_DR_CONNECTOR_TYPE_CPU = 1 << SPAPR_DR_CONNECTOR_TYPE_SHIFT_CPU, +    SPAPR_DR_CONNECTOR_TYPE_PHB = 1 << SPAPR_DR_CONNECTOR_TYPE_SHIFT_PHB, +    SPAPR_DR_CONNECTOR_TYPE_VIO = 1 << SPAPR_DR_CONNECTOR_TYPE_SHIFT_VIO, +    SPAPR_DR_CONNECTOR_TYPE_PCI = 1 << SPAPR_DR_CONNECTOR_TYPE_SHIFT_PCI, +    SPAPR_DR_CONNECTOR_TYPE_LMB = 1 << SPAPR_DR_CONNECTOR_TYPE_SHIFT_LMB, +} sPAPRDRConnectorType; + +/* + * set via set-indicator RTAS calls + * as documented by PAPR+ 2.7 13.5.3.4, Table 177 + * + * isolated: put device under firmware control + * unisolated: claim OS control of device (may or may not be in use) + */ +typedef enum { +    SPAPR_DR_ISOLATION_STATE_ISOLATED   = 0, +    SPAPR_DR_ISOLATION_STATE_UNISOLATED = 1 +} sPAPRDRIsolationState; + +/* + * set via set-indicator RTAS calls + * as documented by PAPR+ 2.7 13.5.3.4, Table 177 + * + * unusable: mark device as unavailable to OS + * usable: mark device as available to OS + * exchange: (currently unused) + * recover: (currently unused) + */ +typedef enum { +    SPAPR_DR_ALLOCATION_STATE_UNUSABLE  = 0, +    SPAPR_DR_ALLOCATION_STATE_USABLE    = 1, +    SPAPR_DR_ALLOCATION_STATE_EXCHANGE  = 2, +    SPAPR_DR_ALLOCATION_STATE_RECOVER   = 3 +} sPAPRDRAllocationState; + +/* + * LED/visual indicator state + * + * set via set-indicator RTAS calls + * as documented by PAPR+ 2.7 13.5.3.4, Table 177, + * and PAPR+ 2.7 13.5.4.1, Table 180 + * + * inactive: hotpluggable entity inactive and safely removable + * active: hotpluggable entity in use and not safely removable + * identify: (currently unused) + * action: (currently unused) + */ +typedef enum { +    SPAPR_DR_INDICATOR_STATE_INACTIVE   = 0, +    SPAPR_DR_INDICATOR_STATE_ACTIVE     = 1, +    SPAPR_DR_INDICATOR_STATE_IDENTIFY   = 2, +    SPAPR_DR_INDICATOR_STATE_ACTION     = 3, +} sPAPRDRIndicatorState; + +/* + * returned via get-sensor-state RTAS calls + * as documented by PAPR+ 2.7 13.5.3.3, Table 175: + * + * empty: connector slot empty (e.g. empty hotpluggable PCI slot) + * present: connector slot populated and device available to OS + * unusable: device not currently available to OS + * exchange: (currently unused) + * recover: (currently unused) + */ +typedef enum { +    SPAPR_DR_ENTITY_SENSE_EMPTY     = 0, +    SPAPR_DR_ENTITY_SENSE_PRESENT   = 1, +    SPAPR_DR_ENTITY_SENSE_UNUSABLE  = 2, +    SPAPR_DR_ENTITY_SENSE_EXCHANGE  = 3, +    SPAPR_DR_ENTITY_SENSE_RECOVER   = 4, +} sPAPRDREntitySense; + +typedef enum { +    SPAPR_DR_CC_RESPONSE_NEXT_SIB       = 1, /* currently unused */ +    SPAPR_DR_CC_RESPONSE_NEXT_CHILD     = 2, +    SPAPR_DR_CC_RESPONSE_NEXT_PROPERTY  = 3, +    SPAPR_DR_CC_RESPONSE_PREV_PARENT    = 4, +    SPAPR_DR_CC_RESPONSE_SUCCESS        = 0, +    SPAPR_DR_CC_RESPONSE_ERROR          = -1, +    SPAPR_DR_CC_RESPONSE_CONTINUE       = -2, +} sPAPRDRCCResponse; + +typedef void (spapr_drc_detach_cb)(DeviceState *d, void *opaque); + +typedef struct sPAPRDRConnector { +    /*< private >*/ +    DeviceState parent; + +    sPAPRDRConnectorType type; +    uint32_t id; +    Object *owner; +    const char *name; + +    /* sensor/indicator states */ +    uint32_t isolation_state; +    uint32_t allocation_state; +    uint32_t indicator_state; + +    /* configure-connector state */ +    void *fdt; +    int fdt_start_offset; +    bool configured; + +    bool awaiting_release; + +    /* device pointer, via link property */ +    DeviceState *dev; +    spapr_drc_detach_cb *detach_cb; +    void *detach_cb_opaque; +} sPAPRDRConnector; + +typedef struct sPAPRDRConnectorClass { +    /*< private >*/ +    DeviceClass parent; + +    /*< public >*/ + +    /* accessors for guest-visible (generally via RTAS) DR state */ +    int (*set_isolation_state)(sPAPRDRConnector *drc, +                               sPAPRDRIsolationState state); +    int (*set_indicator_state)(sPAPRDRConnector *drc, +                               sPAPRDRIndicatorState state); +    int (*set_allocation_state)(sPAPRDRConnector *drc, +                                sPAPRDRAllocationState state); +    uint32_t (*get_index)(sPAPRDRConnector *drc); +    uint32_t (*get_type)(sPAPRDRConnector *drc); +    const char *(*get_name)(sPAPRDRConnector *drc); + +    sPAPRDREntitySense (*entity_sense)(sPAPRDRConnector *drc); + +    /* QEMU interfaces for managing FDT/configure-connector */ +    const void *(*get_fdt)(sPAPRDRConnector *drc, int *fdt_start_offset); +    void (*set_configured)(sPAPRDRConnector *drc); + +    /* QEMU interfaces for managing hotplug operations */ +    void (*attach)(sPAPRDRConnector *drc, DeviceState *d, void *fdt, +                   int fdt_start_offset, bool coldplug, Error **errp); +    void (*detach)(sPAPRDRConnector *drc, DeviceState *d, +                   spapr_drc_detach_cb *detach_cb, +                   void *detach_cb_opaque, Error **errp); +    bool (*release_pending)(sPAPRDRConnector *drc); +} sPAPRDRConnectorClass; + +sPAPRDRConnector *spapr_dr_connector_new(Object *owner, +                                         sPAPRDRConnectorType type, +                                         uint32_t id); +sPAPRDRConnector *spapr_dr_connector_by_index(uint32_t index); +sPAPRDRConnector *spapr_dr_connector_by_id(sPAPRDRConnectorType type, +                                           uint32_t id); +int spapr_drc_populate_dt(void *fdt, int fdt_offset, Object *owner, +                          uint32_t drc_type_mask); + +#endif /* __HW_SPAPR_DRC_H__ */ diff --git a/include/hw/ppc/spapr_vio.h b/include/hw/ppc/spapr_vio.h new file mode 100644 index 00000000..2299a540 --- /dev/null +++ b/include/hw/ppc/spapr_vio.h @@ -0,0 +1,148 @@ +#ifndef _HW_SPAPR_VIO_H +#define _HW_SPAPR_VIO_H +/* + * QEMU sPAPR VIO bus definitions + * + * Copyright (c) 2010 David Gibson, IBM Corporation <david@gibson.dropbear.id.au> + * Based on the s390 virtio bus definitions: + * Copyright (c) 2009 Alexander Graf <agraf@suse.de> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ + +#include "sysemu/dma.h" + +#define TYPE_VIO_SPAPR_DEVICE "vio-spapr-device" +#define VIO_SPAPR_DEVICE(obj) \ +     OBJECT_CHECK(VIOsPAPRDevice, (obj), TYPE_VIO_SPAPR_DEVICE) +#define VIO_SPAPR_DEVICE_CLASS(klass) \ +     OBJECT_CLASS_CHECK(VIOsPAPRDeviceClass, (klass), TYPE_VIO_SPAPR_DEVICE) +#define VIO_SPAPR_DEVICE_GET_CLASS(obj) \ +     OBJECT_GET_CLASS(VIOsPAPRDeviceClass, (obj), TYPE_VIO_SPAPR_DEVICE) + +#define TYPE_SPAPR_VIO_BUS "spapr-vio-bus" +#define SPAPR_VIO_BUS(obj) OBJECT_CHECK(VIOsPAPRBus, (obj), TYPE_SPAPR_VIO_BUS) + +struct VIOsPAPRDevice; + +typedef struct VIOsPAPR_CRQ { +    uint64_t qladdr; +    uint32_t qsize; +    uint32_t qnext; +    int(*SendFunc)(struct VIOsPAPRDevice *vdev, uint8_t *crq); +} VIOsPAPR_CRQ; + +typedef struct VIOsPAPRDevice VIOsPAPRDevice; +typedef struct VIOsPAPRBus VIOsPAPRBus; + +typedef struct VIOsPAPRDeviceClass { +    DeviceClass parent_class; + +    const char *dt_name, *dt_type, *dt_compatible; +    target_ulong signal_mask; +    uint32_t rtce_window_size; +    void (*realize)(VIOsPAPRDevice *dev, Error **errp); +    void (*reset)(VIOsPAPRDevice *dev); +    int (*devnode)(VIOsPAPRDevice *dev, void *fdt, int node_off); +} VIOsPAPRDeviceClass; + +struct VIOsPAPRDevice { +    DeviceState qdev; +    uint32_t reg; +    uint32_t irq; +    target_ulong signal_state; +    VIOsPAPR_CRQ crq; +    AddressSpace as; +    MemoryRegion mrroot; +    MemoryRegion mrbypass; +    sPAPRTCETable *tcet; +}; + +#define DEFINE_SPAPR_PROPERTIES(type, field)           \ +        DEFINE_PROP_UINT32("reg", type, field.reg, -1) + +struct VIOsPAPRBus { +    BusState bus; +    uint32_t next_reg; +    int (*init)(VIOsPAPRDevice *dev); +    int (*devnode)(VIOsPAPRDevice *dev, void *fdt, int node_off); +}; + +extern VIOsPAPRBus *spapr_vio_bus_init(void); +extern VIOsPAPRDevice *spapr_vio_find_by_reg(VIOsPAPRBus *bus, uint32_t reg); +extern int spapr_populate_vdevice(VIOsPAPRBus *bus, void *fdt); +extern int spapr_populate_chosen_stdout(void *fdt, VIOsPAPRBus *bus); + +extern int spapr_vio_signal(VIOsPAPRDevice *dev, target_ulong mode); + +static inline qemu_irq spapr_vio_qirq(VIOsPAPRDevice *dev) +{ +    sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine()); + +    return xics_get_qirq(spapr->icp, dev->irq); +} + +static inline bool spapr_vio_dma_valid(VIOsPAPRDevice *dev, uint64_t taddr, +                                       uint32_t size, DMADirection dir) +{ +    return dma_memory_valid(&dev->as, taddr, size, dir); +} + +static inline int spapr_vio_dma_read(VIOsPAPRDevice *dev, uint64_t taddr, +                                     void *buf, uint32_t size) +{ +    return (dma_memory_read(&dev->as, taddr, buf, size) != 0) ? +        H_DEST_PARM : H_SUCCESS; +} + +static inline int spapr_vio_dma_write(VIOsPAPRDevice *dev, uint64_t taddr, +                                      const void *buf, uint32_t size) +{ +    return (dma_memory_write(&dev->as, taddr, buf, size) != 0) ? +        H_DEST_PARM : H_SUCCESS; +} + +static inline int spapr_vio_dma_set(VIOsPAPRDevice *dev, uint64_t taddr, +                                    uint8_t c, uint32_t size) +{ +    return (dma_memory_set(&dev->as, taddr, c, size) != 0) ? +        H_DEST_PARM : H_SUCCESS; +} + +#define vio_stb(_dev, _addr, _val) (stb_dma(&(_dev)->as, (_addr), (_val))) +#define vio_sth(_dev, _addr, _val) (stw_be_dma(&(_dev)->as, (_addr), (_val))) +#define vio_stl(_dev, _addr, _val) (stl_be_dma(&(_dev)->as, (_addr), (_val))) +#define vio_stq(_dev, _addr, _val) (stq_be_dma(&(_dev)->as, (_addr), (_val))) +#define vio_ldq(_dev, _addr) (ldq_be_dma(&(_dev)->as, (_addr))) + +int spapr_vio_send_crq(VIOsPAPRDevice *dev, uint8_t *crq); + +VIOsPAPRDevice *vty_lookup(sPAPRMachineState *spapr, target_ulong reg); +void vty_putchars(VIOsPAPRDevice *sdev, uint8_t *buf, int len); +void spapr_vty_create(VIOsPAPRBus *bus, CharDriverState *chardev); +void spapr_vlan_create(VIOsPAPRBus *bus, NICInfo *nd); +void spapr_vscsi_create(VIOsPAPRBus *bus); + +VIOsPAPRDevice *spapr_vty_get_default(VIOsPAPRBus *bus); + +void spapr_vio_quiesce(void); + +extern const VMStateDescription vmstate_spapr_vio; + +#define VMSTATE_SPAPR_VIO(_f, _s) \ +    VMSTATE_STRUCT(_f, _s, 0, vmstate_spapr_vio, VIOsPAPRDevice) + +void spapr_vio_set_bypass(VIOsPAPRDevice *dev, bool bypass); + +#endif /* _HW_SPAPR_VIO_H */ diff --git a/include/hw/ppc/xics.h b/include/hw/ppc/xics.h new file mode 100644 index 00000000..355a9662 --- /dev/null +++ b/include/hw/ppc/xics.h @@ -0,0 +1,170 @@ +/* + * QEMU PowerPC pSeries Logical Partition (aka sPAPR) hardware System Emulator + * + * PAPR Virtualized Interrupt System, aka ICS/ICP aka xics + * + * Copyright (c) 2010,2011 David Gibson, IBM Corporation. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * 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 OTHER + * 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. + * + */ +#if !defined(__XICS_H__) +#define __XICS_H__ + +#include "hw/sysbus.h" + +#define TYPE_XICS_COMMON "xics-common" +#define XICS_COMMON(obj) OBJECT_CHECK(XICSState, (obj), TYPE_XICS_COMMON) + +#define TYPE_XICS "xics" +#define XICS(obj) OBJECT_CHECK(XICSState, (obj), TYPE_XICS) + +#define TYPE_KVM_XICS "xics-kvm" +#define KVM_XICS(obj) OBJECT_CHECK(KVMXICSState, (obj), TYPE_KVM_XICS) + +#define XICS_COMMON_CLASS(klass) \ +     OBJECT_CLASS_CHECK(XICSStateClass, (klass), TYPE_XICS_COMMON) +#define XICS_CLASS(klass) \ +     OBJECT_CLASS_CHECK(XICSStateClass, (klass), TYPE_XICS) +#define XICS_COMMON_GET_CLASS(obj) \ +     OBJECT_GET_CLASS(XICSStateClass, (obj), TYPE_XICS_COMMON) +#define XICS_GET_CLASS(obj) \ +     OBJECT_GET_CLASS(XICSStateClass, (obj), TYPE_XICS) + +#define XICS_IPI        0x2 +#define XICS_BUID       0x1 +#define XICS_IRQ_BASE   (XICS_BUID << 12) + +/* + * We currently only support one BUID which is our interrupt base + * (the kernel implementation supports more but we don't exploit + *  that yet) + */ +typedef struct XICSStateClass XICSStateClass; +typedef struct XICSState XICSState; +typedef struct ICPStateClass ICPStateClass; +typedef struct ICPState ICPState; +typedef struct ICSStateClass ICSStateClass; +typedef struct ICSState ICSState; +typedef struct ICSIRQState ICSIRQState; + +struct XICSStateClass { +    DeviceClass parent_class; + +    void (*cpu_setup)(XICSState *icp, PowerPCCPU *cpu); +    void (*set_nr_irqs)(XICSState *icp, uint32_t nr_irqs, Error **errp); +    void (*set_nr_servers)(XICSState *icp, uint32_t nr_servers, Error **errp); +}; + +struct XICSState { +    /*< private >*/ +    SysBusDevice parent_obj; +    /*< public >*/ +    uint32_t nr_servers; +    uint32_t nr_irqs; +    ICPState *ss; +    ICSState *ics; +}; + +#define TYPE_ICP "icp" +#define ICP(obj) OBJECT_CHECK(ICPState, (obj), TYPE_ICP) + +#define TYPE_KVM_ICP "icp-kvm" +#define KVM_ICP(obj) OBJECT_CHECK(ICPState, (obj), TYPE_KVM_ICP) + +#define ICP_CLASS(klass) \ +     OBJECT_CLASS_CHECK(ICPStateClass, (klass), TYPE_ICP) +#define ICP_GET_CLASS(obj) \ +     OBJECT_GET_CLASS(ICPStateClass, (obj), TYPE_ICP) + +struct ICPStateClass { +    DeviceClass parent_class; + +    void (*pre_save)(ICPState *s); +    int (*post_load)(ICPState *s, int version_id); +}; + +struct ICPState { +    /*< private >*/ +    DeviceState parent_obj; +    /*< public >*/ +    CPUState *cs; +    uint32_t xirr; +    uint8_t pending_priority; +    uint8_t mfrr; +    qemu_irq output; +    bool cap_irq_xics_enabled; +}; + +#define TYPE_ICS "ics" +#define ICS(obj) OBJECT_CHECK(ICSState, (obj), TYPE_ICS) + +#define TYPE_KVM_ICS "icskvm" +#define KVM_ICS(obj) OBJECT_CHECK(ICSState, (obj), TYPE_KVM_ICS) + +#define ICS_CLASS(klass) \ +     OBJECT_CLASS_CHECK(ICSStateClass, (klass), TYPE_ICS) +#define ICS_GET_CLASS(obj) \ +     OBJECT_GET_CLASS(ICSStateClass, (obj), TYPE_ICS) + +struct ICSStateClass { +    DeviceClass parent_class; + +    void (*pre_save)(ICSState *s); +    int (*post_load)(ICSState *s, int version_id); +}; + +struct ICSState { +    /*< private >*/ +    DeviceState parent_obj; +    /*< public >*/ +    uint32_t nr_irqs; +    uint32_t offset; +    qemu_irq *qirqs; +    ICSIRQState *irqs; +    XICSState *icp; +}; + +struct ICSIRQState { +    uint32_t server; +    uint8_t priority; +    uint8_t saved_priority; +#define XICS_STATUS_ASSERTED           0x1 +#define XICS_STATUS_SENT               0x2 +#define XICS_STATUS_REJECTED           0x4 +#define XICS_STATUS_MASKED_PENDING     0x8 +    uint8_t status; +/* (flags & XICS_FLAGS_IRQ_MASK) == 0 means the interrupt is not allocated */ +#define XICS_FLAGS_IRQ_LSI             0x1 +#define XICS_FLAGS_IRQ_MSI             0x2 +#define XICS_FLAGS_IRQ_MASK            0x3 +    uint8_t flags; +}; + +#define XICS_IRQS               1024 + +qemu_irq xics_get_qirq(XICSState *icp, int irq); +void xics_set_irq_type(XICSState *icp, int irq, bool lsi); +int xics_alloc(XICSState *icp, int src, int irq_hint, bool lsi); +int xics_alloc_block(XICSState *icp, int src, int num, bool lsi, bool align); +void xics_free(XICSState *icp, int irq, int num); + +void xics_cpu_setup(XICSState *icp, PowerPCCPU *cpu); + +#endif /* __XICS_H__ */ diff --git a/include/hw/ptimer.h b/include/hw/ptimer.h new file mode 100644 index 00000000..8ebacbbd --- /dev/null +++ b/include/hw/ptimer.h @@ -0,0 +1,37 @@ +/* + * General purpose implementation of a simple periodic countdown timer. + * + * Copyright (c) 2007 CodeSourcery. + * + * This code is licensed under the GNU LGPL. + */ +#ifndef PTIMER_H +#define PTIMER_H + +#include "qemu-common.h" +#include "qemu/timer.h" +#include "migration/vmstate.h" + +/* ptimer.c */ +typedef struct ptimer_state ptimer_state; +typedef void (*ptimer_cb)(void *opaque); + +ptimer_state *ptimer_init(QEMUBH *bh); +void ptimer_set_period(ptimer_state *s, int64_t period); +void ptimer_set_freq(ptimer_state *s, uint32_t freq); +void ptimer_set_limit(ptimer_state *s, uint64_t limit, int reload); +uint64_t ptimer_get_count(ptimer_state *s); +void ptimer_set_count(ptimer_state *s, uint64_t count); +void ptimer_run(ptimer_state *s, int oneshot); +void ptimer_stop(ptimer_state *s); + +extern const VMStateDescription vmstate_ptimer; + +#define VMSTATE_PTIMER(_field, _state) \ +    VMSTATE_STRUCT_POINTER_V(_field, _state, 1, vmstate_ptimer, ptimer_state) + +#define VMSTATE_PTIMER_ARRAY(_f, _s, _n)                                \ +    VMSTATE_ARRAY_OF_POINTER_TO_STRUCT(_f, _s, _n, 0,                   \ +                                       vmstate_ptimer, ptimer_state) + +#endif diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h new file mode 100644 index 00000000..8057aeda --- /dev/null +++ b/include/hw/qdev-core.h @@ -0,0 +1,403 @@ +#ifndef QDEV_CORE_H +#define QDEV_CORE_H + +#include "qemu/queue.h" +#include "qemu/option.h" +#include "qemu/typedefs.h" +#include "qemu/bitmap.h" +#include "qom/object.h" +#include "hw/irq.h" +#include "qapi/error.h" +#include "hw/hotplug.h" + +enum { +    DEV_NVECTORS_UNSPECIFIED = -1, +}; + +#define TYPE_DEVICE "device" +#define DEVICE(obj) OBJECT_CHECK(DeviceState, (obj), TYPE_DEVICE) +#define DEVICE_CLASS(klass) OBJECT_CLASS_CHECK(DeviceClass, (klass), TYPE_DEVICE) +#define DEVICE_GET_CLASS(obj) OBJECT_GET_CLASS(DeviceClass, (obj), TYPE_DEVICE) + +typedef enum DeviceCategory { +    DEVICE_CATEGORY_BRIDGE, +    DEVICE_CATEGORY_USB, +    DEVICE_CATEGORY_STORAGE, +    DEVICE_CATEGORY_NETWORK, +    DEVICE_CATEGORY_INPUT, +    DEVICE_CATEGORY_DISPLAY, +    DEVICE_CATEGORY_SOUND, +    DEVICE_CATEGORY_MISC, +    DEVICE_CATEGORY_MAX +} DeviceCategory; + +typedef int (*qdev_initfn)(DeviceState *dev); +typedef int (*qdev_event)(DeviceState *dev); +typedef void (*qdev_resetfn)(DeviceState *dev); +typedef void (*DeviceRealize)(DeviceState *dev, Error **errp); +typedef void (*DeviceUnrealize)(DeviceState *dev, Error **errp); +typedef void (*BusRealize)(BusState *bus, Error **errp); +typedef void (*BusUnrealize)(BusState *bus, Error **errp); + +struct VMStateDescription; + +/** + * DeviceClass: + * @props: Properties accessing state fields. + * @realize: Callback function invoked when the #DeviceState:realized + * property is changed to %true. The default invokes @init if not %NULL. + * @unrealize: Callback function invoked when the #DeviceState:realized + * property is changed to %false. + * @init: Callback function invoked when the #DeviceState::realized property + * is changed to %true. Deprecated, new types inheriting directly from + * TYPE_DEVICE should use @realize instead, new leaf types should consult + * their respective parent type. + * @hotpluggable: indicates if #DeviceClass is hotpluggable, available + * as readonly "hotpluggable" property of #DeviceState instance + * + * # Realization # + * Devices are constructed in two stages, + * 1) object instantiation via object_initialize() and + * 2) device realization via #DeviceState:realized property. + * The former may not fail (it might assert or exit), the latter may return + * error information to the caller and must be re-entrant. + * Trivial field initializations should go into #TypeInfo.instance_init. + * Operations depending on @props static properties should go into @realize. + * After successful realization, setting static properties will fail. + * + * As an interim step, the #DeviceState:realized property can also be + * set with qdev_init_nofail(). + * In the future, devices will propagate this state change to their children + * and along busses they expose. + * The point in time will be deferred to machine creation, so that values + * set in @realize will not be introspectable beforehand. Therefore devices + * must not create children during @realize; they should initialize them via + * object_initialize() in their own #TypeInfo.instance_init and forward the + * realization events appropriately. + * + * The @init callback is considered private to a particular bus implementation + * (immediate abstract child types of TYPE_DEVICE). Derived leaf types set an + * "init" callback on their parent class instead. + * + * Any type may override the @realize and/or @unrealize callbacks but needs + * to call the parent type's implementation if keeping their functionality + * is desired. Refer to QOM documentation for further discussion and examples. + * + * <note> + *   <para> + * If a type derived directly from TYPE_DEVICE implements @realize, it does + * not need to implement @init and therefore does not need to store and call + * #DeviceClass' default @realize callback. + * For other types consult the documentation and implementation of the + * respective parent types. + *   </para> + * </note> + */ +typedef struct DeviceClass { +    /*< private >*/ +    ObjectClass parent_class; +    /*< public >*/ + +    DECLARE_BITMAP(categories, DEVICE_CATEGORY_MAX); +    const char *fw_name; +    const char *desc; +    Property *props; + +    /* +     * Shall we hide this device model from -device / device_add? +     * All devices should support instantiation with device_add, and +     * this flag should not exist.  But we're not there, yet.  Some +     * devices fail to instantiate with cryptic error messages. +     * Others instantiate, but don't work.  Exposing users to such +     * behavior would be cruel; this flag serves to protect them.  It +     * should never be set without a comment explaining why it is set. +     * TODO remove once we're there +     */ +    bool cannot_instantiate_with_device_add_yet; +    /* +     * Does this device model survive object_unref(object_new(TNAME))? +     * All device models should, and this flag shouldn't exist.  Some +     * devices crash in object_new(), some crash or hang in +     * object_unref().  Makes introspecting properties with +     * qmp_device_list_properties() dangerous.  Bad, because it's used +     * by -device FOO,help.  This flag serves to protect that code. +     * It should never be set without a comment explaining why it is +     * set. +     * TODO remove once we're there +     */ +    bool cannot_destroy_with_object_finalize_yet; + +    bool hotpluggable; + +    /* callbacks */ +    void (*reset)(DeviceState *dev); +    DeviceRealize realize; +    DeviceUnrealize unrealize; + +    /* device state */ +    const struct VMStateDescription *vmsd; + +    /* Private to qdev / bus.  */ +    qdev_initfn init; /* TODO remove, once users are converted to realize */ +    qdev_event exit; /* TODO remove, once users are converted to unrealize */ +    const char *bus_type; +} DeviceClass; + +typedef struct NamedGPIOList NamedGPIOList; + +struct NamedGPIOList { +    char *name; +    qemu_irq *in; +    int num_in; +    int num_out; +    QLIST_ENTRY(NamedGPIOList) node; +}; + +/** + * DeviceState: + * @realized: Indicates whether the device has been fully constructed. + * + * This structure should not be accessed directly.  We declare it here + * so that it can be embedded in individual device state structures. + */ +struct DeviceState { +    /*< private >*/ +    Object parent_obj; +    /*< public >*/ + +    const char *id; +    bool realized; +    bool pending_deleted_event; +    QemuOpts *opts; +    int hotplugged; +    BusState *parent_bus; +    QLIST_HEAD(, NamedGPIOList) gpios; +    QLIST_HEAD(, BusState) child_bus; +    int num_child_bus; +    int instance_id_alias; +    int alias_required_for_version; +}; + +struct DeviceListener { +    void (*realize)(DeviceListener *listener, DeviceState *dev); +    void (*unrealize)(DeviceListener *listener, DeviceState *dev); +    QTAILQ_ENTRY(DeviceListener) link; +}; + +#define TYPE_BUS "bus" +#define BUS(obj) OBJECT_CHECK(BusState, (obj), TYPE_BUS) +#define BUS_CLASS(klass) OBJECT_CLASS_CHECK(BusClass, (klass), TYPE_BUS) +#define BUS_GET_CLASS(obj) OBJECT_GET_CLASS(BusClass, (obj), TYPE_BUS) + +struct BusClass { +    ObjectClass parent_class; + +    /* FIXME first arg should be BusState */ +    void (*print_dev)(Monitor *mon, DeviceState *dev, int indent); +    char *(*get_dev_path)(DeviceState *dev); +    /* +     * This callback is used to create Open Firmware device path in accordance +     * with OF spec http://forthworks.com/standards/of1275.pdf. Individual bus +     * bindings can be found at http://playground.sun.com/1275/bindings/. +     */ +    char *(*get_fw_dev_path)(DeviceState *dev); +    void (*reset)(BusState *bus); +    BusRealize realize; +    BusUnrealize unrealize; + +    /* maximum devices allowed on the bus, 0: no limit. */ +    int max_dev; +    /* number of automatically allocated bus ids (e.g. ide.0) */ +    int automatic_ids; +}; + +typedef struct BusChild { +    DeviceState *child; +    int index; +    QTAILQ_ENTRY(BusChild) sibling; +} BusChild; + +#define QDEV_HOTPLUG_HANDLER_PROPERTY "hotplug-handler" + +/** + * BusState: + * @hotplug_device: link to a hotplug device associated with bus. + */ +struct BusState { +    Object obj; +    DeviceState *parent; +    const char *name; +    HotplugHandler *hotplug_handler; +    int max_index; +    bool realized; +    QTAILQ_HEAD(ChildrenHead, BusChild) children; +    QLIST_ENTRY(BusState) sibling; +}; + +struct Property { +    const char   *name; +    PropertyInfo *info; +    int          offset; +    uint8_t      bitnr; +    qtype_code   qtype; +    int64_t      defval; +    int          arrayoffset; +    PropertyInfo *arrayinfo; +    int          arrayfieldsize; +}; + +struct PropertyInfo { +    const char *name; +    const char *description; +    const char * const *enum_table; +    int (*print)(DeviceState *dev, Property *prop, char *dest, size_t len); +    ObjectPropertyAccessor *get; +    ObjectPropertyAccessor *set; +    ObjectPropertyRelease *release; +}; + +/** + * GlobalProperty: + * @user_provided: Set to true if property comes from user-provided config + * (command-line or config file). + * @used: Set to true if property was used when initializing a device. + */ +typedef struct GlobalProperty { +    const char *driver; +    const char *property; +    const char *value; +    bool user_provided; +    bool used; +    QTAILQ_ENTRY(GlobalProperty) next; +} GlobalProperty; + +/*** Board API.  This should go away once we have a machine config file.  ***/ + +DeviceState *qdev_create(BusState *bus, const char *name); +DeviceState *qdev_try_create(BusState *bus, const char *name); +void qdev_init_nofail(DeviceState *dev); +void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id, +                                 int required_for_version); +HotplugHandler *qdev_get_hotplug_handler(DeviceState *dev); +void qdev_unplug(DeviceState *dev, Error **errp); +void qdev_simple_device_unplug_cb(HotplugHandler *hotplug_dev, +                                  DeviceState *dev, Error **errp); +void qdev_machine_creation_done(void); +bool qdev_machine_modified(void); + +qemu_irq qdev_get_gpio_in(DeviceState *dev, int n); +qemu_irq qdev_get_gpio_in_named(DeviceState *dev, const char *name, int n); + +void qdev_connect_gpio_out(DeviceState *dev, int n, qemu_irq pin); +void qdev_connect_gpio_out_named(DeviceState *dev, const char *name, int n, +                                 qemu_irq pin); +qemu_irq qdev_get_gpio_out_connector(DeviceState *dev, const char *name, int n); +qemu_irq qdev_intercept_gpio_out(DeviceState *dev, qemu_irq icpt, +                                 const char *name, int n); + +BusState *qdev_get_child_bus(DeviceState *dev, const char *name); + +/*** Device API.  ***/ + +/* Register device properties.  */ +/* GPIO inputs also double as IRQ sinks.  */ +void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n); +void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n); +void qdev_init_gpio_in_named(DeviceState *dev, qemu_irq_handler handler, +                             const char *name, int n); +void qdev_init_gpio_out_named(DeviceState *dev, qemu_irq *pins, +                              const char *name, int n); + +void qdev_pass_gpios(DeviceState *dev, DeviceState *container, +                     const char *name); + +BusState *qdev_get_parent_bus(DeviceState *dev); + +/*** BUS API. ***/ + +DeviceState *qdev_find_recursive(BusState *bus, const char *id); + +/* Returns 0 to walk children, > 0 to skip walk, < 0 to terminate walk. */ +typedef int (qbus_walkerfn)(BusState *bus, void *opaque); +typedef int (qdev_walkerfn)(DeviceState *dev, void *opaque); + +void qbus_create_inplace(void *bus, size_t size, const char *typename, +                         DeviceState *parent, const char *name); +BusState *qbus_create(const char *typename, DeviceState *parent, const char *name); +/* Returns > 0 if either devfn or busfn skip walk somewhere in cursion, + *         < 0 if either devfn or busfn terminate walk somewhere in cursion, + *           0 otherwise. */ +int qbus_walk_children(BusState *bus, +                       qdev_walkerfn *pre_devfn, qbus_walkerfn *pre_busfn, +                       qdev_walkerfn *post_devfn, qbus_walkerfn *post_busfn, +                       void *opaque); +int qdev_walk_children(DeviceState *dev, +                       qdev_walkerfn *pre_devfn, qbus_walkerfn *pre_busfn, +                       qdev_walkerfn *post_devfn, qbus_walkerfn *post_busfn, +                       void *opaque); + +void qdev_reset_all(DeviceState *dev); + +/** + * @qbus_reset_all: + * @bus: Bus to be reset. + * + * Reset @bus and perform a bus-level ("hard") reset of all devices connected + * to it, including recursive processing of all buses below @bus itself.  A + * hard reset means that qbus_reset_all will reset all state of the device. + * For PCI devices, for example, this will include the base address registers + * or configuration space. + */ +void qbus_reset_all(BusState *bus); +void qbus_reset_all_fn(void *opaque); + +/* This should go away once we get rid of the NULL bus hack */ +BusState *sysbus_get_default(void); + +char *qdev_get_fw_dev_path(DeviceState *dev); +char *qdev_get_own_fw_dev_path_from_handler(BusState *bus, DeviceState *dev); + +/** + * @qdev_machine_init + * + * Initialize platform devices before machine init.  This is a hack until full + * support for composition is added. + */ +void qdev_machine_init(void); + +/** + * @device_reset + * + * Reset a single device (by calling the reset method). + */ +void device_reset(DeviceState *dev); + +const struct VMStateDescription *qdev_get_vmsd(DeviceState *dev); + +const char *qdev_fw_name(DeviceState *dev); + +Object *qdev_get_machine(void); + +/* FIXME: make this a link<> */ +void qdev_set_parent_bus(DeviceState *dev, BusState *bus); + +extern int qdev_hotplug; + +char *qdev_get_dev_path(DeviceState *dev); + +GSList *qdev_build_hotpluggable_device_list(Object *peripheral); + +void qbus_set_hotplug_handler(BusState *bus, DeviceState *handler, +                              Error **errp); + +void qbus_set_bus_hotplug_handler(BusState *bus, Error **errp); + +static inline bool qbus_is_hotpluggable(BusState *bus) +{ +   return bus->hotplug_handler; +} + +void device_listener_register(DeviceListener *listener); +void device_listener_unregister(DeviceListener *listener); + +#endif diff --git a/include/hw/qdev-dma.h b/include/hw/qdev-dma.h new file mode 100644 index 00000000..8cfb0f34 --- /dev/null +++ b/include/hw/qdev-dma.h @@ -0,0 +1,10 @@ +/* + * Support for dma_addr_t typed properties + * + * Copyright (C) 2012 David Gibson, IBM Corporation. + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ +#define DEFINE_PROP_DMAADDR(_n, _s, _f, _d)                               \ +    DEFINE_PROP_UINT64(_n, _s, _f, _d) diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h new file mode 100644 index 00000000..77538a8c --- /dev/null +++ b/include/hw/qdev-properties.h @@ -0,0 +1,228 @@ +#ifndef QEMU_QDEV_PROPERTIES_H +#define QEMU_QDEV_PROPERTIES_H + +#include "hw/qdev-core.h" + +/*** qdev-properties.c ***/ + +extern PropertyInfo qdev_prop_bit; +extern PropertyInfo qdev_prop_bit64; +extern PropertyInfo qdev_prop_bool; +extern PropertyInfo qdev_prop_uint8; +extern PropertyInfo qdev_prop_uint16; +extern PropertyInfo qdev_prop_uint32; +extern PropertyInfo qdev_prop_int32; +extern PropertyInfo qdev_prop_uint64; +extern PropertyInfo qdev_prop_size; +extern PropertyInfo qdev_prop_string; +extern PropertyInfo qdev_prop_chr; +extern PropertyInfo qdev_prop_ptr; +extern PropertyInfo qdev_prop_macaddr; +extern PropertyInfo qdev_prop_losttickpolicy; +extern PropertyInfo qdev_prop_bios_chs_trans; +extern PropertyInfo qdev_prop_drive; +extern PropertyInfo qdev_prop_netdev; +extern PropertyInfo qdev_prop_vlan; +extern PropertyInfo qdev_prop_pci_devfn; +extern PropertyInfo qdev_prop_blocksize; +extern PropertyInfo qdev_prop_pci_host_devaddr; +extern PropertyInfo qdev_prop_arraylen; + +#define DEFINE_PROP(_name, _state, _field, _prop, _type) { \ +        .name      = (_name),                                    \ +        .info      = &(_prop),                                   \ +        .offset    = offsetof(_state, _field)                    \ +            + type_check(_type, typeof_field(_state, _field)),   \ +        } +#define DEFINE_PROP_DEFAULT(_name, _state, _field, _defval, _prop, _type) { \ +        .name      = (_name),                                           \ +        .info      = &(_prop),                                          \ +        .offset    = offsetof(_state, _field)                           \ +            + type_check(_type,typeof_field(_state, _field)),           \ +        .qtype     = QTYPE_QINT,                                        \ +        .defval    = (_type)_defval,                                    \ +        } +#define DEFINE_PROP_BIT(_name, _state, _field, _bit, _defval) {  \ +        .name      = (_name),                                    \ +        .info      = &(qdev_prop_bit),                           \ +        .bitnr    = (_bit),                                      \ +        .offset    = offsetof(_state, _field)                    \ +            + type_check(uint32_t,typeof_field(_state, _field)), \ +        .qtype     = QTYPE_QBOOL,                                \ +        .defval    = (bool)_defval,                              \ +        } +#define DEFINE_PROP_BIT64(_name, _state, _field, _bit, _defval) {       \ +        .name      = (_name),                                           \ +        .info      = &(qdev_prop_bit64),                                \ +        .bitnr    = (_bit),                                             \ +        .offset    = offsetof(_state, _field)                           \ +            + type_check(uint64_t, typeof_field(_state, _field)),       \ +        .qtype     = QTYPE_QBOOL,                                       \ +        .defval    = (bool)_defval,                                     \ +        } + +#define DEFINE_PROP_BOOL(_name, _state, _field, _defval) {       \ +        .name      = (_name),                                    \ +        .info      = &(qdev_prop_bool),                          \ +        .offset    = offsetof(_state, _field)                    \ +            + type_check(bool, typeof_field(_state, _field)),    \ +        .qtype     = QTYPE_QBOOL,                                \ +        .defval    = (bool)_defval,                              \ +        } + +#define PROP_ARRAY_LEN_PREFIX "len-" + +/** + * DEFINE_PROP_ARRAY: + * @_name: name of the array + * @_state: name of the device state structure type + * @_field: uint32_t field in @_state to hold the array length + * @_arrayfield: field in @_state (of type '@_arraytype *') which + *               will point to the array + * @_arrayprop: PropertyInfo defining what property the array elements have + * @_arraytype: C type of the array elements + * + * Define device properties for a variable-length array _name.  A + * static property "len-arrayname" is defined. When the device creator + * sets this property to the desired length of array, further dynamic + * properties "arrayname[0]", "arrayname[1]", ...  are defined so the + * device creator can set the array element values. Setting the + * "len-arrayname" property more than once is an error. + * + * When the array length is set, the @_field member of the device + * struct is set to the array length, and @_arrayfield is set to point + * to (zero-initialised) memory allocated for the array.  For a zero + * length array, @_field will be set to 0 and @_arrayfield to NULL. + * It is the responsibility of the device deinit code to free the + * @_arrayfield memory. + */ +#define DEFINE_PROP_ARRAY(_name, _state, _field,                        \ +                          _arrayfield, _arrayprop, _arraytype) {        \ +        .name = (PROP_ARRAY_LEN_PREFIX _name),                          \ +        .info = &(qdev_prop_arraylen),                                  \ +        .offset = offsetof(_state, _field)                              \ +            + type_check(uint32_t, typeof_field(_state, _field)),       \ +        .qtype = QTYPE_QINT,                                            \ +        .arrayinfo = &(_arrayprop),                                     \ +        .arrayfieldsize = sizeof(_arraytype),                           \ +        .arrayoffset = offsetof(_state, _arrayfield),                   \ +        } + +#define DEFINE_PROP_UINT8(_n, _s, _f, _d)                       \ +    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_uint8, uint8_t) +#define DEFINE_PROP_UINT16(_n, _s, _f, _d)                      \ +    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_uint16, uint16_t) +#define DEFINE_PROP_UINT32(_n, _s, _f, _d)                      \ +    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_uint32, uint32_t) +#define DEFINE_PROP_INT32(_n, _s, _f, _d)                      \ +    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_int32, int32_t) +#define DEFINE_PROP_UINT64(_n, _s, _f, _d)                      \ +    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_uint64, uint64_t) +#define DEFINE_PROP_SIZE(_n, _s, _f, _d)                       \ +    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_size, uint64_t) +#define DEFINE_PROP_PCI_DEVFN(_n, _s, _f, _d)                   \ +    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_pci_devfn, int32_t) + +/* + * Please avoid pointer properties.  If you must use them, you must + * cover them in their device's class init function as follows: + * + * - If the property must be set, the device cannot be used with + *   device_add, so add code like this: + *   |* Reason: pointer property "NAME-OF-YOUR-PROP" *| + *   DeviceClass *dc = DEVICE_CLASS(class); + *   dc->cannot_instantiate_with_device_add_yet = true; + * + * - If the property may safely remain null, document it like this: + *   |* + *    * Note: pointer property "interrupt_vector" may remain null, thus + *    * no need for dc->cannot_instantiate_with_device_add_yet = true; + *    *| + */ +#define DEFINE_PROP_PTR(_n, _s, _f)             \ +    DEFINE_PROP(_n, _s, _f, qdev_prop_ptr, void*) + +#define DEFINE_PROP_CHR(_n, _s, _f)             \ +    DEFINE_PROP(_n, _s, _f, qdev_prop_chr, CharDriverState*) +#define DEFINE_PROP_STRING(_n, _s, _f)             \ +    DEFINE_PROP(_n, _s, _f, qdev_prop_string, char*) +#define DEFINE_PROP_NETDEV(_n, _s, _f)             \ +    DEFINE_PROP(_n, _s, _f, qdev_prop_netdev, NICPeers) +#define DEFINE_PROP_VLAN(_n, _s, _f)             \ +    DEFINE_PROP(_n, _s, _f, qdev_prop_vlan, NICPeers) +#define DEFINE_PROP_DRIVE(_n, _s, _f) \ +    DEFINE_PROP(_n, _s, _f, qdev_prop_drive, BlockBackend *) +#define DEFINE_PROP_MACADDR(_n, _s, _f)         \ +    DEFINE_PROP(_n, _s, _f, qdev_prop_macaddr, MACAddr) +#define DEFINE_PROP_LOSTTICKPOLICY(_n, _s, _f, _d) \ +    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_losttickpolicy, \ +                        LostTickPolicy) +#define DEFINE_PROP_BIOS_CHS_TRANS(_n, _s, _f, _d) \ +    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_bios_chs_trans, int) +#define DEFINE_PROP_BLOCKSIZE(_n, _s, _f) \ +    DEFINE_PROP_DEFAULT(_n, _s, _f, 0, qdev_prop_blocksize, uint16_t) +#define DEFINE_PROP_PCI_HOST_DEVADDR(_n, _s, _f) \ +    DEFINE_PROP(_n, _s, _f, qdev_prop_pci_host_devaddr, PCIHostDeviceAddress) + +#define DEFINE_PROP_END_OF_LIST()               \ +    {} + +/* Set properties between creation and init.  */ +void *qdev_get_prop_ptr(DeviceState *dev, Property *prop); +void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value); +void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value); +void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value); +void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value); +void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value); +void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value); +void qdev_prop_set_string(DeviceState *dev, const char *name, const char *value); +void qdev_prop_set_chr(DeviceState *dev, const char *name, CharDriverState *value); +void qdev_prop_set_netdev(DeviceState *dev, const char *name, NetClientState *value); +void qdev_prop_set_drive(DeviceState *dev, const char *name, +                         BlockBackend *value, Error **errp); +void qdev_prop_set_drive_nofail(DeviceState *dev, const char *name, +                                BlockBackend *value); +void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value); +void qdev_prop_set_enum(DeviceState *dev, const char *name, int value); +/* FIXME: Remove opaque pointer properties.  */ +void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value); + +void qdev_prop_register_global(GlobalProperty *prop); +void qdev_prop_register_global_list(GlobalProperty *props); +int qdev_prop_check_globals(void); +void qdev_prop_set_globals(DeviceState *dev); +void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev, +                                    Property *prop, const char *value); + +/** + * @qdev_property_add_static - add a @Property to a device referencing a + * field in a struct. + */ +void qdev_property_add_static(DeviceState *dev, Property *prop, Error **errp); + +void qdev_alias_all_properties(DeviceState *target, Object *source); + +/** + * @qdev_prop_set_after_realize: + * @dev: device + * @name: name of property + * @errp: indirect pointer to Error to be set + * Set the Error object to report that an attempt was made to set a property + * on a device after it has already been realized. This is a utility function + * which allows property-setter functions to easily report the error in + * a friendly format identifying both the device and the property. + */ +void qdev_prop_set_after_realize(DeviceState *dev, const char *name, +                                 Error **errp); + +/** + * qdev_prop_allow_set_link_before_realize: + * + * Set the #Error object if an attempt is made to set the link after realize. + * This function should be used as the check() argument to + * object_property_add_link(). + */ +void qdev_prop_allow_set_link_before_realize(Object *obj, const char *name, +                                             Object *val, Error **errp); + +#endif diff --git a/include/hw/qdev.h b/include/hw/qdev.h new file mode 100644 index 00000000..5cb8b080 --- /dev/null +++ b/include/hw/qdev.h @@ -0,0 +1,8 @@ +#ifndef QDEV_H +#define QDEV_H + +#include "hw/hw.h" +#include "hw/qdev-core.h" +#include "hw/qdev-properties.h" + +#endif diff --git a/include/hw/s390x/adapter.h b/include/hw/s390x/adapter.h new file mode 100644 index 00000000..7f170350 --- /dev/null +++ b/include/hw/s390x/adapter.h @@ -0,0 +1,23 @@ +/* + * s390 adapter definitions + * + * Copyright 2013,2014 IBM Corp. + * Author(s): Cornelia Huck <cornelia.huck@de.ibm.com> + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at + * your option) any later version. See the COPYING file in the top-level + * directory. + */ + +#ifndef S390X_ADAPTER_H +#define S390X_ADAPTER_H + +struct AdapterInfo { +    uint64_t ind_addr; +    uint64_t summary_addr; +    uint64_t ind_offset; +    uint32_t summary_offset; +    uint32_t adapter_id; +}; + +#endif diff --git a/include/hw/s390x/ebcdic.h b/include/hw/s390x/ebcdic.h new file mode 100644 index 00000000..1d6fde9c --- /dev/null +++ b/include/hw/s390x/ebcdic.h @@ -0,0 +1,104 @@ +/* + * EBCDIC/ASCII conversion Support + * + * Copyright (c) 2011 Alexander Graf + * Copyright IBM, Corp. 2013 + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at your + * option) any later version.  See the COPYING file in the top-level directory. + * + */ + +#ifndef EBCDIC_H_ +#define EBCDIC_H_ + +/* EBCDIC handling */ +static const uint8_t ebcdic2ascii[] = { +    0x00, 0x01, 0x02, 0x03, 0x07, 0x09, 0x07, 0x7F, +    0x07, 0x07, 0x07, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, +    0x10, 0x11, 0x12, 0x13, 0x07, 0x0A, 0x08, 0x07, +    0x18, 0x19, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, +    0x07, 0x07, 0x1C, 0x07, 0x07, 0x0A, 0x17, 0x1B, +    0x07, 0x07, 0x07, 0x07, 0x07, 0x05, 0x06, 0x07, +    0x07, 0x07, 0x16, 0x07, 0x07, 0x07, 0x07, 0x04, +    0x07, 0x07, 0x07, 0x07, 0x14, 0x15, 0x07, 0x1A, +    0x20, 0xFF, 0x83, 0x84, 0x85, 0xA0, 0x07, 0x86, +    0x87, 0xA4, 0x5B, 0x2E, 0x3C, 0x28, 0x2B, 0x21, +    0x26, 0x82, 0x88, 0x89, 0x8A, 0xA1, 0x8C, 0x07, +    0x8D, 0xE1, 0x5D, 0x24, 0x2A, 0x29, 0x3B, 0x5E, +    0x2D, 0x2F, 0x07, 0x8E, 0x07, 0x07, 0x07, 0x8F, +    0x80, 0xA5, 0x07, 0x2C, 0x25, 0x5F, 0x3E, 0x3F, +    0x07, 0x90, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, +    0x70, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22, +    0x07, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, +    0x68, 0x69, 0xAE, 0xAF, 0x07, 0x07, 0x07, 0xF1, +    0xF8, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, +    0x71, 0x72, 0xA6, 0xA7, 0x91, 0x07, 0x92, 0x07, +    0xE6, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, +    0x79, 0x7A, 0xAD, 0xAB, 0x07, 0x07, 0x07, 0x07, +    0x9B, 0x9C, 0x9D, 0xFA, 0x07, 0x07, 0x07, 0xAC, +    0xAB, 0x07, 0xAA, 0x7C, 0x07, 0x07, 0x07, 0x07, +    0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, +    0x48, 0x49, 0x07, 0x93, 0x94, 0x95, 0xA2, 0x07, +    0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, +    0x51, 0x52, 0x07, 0x96, 0x81, 0x97, 0xA3, 0x98, +    0x5C, 0xF6, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, +    0x59, 0x5A, 0xFD, 0x07, 0x99, 0x07, 0x07, 0x07, +    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, +    0x38, 0x39, 0x07, 0x07, 0x9A, 0x07, 0x07, 0x07, +}; + +static const uint8_t ascii2ebcdic[] = { +    0x00, 0x01, 0x02, 0x03, 0x37, 0x2D, 0x2E, 0x2F, +    0x16, 0x05, 0x15, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, +    0x10, 0x11, 0x12, 0x13, 0x3C, 0x3D, 0x32, 0x26, +    0x18, 0x19, 0x3F, 0x27, 0x22, 0x1D, 0x1E, 0x1F, +    0x40, 0x5A, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D, +    0x4D, 0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61, +    0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, +    0xF8, 0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F, +    0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, +    0xC8, 0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, +    0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, +    0xE7, 0xE8, 0xE9, 0xBA, 0xE0, 0xBB, 0xB0, 0x6D, +    0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, +    0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, +    0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, +    0xA7, 0xA8, 0xA9, 0xC0, 0x4F, 0xD0, 0xA1, 0x07, +    0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, +    0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, +    0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, +    0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, +    0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, +    0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, +    0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, +    0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, +    0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, +    0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, +    0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, +    0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, +    0x3F, 0x59, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, +    0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, +    0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, +    0x90, 0x3F, 0x3F, 0x3F, 0x3F, 0xEA, 0x3F, 0xFF +}; + +static inline void ebcdic_put(uint8_t *p, const char *ascii, int len) +{ +    int i; + +    for (i = 0; i < len; i++) { +        p[i] = ascii2ebcdic[(uint8_t)ascii[i]]; +    } +} + +static inline void ascii_put(uint8_t *p, const char *ebcdic, int len) +{ +    int i; + +    for (i = 0; i < len; i++) { +        p[i] = ebcdic2ascii[(uint8_t)ebcdic[i]]; +    } +} + +#endif /* EBCDIC_H_ */ diff --git a/include/hw/s390x/event-facility.h b/include/hw/s390x/event-facility.h new file mode 100644 index 00000000..6a062b66 --- /dev/null +++ b/include/hw/s390x/event-facility.h @@ -0,0 +1,198 @@ +/* + * SCLP + *    Event Facility definitions + * + * Copyright IBM, Corp. 2012 + * + * Authors: + *  Heinz Graalfs <graalfs@de.ibm.com> + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at your + * option) any later version.  See the COPYING file in the top-level directory. + * + */ + +#ifndef HW_S390_SCLP_EVENT_FACILITY_H +#define HW_S390_SCLP_EVENT_FACILITY_H + +#include <hw/qdev.h> +#include "qemu/thread.h" +#include "hw/s390x/sclp.h" + +/* SCLP event types */ +#define SCLP_EVENT_OPRTNS_COMMAND               0x01 +#define SCLP_EVENT_MESSAGE                      0x02 +#define SCLP_EVENT_CONFIG_MGT_DATA              0x04 +#define SCLP_EVENT_PMSGCMD                      0x09 +#define SCLP_EVENT_ASCII_CONSOLE_DATA           0x1a +#define SCLP_EVENT_SIGNAL_QUIESCE               0x1d + +/* SCLP event masks */ +#define SCLP_EVENT_MASK_SIGNAL_QUIESCE          0x00000008 +#define SCLP_EVENT_MASK_MSG_ASCII               0x00000040 +#define SCLP_EVENT_MASK_CONFIG_MGT_DATA         0x10000000 +#define SCLP_EVENT_MASK_OP_CMD                  0x80000000 +#define SCLP_EVENT_MASK_MSG                     0x40000000 +#define SCLP_EVENT_MASK_PMSGCMD                 0x00800000 + +#define SCLP_UNCONDITIONAL_READ                 0x00 +#define SCLP_SELECTIVE_READ                     0x01 + +#define TYPE_SCLP_EVENT "s390-sclp-event-type" +#define SCLP_EVENT(obj) \ +     OBJECT_CHECK(SCLPEvent, (obj), TYPE_SCLP_EVENT) +#define SCLP_EVENT_CLASS(klass) \ +     OBJECT_CLASS_CHECK(SCLPEventClass, (klass), TYPE_SCLP_EVENT) +#define SCLP_EVENT_GET_CLASS(obj) \ +     OBJECT_GET_CLASS(SCLPEventClass, (obj), TYPE_SCLP_EVENT) + +#define TYPE_SCLP_CPU_HOTPLUG "sclp-cpu-hotplug" + +typedef struct WriteEventMask { +    SCCBHeader h; +    uint16_t _reserved; +    uint16_t mask_length; +    uint32_t cp_receive_mask; +    uint32_t cp_send_mask; +    uint32_t receive_mask; +    uint32_t send_mask; +} QEMU_PACKED WriteEventMask; + +typedef struct EventBufferHeader { +    uint16_t length; +    uint8_t  type; +    uint8_t  flags; +    uint16_t _reserved; +} QEMU_PACKED EventBufferHeader; + +typedef struct MdbHeader { +    uint16_t length; +    uint16_t type; +    uint32_t tag; +    uint32_t revision_code; +} QEMU_PACKED MdbHeader; + +typedef struct MTO { +    uint16_t line_type_flags; +    uint8_t  alarm_control; +    uint8_t  _reserved[3]; +    char     message[]; +} QEMU_PACKED MTO; + +typedef struct GO { +    uint32_t domid; +    uint8_t  hhmmss_time[8]; +    uint8_t  th_time[3]; +    uint8_t  _reserved_0; +    uint8_t  dddyyyy_date[7]; +    uint8_t  _reserved_1; +    uint16_t general_msg_flags; +    uint8_t  _reserved_2[10]; +    uint8_t  originating_system_name[8]; +    uint8_t  job_guest_name[8]; +} QEMU_PACKED GO; + +#define MESSAGE_TEXT 0x0004 + +typedef struct MDBO { +    uint16_t length; +    uint16_t type; +    union { +        GO go; +        MTO mto; +    }; +} QEMU_PACKED MDBO; + +typedef struct MDB { +    MdbHeader header; +    MDBO mdbo[0]; +} QEMU_PACKED MDB; + +typedef struct SclpMsg { +    EventBufferHeader header; +    MDB mdb; +} QEMU_PACKED SclpMsg; + +#define GDS_ID_MDSMU                            0x1310 +#define GDS_ID_CPMSU                            0x1212 +#define GDS_ID_TEXTCMD                          0x1320 + +typedef struct GdsVector { +    uint16_t length; +    uint16_t gds_id; +} QEMU_PACKED GdsVector; + +#define GDS_KEY_SELFDEFTEXTMSG                  0x31 +#define GDS_KEY_TEXTMSG                         0x30 + +typedef struct GdsSubvector { +    uint8_t length; +    uint8_t key; +} QEMU_PACKED GdsSubvector; + +/* MDS Message Unit */ +typedef struct MDMSU { +    GdsVector mdmsu; +    GdsVector cpmsu; +    GdsVector text_command; +    GdsSubvector self_def_text_message; +    GdsSubvector text_message; +} QEMU_PACKED MDMSU; + +typedef struct WriteEventData { +    SCCBHeader h; +    EventBufferHeader ebh; +} QEMU_PACKED WriteEventData; + +typedef struct ReadEventData { +    SCCBHeader h; +    EventBufferHeader ebh; +    uint32_t mask; +} QEMU_PACKED ReadEventData; + +typedef struct SCLPEvent { +    DeviceState qdev; +    bool event_pending; +    char *name; +} SCLPEvent; + +typedef struct SCLPEventClass { +    DeviceClass parent_class; +    int (*init)(SCLPEvent *event); +    int (*exit)(SCLPEvent *event); + +    /* get SCLP's send mask */ +    unsigned int (*get_send_mask)(void); + +    /* get SCLP's receive mask */ +    unsigned int (*get_receive_mask)(void); + +    int (*read_event_data)(SCLPEvent *event, EventBufferHeader *evt_buf_hdr, +                           int *slen); + +    int (*write_event_data)(SCLPEvent *event, EventBufferHeader *evt_buf_hdr); + +    /* can we handle this event type? */ +    bool (*can_handle_event)(uint8_t type); +} SCLPEventClass; + +#define TYPE_SCLP_EVENT_FACILITY "s390-sclp-event-facility" +#define EVENT_FACILITY(obj) \ +     OBJECT_CHECK(SCLPEventFacility, (obj), TYPE_SCLP_EVENT_FACILITY) +#define EVENT_FACILITY_CLASS(klass) \ +     OBJECT_CLASS_CHECK(SCLPEventFacilityClass, (klass), \ +                        TYPE_SCLP_EVENT_FACILITY) +#define EVENT_FACILITY_GET_CLASS(obj) \ +     OBJECT_GET_CLASS(SCLPEventFacilityClass, (obj), \ +                      TYPE_SCLP_EVENT_FACILITY) + +typedef struct SCLPEventFacility SCLPEventFacility; + +typedef struct SCLPEventFacilityClass { +    DeviceClass parent_class; +    int (*init)(SCLPEventFacility *ef); +    void (*command_handler)(SCLPEventFacility *ef, SCCB *sccb, uint64_t code); +    bool (*event_pending)(SCLPEventFacility *ef); +} SCLPEventFacilityClass; + +#endif diff --git a/include/hw/s390x/s390_flic.h b/include/hw/s390x/s390_flic.h new file mode 100644 index 00000000..200e7e93 --- /dev/null +++ b/include/hw/s390x/s390_flic.h @@ -0,0 +1,79 @@ +/* + * QEMU S390x floating interrupt controller (flic) + * + * Copyright 2014 IBM Corp. + * Author(s): Jens Freimann <jfrei@linux.vnet.ibm.com> + *            Cornelia Huck <cornelia.huck@de.ibm.com> + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at + * your option) any later version. See the COPYING file in the top-level + * directory. + */ + +#ifndef __HW_S390_FLIC_H +#define __HW_S390_FLIC_H + +#include "hw/sysbus.h" +#include "hw/s390x/adapter.h" +#include "hw/virtio/virtio.h" + +#define ADAPTER_ROUTES_MAX_GSI 64 +#define VIRTIO_CCW_QUEUE_MAX ADAPTER_ROUTES_MAX_GSI + +typedef struct AdapterRoutes { +    AdapterInfo adapter; +    int num_routes; +    int gsi[ADAPTER_ROUTES_MAX_GSI]; +} AdapterRoutes; + +#define TYPE_S390_FLIC_COMMON "s390-flic" +#define S390_FLIC_COMMON(obj) \ +    OBJECT_CHECK(S390FLICState, (obj), TYPE_S390_FLIC_COMMON) + +typedef struct S390FLICState { +    SysBusDevice parent_obj; + +} S390FLICState; + +#define S390_FLIC_COMMON_CLASS(klass) \ +    OBJECT_CLASS_CHECK(S390FLICStateClass, (klass), TYPE_S390_FLIC_COMMON) +#define S390_FLIC_COMMON_GET_CLASS(obj) \ +    OBJECT_GET_CLASS(S390FLICStateClass, (obj), TYPE_S390_FLIC_COMMON) + +typedef struct S390FLICStateClass { +    DeviceClass parent_class; + +    int (*register_io_adapter)(S390FLICState *fs, uint32_t id, uint8_t isc, +                               bool swap, bool maskable); +    int (*io_adapter_map)(S390FLICState *fs, uint32_t id, uint64_t map_addr, +                          bool do_map); +    int (*add_adapter_routes)(S390FLICState *fs, AdapterRoutes *routes); +    void (*release_adapter_routes)(S390FLICState *fs, AdapterRoutes *routes); +} S390FLICStateClass; + +#define TYPE_KVM_S390_FLIC "s390-flic-kvm" +#define KVM_S390_FLIC(obj) \ +    OBJECT_CHECK(KVMS390FLICState, (obj), TYPE_KVM_S390_FLIC) + +#define TYPE_QEMU_S390_FLIC "s390-flic-qemu" +#define QEMU_S390_FLIC(obj) \ +    OBJECT_CHECK(QEMUS390FLICState, (obj), TYPE_QEMU_S390_FLIC) + +typedef struct QEMUS390FLICState { +    S390FLICState parent_obj; +} QEMUS390FLICState; + +void s390_flic_init(void); + +S390FLICState *s390_get_flic(void); + +#ifdef CONFIG_KVM +DeviceState *s390_flic_kvm_create(void); +#else +static inline DeviceState *s390_flic_kvm_create(void) +{ +    return NULL; +} +#endif + +#endif /* __HW_S390_FLIC_H */ diff --git a/include/hw/s390x/sclp.h b/include/hw/s390x/sclp.h new file mode 100644 index 00000000..e8a64e25 --- /dev/null +++ b/include/hw/s390x/sclp.h @@ -0,0 +1,195 @@ +/* + * SCLP Support + * + * Copyright IBM, Corp. 2012 + * + * Authors: + *  Christian Borntraeger <borntraeger@de.ibm.com> + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at your + * option) any later version.  See the COPYING file in the top-level directory. + * + */ + +#ifndef HW_S390_SCLP_H +#define HW_S390_SCLP_H + +#include <hw/sysbus.h> +#include <hw/qdev.h> + +#define SCLP_CMD_CODE_MASK                      0xffff00ff + +/* SCLP command codes */ +#define SCLP_CMDW_READ_SCP_INFO                 0x00020001 +#define SCLP_CMDW_READ_SCP_INFO_FORCED          0x00120001 +#define SCLP_READ_STORAGE_ELEMENT_INFO          0x00040001 +#define SCLP_ATTACH_STORAGE_ELEMENT             0x00080001 +#define SCLP_ASSIGN_STORAGE                     0x000D0001 +#define SCLP_UNASSIGN_STORAGE                   0x000C0001 +#define SCLP_CMD_READ_EVENT_DATA                0x00770005 +#define SCLP_CMD_WRITE_EVENT_DATA               0x00760005 +#define SCLP_CMD_WRITE_EVENT_MASK               0x00780005 + +/* SCLP Memory hotplug codes */ +#define SCLP_FC_ASSIGN_ATTACH_READ_STOR         0xE00000000000ULL +#define SCLP_STARTING_SUBINCREMENT_ID           0x10001 +#define SCLP_INCREMENT_UNIT                     0x10000 +#define MAX_AVAIL_SLOTS                         32 +#define MAX_STORAGE_INCREMENTS                  1020 + +/* CPU hotplug SCLP codes */ +#define SCLP_HAS_CPU_INFO                       0x0C00000000000000ULL +#define SCLP_CMDW_READ_CPU_INFO                 0x00010001 +#define SCLP_CMDW_CONFIGURE_CPU                 0x00110001 +#define SCLP_CMDW_DECONFIGURE_CPU               0x00100001 + +/* SCLP PCI codes */ +#define SCLP_HAS_PCI_RECONFIG                   0x0000000040000000ULL +#define SCLP_CMDW_CONFIGURE_PCI                 0x001a0001 +#define SCLP_CMDW_DECONFIGURE_PCI               0x001b0001 +#define SCLP_RECONFIG_PCI_ATPYE                 2 + +/* SCLP response codes */ +#define SCLP_RC_NORMAL_READ_COMPLETION          0x0010 +#define SCLP_RC_NORMAL_COMPLETION               0x0020 +#define SCLP_RC_SCCB_BOUNDARY_VIOLATION         0x0100 +#define SCLP_RC_NO_ACTION_REQUIRED              0x0120 +#define SCLP_RC_INVALID_SCLP_COMMAND            0x01f0 +#define SCLP_RC_CONTAINED_EQUIPMENT_CHECK       0x0340 +#define SCLP_RC_INSUFFICIENT_SCCB_LENGTH        0x0300 +#define SCLP_RC_STANDBY_READ_COMPLETION         0x0410 +#define SCLP_RC_ADAPTER_ID_NOT_RECOGNIZED       0x09f0 +#define SCLP_RC_INVALID_FUNCTION                0x40f0 +#define SCLP_RC_NO_EVENT_BUFFERS_STORED         0x60f0 +#define SCLP_RC_INVALID_SELECTION_MASK          0x70f0 +#define SCLP_RC_INCONSISTENT_LENGTHS            0x72f0 +#define SCLP_RC_EVENT_BUFFER_SYNTAX_ERROR       0x73f0 +#define SCLP_RC_INVALID_MASK_LENGTH             0x74f0 + + +/* Service Call Control Block (SCCB) and its elements */ + +#define SCCB_SIZE 4096 + +#define SCLP_VARIABLE_LENGTH_RESPONSE           0x80 +#define SCLP_EVENT_BUFFER_ACCEPTED              0x80 + +#define SCLP_FC_NORMAL_WRITE                    0 + +/* + * Normally packed structures are not the right thing to do, since all code + * must take care of endianness. We cannot use ldl_phys and friends for two + * reasons, though: + * - some of the embedded structures below the SCCB can appear multiple times + *   at different locations, so there is no fixed offset + * - we work on a private copy of the SCCB, since there are several length + *   fields, that would cause a security nightmare if we allow the guest to + *   alter the structure while we parse it. We cannot use ldl_p and friends + *   either without doing pointer arithmetics + * So we have to double check that all users of sclp data structures use the + * right endianness wrappers. + */ +typedef struct SCCBHeader { +    uint16_t length; +    uint8_t function_code; +    uint8_t control_mask[3]; +    uint16_t response_code; +} QEMU_PACKED SCCBHeader; + +#define SCCB_DATA_LEN (SCCB_SIZE - sizeof(SCCBHeader)) + +/* CPU information */ +typedef struct CPUEntry { +    uint8_t address; +    uint8_t reserved0[13]; +    uint8_t type; +    uint8_t reserved1; +} QEMU_PACKED CPUEntry; + +typedef struct ReadInfo { +    SCCBHeader h; +    uint16_t rnmax; +    uint8_t rnsize; +    uint8_t  _reserved1[16 - 11];       /* 11-15 */ +    uint16_t entries_cpu;               /* 16-17 */ +    uint16_t offset_cpu;                /* 18-19 */ +    uint8_t  _reserved2[24 - 20];       /* 20-23 */ +    uint8_t  loadparm[8];               /* 24-31 */ +    uint8_t  _reserved3[48 - 32];       /* 32-47 */ +    uint64_t facilities;                /* 48-55 */ +    uint8_t  _reserved0[100 - 56]; +    uint32_t rnsize2; +    uint64_t rnmax2; +    uint8_t  _reserved4[120-112];       /* 112-119 */ +    uint16_t highest_cpu; +    uint8_t  _reserved5[128 - 122];     /* 122-127 */ +    struct CPUEntry entries[0]; +} QEMU_PACKED ReadInfo; + +typedef struct ReadCpuInfo { +    SCCBHeader h; +    uint16_t nr_configured;         /* 8-9 */ +    uint16_t offset_configured;     /* 10-11 */ +    uint16_t nr_standby;            /* 12-13 */ +    uint16_t offset_standby;        /* 14-15 */ +    uint8_t reserved0[24-16];       /* 16-23 */ +    struct CPUEntry entries[0]; +} QEMU_PACKED ReadCpuInfo; + +typedef struct ReadStorageElementInfo { +    SCCBHeader h; +    uint16_t max_id; +    uint16_t assigned; +    uint16_t standby; +    uint8_t _reserved0[16 - 14]; /* 14-15 */ +    uint32_t entries[0]; +} QEMU_PACKED ReadStorageElementInfo; + +typedef struct AttachStorageElement { +    SCCBHeader h; +    uint8_t _reserved0[10 - 8];  /* 8-9 */ +    uint16_t assigned; +    uint8_t _reserved1[16 - 12]; /* 12-15 */ +    uint32_t entries[0]; +} QEMU_PACKED AttachStorageElement; + +typedef struct AssignStorage { +    SCCBHeader h; +    uint16_t rn; +} QEMU_PACKED AssignStorage; + +typedef struct SCCB { +    SCCBHeader h; +    char data[SCCB_DATA_LEN]; + } QEMU_PACKED SCCB; + +typedef struct sclpMemoryHotplugDev sclpMemoryHotplugDev; + +#define TYPE_SCLP_MEMORY_HOTPLUG_DEV "sclp-memory-hotplug-dev" +#define SCLP_MEMORY_HOTPLUG_DEV(obj) \ +  OBJECT_CHECK(sclpMemoryHotplugDev, (obj), TYPE_SCLP_MEMORY_HOTPLUG_DEV) + +struct sclpMemoryHotplugDev { +    SysBusDevice parent; +    ram_addr_t standby_mem_size; +    ram_addr_t padded_ram_size; +    ram_addr_t pad_size; +    ram_addr_t standby_subregion_size; +    ram_addr_t rzm; +    int increment_size; +    char *standby_state_map; +}; + +static inline int sccb_data_len(SCCB *sccb) +{ +    return be16_to_cpu(sccb->h.length) - sizeof(sccb->h); +} + + +void s390_sclp_init(void); +sclpMemoryHotplugDev *init_sclp_memory_hotplug_dev(void); +sclpMemoryHotplugDev *get_sclp_memory_hotplug_dev(void); +void sclp_service_interrupt(uint32_t sccb); +void raise_irq_cpu_hotplug(void); + +#endif diff --git a/include/hw/scsi/esp.h b/include/hw/scsi/esp.h new file mode 100644 index 00000000..6c795276 --- /dev/null +++ b/include/hw/scsi/esp.h @@ -0,0 +1,133 @@ +#ifndef QEMU_HW_ESP_H +#define QEMU_HW_ESP_H + +#include "hw/scsi/scsi.h" + +/* esp.c */ +#define ESP_MAX_DEVS 7 +typedef void (*ESPDMAMemoryReadWriteFunc)(void *opaque, uint8_t *buf, int len); +void esp_init(hwaddr espaddr, int it_shift, +              ESPDMAMemoryReadWriteFunc dma_memory_read, +              ESPDMAMemoryReadWriteFunc dma_memory_write, +              void *dma_opaque, qemu_irq irq, qemu_irq *reset, +              qemu_irq *dma_enable); + +#define ESP_REGS 16 +#define TI_BUFSZ 16 + +typedef struct ESPState ESPState; + +struct ESPState { +    uint8_t rregs[ESP_REGS]; +    uint8_t wregs[ESP_REGS]; +    qemu_irq irq; +    uint8_t chip_id; +    bool tchi_written; +    int32_t ti_size; +    uint32_t ti_rptr, ti_wptr; +    uint32_t status; +    uint32_t dma; +    uint8_t ti_buf[TI_BUFSZ]; +    SCSIBus bus; +    SCSIDevice *current_dev; +    SCSIRequest *current_req; +    uint8_t cmdbuf[TI_BUFSZ]; +    uint32_t cmdlen; +    uint32_t do_cmd; + +    /* The amount of data left in the current DMA transfer.  */ +    uint32_t dma_left; +    /* The size of the current DMA transfer.  Zero if no transfer is in +       progress.  */ +    uint32_t dma_counter; +    int dma_enabled; + +    uint32_t async_len; +    uint8_t *async_buf; + +    ESPDMAMemoryReadWriteFunc dma_memory_read; +    ESPDMAMemoryReadWriteFunc dma_memory_write; +    void *dma_opaque; +    void (*dma_cb)(ESPState *s); +}; + +#define ESP_TCLO   0x0 +#define ESP_TCMID  0x1 +#define ESP_FIFO   0x2 +#define ESP_CMD    0x3 +#define ESP_RSTAT  0x4 +#define ESP_WBUSID 0x4 +#define ESP_RINTR  0x5 +#define ESP_WSEL   0x5 +#define ESP_RSEQ   0x6 +#define ESP_WSYNTP 0x6 +#define ESP_RFLAGS 0x7 +#define ESP_WSYNO  0x7 +#define ESP_CFG1   0x8 +#define ESP_RRES1  0x9 +#define ESP_WCCF   0x9 +#define ESP_RRES2  0xa +#define ESP_WTEST  0xa +#define ESP_CFG2   0xb +#define ESP_CFG3   0xc +#define ESP_RES3   0xd +#define ESP_TCHI   0xe +#define ESP_RES4   0xf + +#define CMD_DMA 0x80 +#define CMD_CMD 0x7f + +#define CMD_NOP      0x00 +#define CMD_FLUSH    0x01 +#define CMD_RESET    0x02 +#define CMD_BUSRESET 0x03 +#define CMD_TI       0x10 +#define CMD_ICCS     0x11 +#define CMD_MSGACC   0x12 +#define CMD_PAD      0x18 +#define CMD_SATN     0x1a +#define CMD_RSTATN   0x1b +#define CMD_SEL      0x41 +#define CMD_SELATN   0x42 +#define CMD_SELATNS  0x43 +#define CMD_ENSEL    0x44 +#define CMD_DISSEL   0x45 + +#define STAT_DO 0x00 +#define STAT_DI 0x01 +#define STAT_CD 0x02 +#define STAT_ST 0x03 +#define STAT_MO 0x06 +#define STAT_MI 0x07 +#define STAT_PIO_MASK 0x06 + +#define STAT_TC 0x10 +#define STAT_PE 0x20 +#define STAT_GE 0x40 +#define STAT_INT 0x80 + +#define BUSID_DID 0x07 + +#define INTR_FC 0x08 +#define INTR_BS 0x10 +#define INTR_DC 0x20 +#define INTR_RST 0x80 + +#define SEQ_0 0x0 +#define SEQ_CD 0x4 + +#define CFG1_RESREPT 0x40 + +#define TCHI_FAS100A 0x4 +#define TCHI_AM53C974 0x12 + +void esp_dma_enable(ESPState *s, int irq, int level); +void esp_request_cancelled(SCSIRequest *req); +void esp_command_complete(SCSIRequest *req, uint32_t status, size_t resid); +void esp_transfer_data(SCSIRequest *req, uint32_t len); +void esp_hard_reset(ESPState *s); +uint64_t esp_reg_read(ESPState *s, uint32_t saddr); +void esp_reg_write(ESPState *s, uint32_t saddr, uint64_t val); +extern const VMStateDescription vmstate_esp; + +#endif diff --git a/include/hw/scsi/scsi.h b/include/hw/scsi/scsi.h new file mode 100644 index 00000000..cdaf0f8e --- /dev/null +++ b/include/hw/scsi/scsi.h @@ -0,0 +1,281 @@ +#ifndef QEMU_HW_SCSI_H +#define QEMU_HW_SCSI_H + +#include "hw/qdev.h" +#include "qemu/typedefs.h" +#include "hw/block/block.h" +#include "sysemu/sysemu.h" +#include "qemu/notify.h" + +#define MAX_SCSI_DEVS	255 + +#define SCSI_CMD_BUF_SIZE     16 +#define SCSI_SENSE_LEN      18 +#define SCSI_INQUIRY_LEN    36 + +typedef struct SCSIBus SCSIBus; +typedef struct SCSIBusInfo SCSIBusInfo; +typedef struct SCSICommand SCSICommand; +typedef struct SCSIDevice SCSIDevice; +typedef struct SCSIRequest SCSIRequest; +typedef struct SCSIReqOps SCSIReqOps; + +enum SCSIXferMode { +    SCSI_XFER_NONE,      /*  TEST_UNIT_READY, ...            */ +    SCSI_XFER_FROM_DEV,  /*  READ, INQUIRY, MODE_SENSE, ...  */ +    SCSI_XFER_TO_DEV,    /*  WRITE, MODE_SELECT, ...         */ +}; + +typedef struct SCSISense { +    uint8_t key; +    uint8_t asc; +    uint8_t ascq; +} SCSISense; + +#define SCSI_SENSE_BUF_SIZE_OLD 96 +#define SCSI_SENSE_BUF_SIZE 252 + +struct SCSICommand { +    uint8_t buf[SCSI_CMD_BUF_SIZE]; +    int len; +    size_t xfer; +    uint64_t lba; +    enum SCSIXferMode mode; +}; + +struct SCSIRequest { +    SCSIBus           *bus; +    SCSIDevice        *dev; +    const SCSIReqOps  *ops; +    uint32_t          refcount; +    uint32_t          tag; +    uint32_t          lun; +    uint32_t          status; +    void              *hba_private; +    size_t            resid; +    SCSICommand       cmd; +    NotifierList      cancel_notifiers; + +    /* Note: +     * - fields before sense are initialized by scsi_req_alloc; +     * - sense[] is uninitialized; +     * - fields after sense are memset to 0 by scsi_req_alloc. +     * */ + +    uint8_t           sense[SCSI_SENSE_BUF_SIZE]; +    uint32_t          sense_len; +    bool              enqueued; +    bool              io_canceled; +    bool              retry; +    bool              dma_started; +    BlockAIOCB        *aiocb; +    QEMUSGList        *sg; +    QTAILQ_ENTRY(SCSIRequest) next; +}; + +#define TYPE_SCSI_DEVICE "scsi-device" +#define SCSI_DEVICE(obj) \ +     OBJECT_CHECK(SCSIDevice, (obj), TYPE_SCSI_DEVICE) +#define SCSI_DEVICE_CLASS(klass) \ +     OBJECT_CLASS_CHECK(SCSIDeviceClass, (klass), TYPE_SCSI_DEVICE) +#define SCSI_DEVICE_GET_CLASS(obj) \ +     OBJECT_GET_CLASS(SCSIDeviceClass, (obj), TYPE_SCSI_DEVICE) + +typedef struct SCSIDeviceClass { +    DeviceClass parent_class; +    void (*realize)(SCSIDevice *dev, Error **errp); +    int (*parse_cdb)(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf, +                     void *hba_private); +    SCSIRequest *(*alloc_req)(SCSIDevice *s, uint32_t tag, uint32_t lun, +                              uint8_t *buf, void *hba_private); +    void (*unit_attention_reported)(SCSIDevice *s); +} SCSIDeviceClass; + +struct SCSIDevice +{ +    DeviceState qdev; +    VMChangeStateEntry *vmsentry; +    QEMUBH *bh; +    uint32_t id; +    BlockConf conf; +    SCSISense unit_attention; +    bool sense_is_ua; +    uint8_t sense[SCSI_SENSE_BUF_SIZE]; +    uint32_t sense_len; +    QTAILQ_HEAD(, SCSIRequest) requests; +    uint32_t channel; +    uint32_t lun; +    int blocksize; +    int type; +    uint64_t max_lba; +}; + +extern const VMStateDescription vmstate_scsi_device; + +#define VMSTATE_SCSI_DEVICE(_field, _state) {                        \ +    .name       = (stringify(_field)),                               \ +    .size       = sizeof(SCSIDevice),                                \ +    .vmsd       = &vmstate_scsi_device,                              \ +    .flags      = VMS_STRUCT,                                        \ +    .offset     = vmstate_offset_value(_state, _field, SCSIDevice),  \ +} + +/* cdrom.c */ +int cdrom_read_toc(int nb_sectors, uint8_t *buf, int msf, int start_track); +int cdrom_read_toc_raw(int nb_sectors, uint8_t *buf, int msf, int session_num); + +/* scsi-bus.c */ +struct SCSIReqOps { +    size_t size; +    void (*free_req)(SCSIRequest *req); +    int32_t (*send_command)(SCSIRequest *req, uint8_t *buf); +    void (*read_data)(SCSIRequest *req); +    void (*write_data)(SCSIRequest *req); +    uint8_t *(*get_buf)(SCSIRequest *req); + +    void (*save_request)(QEMUFile *f, SCSIRequest *req); +    void (*load_request)(QEMUFile *f, SCSIRequest *req); +}; + +struct SCSIBusInfo { +    int tcq; +    int max_channel, max_target, max_lun; +    int (*parse_cdb)(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf, +                     void *hba_private); +    void (*transfer_data)(SCSIRequest *req, uint32_t arg); +    void (*complete)(SCSIRequest *req, uint32_t arg, size_t resid); +    void (*cancel)(SCSIRequest *req); +    void (*change)(SCSIBus *bus, SCSIDevice *dev, SCSISense sense); +    QEMUSGList *(*get_sg_list)(SCSIRequest *req); + +    void (*save_request)(QEMUFile *f, SCSIRequest *req); +    void *(*load_request)(QEMUFile *f, SCSIRequest *req); +    void (*free_request)(SCSIBus *bus, void *priv); +}; + +#define TYPE_SCSI_BUS "SCSI" +#define SCSI_BUS(obj) OBJECT_CHECK(SCSIBus, (obj), TYPE_SCSI_BUS) + +struct SCSIBus { +    BusState qbus; +    int busnr; + +    SCSISense unit_attention; +    const SCSIBusInfo *info; +}; + +void scsi_bus_new(SCSIBus *bus, size_t bus_size, DeviceState *host, +                  const SCSIBusInfo *info, const char *bus_name); + +static inline SCSIBus *scsi_bus_from_device(SCSIDevice *d) +{ +    return DO_UPCAST(SCSIBus, qbus, d->qdev.parent_bus); +} + +SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockBackend *blk, +                                      int unit, bool removable, int bootindex, +                                      const char *serial, Error **errp); +void scsi_bus_legacy_handle_cmdline(SCSIBus *bus, Error **errp); + +/* + * Predefined sense codes + */ + +/* No sense data available */ +extern const struct SCSISense sense_code_NO_SENSE; +/* LUN not ready, Manual intervention required */ +extern const struct SCSISense sense_code_LUN_NOT_READY; +/* LUN not ready, Medium not present */ +extern const struct SCSISense sense_code_NO_MEDIUM; +/* LUN not ready, medium removal prevented */ +extern const struct SCSISense sense_code_NOT_READY_REMOVAL_PREVENTED; +/* Hardware error, internal target failure */ +extern const struct SCSISense sense_code_TARGET_FAILURE; +/* Illegal request, invalid command operation code */ +extern const struct SCSISense sense_code_INVALID_OPCODE; +/* Illegal request, LBA out of range */ +extern const struct SCSISense sense_code_LBA_OUT_OF_RANGE; +/* Illegal request, Invalid field in CDB */ +extern const struct SCSISense sense_code_INVALID_FIELD; +/* Illegal request, Invalid field in parameter list */ +extern const struct SCSISense sense_code_INVALID_PARAM; +/* Illegal request, Parameter list length error */ +extern const struct SCSISense sense_code_INVALID_PARAM_LEN; +/* Illegal request, LUN not supported */ +extern const struct SCSISense sense_code_LUN_NOT_SUPPORTED; +/* Illegal request, Saving parameters not supported */ +extern const struct SCSISense sense_code_SAVING_PARAMS_NOT_SUPPORTED; +/* Illegal request, Incompatible format */ +extern const struct SCSISense sense_code_INCOMPATIBLE_FORMAT; +/* Illegal request, medium removal prevented */ +extern const struct SCSISense sense_code_ILLEGAL_REQ_REMOVAL_PREVENTED; +/* Illegal request, Invalid Transfer Tag */ +extern const struct SCSISense sense_code_INVALID_TAG; +/* Command aborted, I/O process terminated */ +extern const struct SCSISense sense_code_IO_ERROR; +/* Command aborted, I_T Nexus loss occurred */ +extern const struct SCSISense sense_code_I_T_NEXUS_LOSS; +/* Command aborted, Logical Unit failure */ +extern const struct SCSISense sense_code_LUN_FAILURE; +/* Command aborted, Overlapped Commands Attempted */ +extern const struct SCSISense sense_code_OVERLAPPED_COMMANDS; +/* LUN not ready, Capacity data has changed */ +extern const struct SCSISense sense_code_CAPACITY_CHANGED; +/* LUN not ready, Medium not present */ +extern const struct SCSISense sense_code_UNIT_ATTENTION_NO_MEDIUM; +/* Unit attention, Power on, reset or bus device reset occurred */ +extern const struct SCSISense sense_code_RESET; +/* Unit attention, Medium may have changed*/ +extern const struct SCSISense sense_code_MEDIUM_CHANGED; +/* Unit attention, Reported LUNs data has changed */ +extern const struct SCSISense sense_code_REPORTED_LUNS_CHANGED; +/* Unit attention, Device internal reset */ +extern const struct SCSISense sense_code_DEVICE_INTERNAL_RESET; +/* Data Protection, Write Protected */ +extern const struct SCSISense sense_code_WRITE_PROTECTED; +/* Data Protection, Space Allocation Failed Write Protect */ +extern const struct SCSISense sense_code_SPACE_ALLOC_FAILED; + +#define SENSE_CODE(x) sense_code_ ## x + +uint32_t scsi_data_cdb_xfer(uint8_t *buf); +uint32_t scsi_cdb_xfer(uint8_t *buf); +int scsi_cdb_length(uint8_t *buf); +int scsi_sense_valid(SCSISense sense); +int scsi_build_sense(uint8_t *in_buf, int in_len, +                     uint8_t *buf, int len, bool fixed); + +SCSIRequest *scsi_req_alloc(const SCSIReqOps *reqops, SCSIDevice *d, +                            uint32_t tag, uint32_t lun, void *hba_private); +SCSIRequest *scsi_req_new(SCSIDevice *d, uint32_t tag, uint32_t lun, +                          uint8_t *buf, void *hba_private); +int32_t scsi_req_enqueue(SCSIRequest *req); +void scsi_req_free(SCSIRequest *req); +SCSIRequest *scsi_req_ref(SCSIRequest *req); +void scsi_req_unref(SCSIRequest *req); + +int scsi_bus_parse_cdb(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf, +                       void *hba_private); +int scsi_req_parse_cdb(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf); +void scsi_req_build_sense(SCSIRequest *req, SCSISense sense); +void scsi_req_print(SCSIRequest *req); +void scsi_req_continue(SCSIRequest *req); +void scsi_req_data(SCSIRequest *req, int len); +void scsi_req_complete(SCSIRequest *req, int status); +uint8_t *scsi_req_get_buf(SCSIRequest *req); +int scsi_req_get_sense(SCSIRequest *req, uint8_t *buf, int len); +void scsi_req_cancel_complete(SCSIRequest *req); +void scsi_req_cancel(SCSIRequest *req); +void scsi_req_cancel_async(SCSIRequest *req, Notifier *notifier); +void scsi_req_retry(SCSIRequest *req); +void scsi_device_purge_requests(SCSIDevice *sdev, SCSISense sense); +void scsi_device_set_ua(SCSIDevice *sdev, SCSISense sense); +void scsi_device_report_change(SCSIDevice *dev, SCSISense sense); +void scsi_device_unit_attention_reported(SCSIDevice *dev); +int scsi_device_get_sense(SCSIDevice *dev, uint8_t *buf, int len, bool fixed); +SCSIDevice *scsi_device_find(SCSIBus *bus, int channel, int target, int lun); + +/* scsi-generic.c. */ +extern const SCSIReqOps scsi_generic_req_ops; + +#endif diff --git a/include/hw/sd.h b/include/hw/sd.h new file mode 100644 index 00000000..79adb5bb --- /dev/null +++ b/include/hw/sd.h @@ -0,0 +1,80 @@ +/* + * SD Memory Card emulation.  Mostly correct for MMC too. + * + * Copyright (c) 2006 Andrzej Zaborowski  <balrog@zabor.org> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + *    notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + *    notice, this list of conditions and the following disclaimer in + *    the documentation and/or other materials provided with the + *    distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef __hw_sd_h +#define __hw_sd_h		1 + +#define OUT_OF_RANGE		(1 << 31) +#define ADDRESS_ERROR		(1 << 30) +#define BLOCK_LEN_ERROR		(1 << 29) +#define ERASE_SEQ_ERROR		(1 << 28) +#define ERASE_PARAM		(1 << 27) +#define WP_VIOLATION		(1 << 26) +#define CARD_IS_LOCKED		(1 << 25) +#define LOCK_UNLOCK_FAILED	(1 << 24) +#define COM_CRC_ERROR		(1 << 23) +#define ILLEGAL_COMMAND		(1 << 22) +#define CARD_ECC_FAILED		(1 << 21) +#define CC_ERROR		(1 << 20) +#define SD_ERROR		(1 << 19) +#define CID_CSD_OVERWRITE	(1 << 16) +#define WP_ERASE_SKIP		(1 << 15) +#define CARD_ECC_DISABLED	(1 << 14) +#define ERASE_RESET		(1 << 13) +#define CURRENT_STATE		(7 << 9) +#define READY_FOR_DATA		(1 << 8) +#define APP_CMD			(1 << 5) +#define AKE_SEQ_ERROR		(1 << 3) +#define OCR_CCS_BITN        30 + +typedef enum { +    sd_none = -1, +    sd_bc = 0,	/* broadcast -- no response */ +    sd_bcr,	/* broadcast with response */ +    sd_ac,	/* addressed -- no data transfer */ +    sd_adtc,	/* addressed with data transfer */ +} sd_cmd_type_t; + +typedef struct { +    uint8_t cmd; +    uint32_t arg; +    uint8_t crc; +} SDRequest; + +typedef struct SDState SDState; + +SDState *sd_init(BlockBackend *bs, bool is_spi); +int sd_do_command(SDState *sd, SDRequest *req, +                  uint8_t *response); +void sd_write_data(SDState *sd, uint8_t value); +uint8_t sd_read_data(SDState *sd); +void sd_set_cb(SDState *sd, qemu_irq readonly, qemu_irq insert); +bool sd_data_ready(SDState *sd); +void sd_enable(SDState *sd, bool enable); + +#endif	/* __hw_sd_h */ diff --git a/include/hw/sh4/sh.h b/include/hw/sh4/sh.h new file mode 100644 index 00000000..e61de9ac --- /dev/null +++ b/include/hw/sh4/sh.h @@ -0,0 +1,57 @@ +#ifndef QEMU_SH_H +#define QEMU_SH_H +/* Definitions for SH board emulation.  */ + +#include "hw/sh4/sh_intc.h" + +#define A7ADDR(x) ((x) & 0x1fffffff) +#define P4ADDR(x) ((x) | 0xe0000000) + +/* sh7750.c */ +struct SH7750State; +struct MemoryRegion; + +struct SH7750State *sh7750_init(SuperHCPU *cpu, struct MemoryRegion *sysmem); + +typedef struct { +    /* The callback will be triggered if any of the designated lines change */ +    uint16_t portamask_trigger; +    uint16_t portbmask_trigger; +    /* Return 0 if no action was taken */ +    int (*port_change_cb) (uint16_t porta, uint16_t portb, +			   uint16_t * periph_pdtra, +			   uint16_t * periph_portdira, +			   uint16_t * periph_pdtrb, +			   uint16_t * periph_portdirb); +} sh7750_io_device; + +int sh7750_register_io_device(struct SH7750State *s, +			      sh7750_io_device * device); +/* sh_timer.c */ +#define TMU012_FEAT_TOCR   (1 << 0) +#define TMU012_FEAT_3CHAN  (1 << 1) +#define TMU012_FEAT_EXTCLK (1 << 2) +void tmu012_init(struct MemoryRegion *sysmem, hwaddr base, +                 int feat, uint32_t freq, +		 qemu_irq ch0_irq, qemu_irq ch1_irq, +		 qemu_irq ch2_irq0, qemu_irq ch2_irq1); + + +/* sh_serial.c */ +#define SH_SERIAL_FEAT_SCIF (1 << 0) +void sh_serial_init(MemoryRegion *sysmem, +                    hwaddr base, int feat, +		     uint32_t freq, CharDriverState *chr, +		     qemu_irq eri_source, +		     qemu_irq rxi_source, +		     qemu_irq txi_source, +		     qemu_irq tei_source, +		     qemu_irq bri_source); + +/* sh7750.c */ +qemu_irq sh7750_irl(struct SH7750State *s); + +/* tc58128.c */ +int tc58128_init(struct SH7750State *s, const char *zone1, const char *zone2); + +#endif diff --git a/include/hw/sh4/sh_intc.h b/include/hw/sh4/sh_intc.h new file mode 100644 index 00000000..b7ddcb09 --- /dev/null +++ b/include/hw/sh4/sh_intc.h @@ -0,0 +1,83 @@ +#ifndef __SH_INTC_H__ +#define __SH_INTC_H__ + +#include "qemu-common.h" +#include "hw/irq.h" +#include "exec/address-spaces.h" + +typedef unsigned char intc_enum; + +struct intc_vect { +    intc_enum enum_id; +    unsigned short vect; +}; + +#define INTC_VECT(enum_id, vect) { enum_id, vect } + +struct intc_group { +    intc_enum enum_id; +    intc_enum enum_ids[32]; +}; + +#define INTC_GROUP(enum_id, ...) { enum_id, {  __VA_ARGS__ } } + +struct intc_mask_reg { +    unsigned long set_reg, clr_reg, reg_width; +    intc_enum enum_ids[32]; +    unsigned long value; +}; + +struct intc_prio_reg { +    unsigned long set_reg, clr_reg, reg_width, field_width; +    intc_enum enum_ids[16]; +    unsigned long value; +}; + +#define _INTC_ARRAY(a) a, ARRAY_SIZE(a) + +struct intc_source { +    unsigned short vect; +    intc_enum next_enum_id; + +    int asserted; /* emulates the interrupt signal line from device to intc */ +    int enable_count; +    int enable_max; +    int pending; /* emulates the result of signal and masking */ +    struct intc_desc *parent; +}; + +struct intc_desc { +    MemoryRegion iomem; +    MemoryRegion *iomem_aliases; +    qemu_irq *irqs; +    struct intc_source *sources; +    int nr_sources; +    struct intc_mask_reg *mask_regs; +    int nr_mask_regs; +    struct intc_prio_reg *prio_regs; +    int nr_prio_regs; +    int pending; /* number of interrupt sources that has pending set */ +}; + +int sh_intc_get_pending_vector(struct intc_desc *desc, int imask); +struct intc_source *sh_intc_source(struct intc_desc *desc, intc_enum id); +void sh_intc_toggle_source(struct intc_source *source, +			   int enable_adj, int assert_adj); + +void sh_intc_register_sources(struct intc_desc *desc, +			      struct intc_vect *vectors, +			      int nr_vectors, +			      struct intc_group *groups, +			      int nr_groups); + +int sh_intc_init(MemoryRegion *sysmem, +                 struct intc_desc *desc, +		 int nr_sources, +		 struct intc_mask_reg *mask_regs, +		 int nr_mask_regs, +		 struct intc_prio_reg *prio_regs, +		 int nr_prio_regs); + +void sh_intc_set_irl(void *opaque, int n, int level); + +#endif /* __SH_INTC_H__ */ diff --git a/include/hw/sparc/grlib.h b/include/hw/sparc/grlib.h new file mode 100644 index 00000000..9a0db7b4 --- /dev/null +++ b/include/hw/sparc/grlib.h @@ -0,0 +1,120 @@ +/* + * QEMU GRLIB Components + * + * Copyright (c) 2010-2011 AdaCore + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * 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 OTHER + * 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. + */ + +#ifndef _GRLIB_H_ +#define _GRLIB_H_ + +#include "hw/qdev.h" +#include "hw/sysbus.h" + +/* Emulation of GrLib device is base on the GRLIB IP Core User's Manual: + * http://www.gaisler.com/products/grlib/grip.pdf + */ + +/* IRQMP */ + +typedef void (*set_pil_in_fn) (void *opaque, uint32_t pil_in); + +void grlib_irqmp_set_irq(void *opaque, int irq, int level); + +void grlib_irqmp_ack(DeviceState *dev, int intno); + +static inline +DeviceState *grlib_irqmp_create(hwaddr   base, +                                CPUSPARCState            *env, +                                qemu_irq           **cpu_irqs, +                                uint32_t             nr_irqs, +                                set_pil_in_fn        set_pil_in) +{ +    DeviceState *dev; + +    assert(cpu_irqs != NULL); + +    dev = qdev_create(NULL, "grlib,irqmp"); +    qdev_prop_set_ptr(dev, "set_pil_in", set_pil_in); +    qdev_prop_set_ptr(dev, "set_pil_in_opaque", env); + +    qdev_init_nofail(dev); + +    env->irq_manager = dev; + +    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base); + +    *cpu_irqs = qemu_allocate_irqs(grlib_irqmp_set_irq, +                                   dev, +                                   nr_irqs); + +    return dev; +} + +/* GPTimer */ + +static inline +DeviceState *grlib_gptimer_create(hwaddr  base, +                                  uint32_t            nr_timers, +                                  uint32_t            freq, +                                  qemu_irq           *cpu_irqs, +                                  int                 base_irq) +{ +    DeviceState *dev; +    int i; + +    dev = qdev_create(NULL, "grlib,gptimer"); +    qdev_prop_set_uint32(dev, "nr-timers", nr_timers); +    qdev_prop_set_uint32(dev, "frequency", freq); +    qdev_prop_set_uint32(dev, "irq-line", base_irq); + +    qdev_init_nofail(dev); + +    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base); + +    for (i = 0; i < nr_timers; i++) { +        sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, cpu_irqs[base_irq + i]); +    } + +    return dev; +} + +/* APB UART */ + +static inline +DeviceState *grlib_apbuart_create(hwaddr  base, +                                  CharDriverState    *serial, +                                  qemu_irq            irq) +{ +    DeviceState *dev; + +    dev = qdev_create(NULL, "grlib,apbuart"); +    qdev_prop_set_chr(dev, "chrdev", serial); + +    qdev_init_nofail(dev); + +    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base); + +    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, irq); + +    return dev; +} + +#endif /* ! _GRLIB_H_ */ diff --git a/include/hw/sparc/sparc32_dma.h b/include/hw/sparc/sparc32_dma.h new file mode 100644 index 00000000..9497b13d --- /dev/null +++ b/include/hw/sparc/sparc32_dma.h @@ -0,0 +1,12 @@ +#ifndef SPARC32_DMA_H +#define SPARC32_DMA_H + +/* sparc32_dma.c */ +void ledma_memory_read(void *opaque, hwaddr addr, +                       uint8_t *buf, int len, int do_bswap); +void ledma_memory_write(void *opaque, hwaddr addr, +                        uint8_t *buf, int len, int do_bswap); +void espdma_memory_read(void *opaque, uint8_t *buf, int len); +void espdma_memory_write(void *opaque, uint8_t *buf, int len); + +#endif diff --git a/include/hw/sparc/sun4m.h b/include/hw/sparc/sun4m.h new file mode 100644 index 00000000..9c17425a --- /dev/null +++ b/include/hw/sparc/sun4m.h @@ -0,0 +1,38 @@ +#ifndef SUN4M_H +#define SUN4M_H + +#include "qemu-common.h" +#include "exec/hwaddr.h" +#include "qapi/qmp/types.h" + +/* Devices used by sparc32 system.  */ + +/* iommu.c */ +void sparc_iommu_memory_rw(void *opaque, hwaddr addr, +                                 uint8_t *buf, int len, int is_write); +static inline void sparc_iommu_memory_read(void *opaque, +                                           hwaddr addr, +                                           uint8_t *buf, int len) +{ +    sparc_iommu_memory_rw(opaque, addr, buf, len, 0); +} + +static inline void sparc_iommu_memory_write(void *opaque, +                                            hwaddr addr, +                                            uint8_t *buf, int len) +{ +    sparc_iommu_memory_rw(opaque, addr, buf, len, 1); +} + +/* slavio_intctl.c */ +void slavio_pic_info(Monitor *mon, DeviceState *dev); +void slavio_irq_info(Monitor *mon, DeviceState *dev); + +/* sun4m.c */ +void sun4m_hmp_info_pic(Monitor *mon, const QDict *qdict); +void sun4m_hmp_info_irq(Monitor *mon, const QDict *qdict); + +/* sparc32_dma.c */ +#include "hw/sparc/sparc32_dma.h" + +#endif diff --git a/include/hw/ssi.h b/include/hw/ssi.h new file mode 100644 index 00000000..df0f8385 --- /dev/null +++ b/include/hw/ssi.h @@ -0,0 +1,94 @@ +/* QEMU Synchronous Serial Interface support.  */ + +/* In principle SSI is a point-point interface.  As such the qemu +   implementation has a single slave device on a "bus". +   However it is fairly common for boards to have multiple slaves +   connected to a single master, and select devices with an external +   chip select.  This is implemented in qemu by having an explicit mux device. +   It is assumed that master and slave are both using the same transfer width. +   */ + +#ifndef QEMU_SSI_H +#define QEMU_SSI_H + +#include "hw/qdev.h" + +typedef struct SSISlave SSISlave; + +#define TYPE_SSI_SLAVE "ssi-slave" +#define SSI_SLAVE(obj) \ +     OBJECT_CHECK(SSISlave, (obj), TYPE_SSI_SLAVE) +#define SSI_SLAVE_CLASS(klass) \ +     OBJECT_CLASS_CHECK(SSISlaveClass, (klass), TYPE_SSI_SLAVE) +#define SSI_SLAVE_GET_CLASS(obj) \ +     OBJECT_GET_CLASS(SSISlaveClass, (obj), TYPE_SSI_SLAVE) + +#define SSI_GPIO_CS "ssi-gpio-cs" + +typedef enum { +    SSI_CS_NONE = 0, +    SSI_CS_LOW, +    SSI_CS_HIGH, +} SSICSMode; + +/* Slave devices.  */ +typedef struct SSISlaveClass { +    DeviceClass parent_class; + +    int (*init)(SSISlave *dev); + +    /* if you have standard or no CS behaviour, just override transfer. +     * This is called when the device cs is active (true by default). +     */ +    uint32_t (*transfer)(SSISlave *dev, uint32_t val); +    /* called when the CS line changes. Optional, devices only need to implement +     * this if they have side effects associated with the cs line (beyond +     * tristating the txrx lines). +     */ +    int (*set_cs)(SSISlave *dev, bool select); +    /* define whether or not CS exists and is active low/high */ +    SSICSMode cs_polarity; + +    /* if you have non-standard CS behaviour override this to take control +     * of the CS behaviour at the device level. transfer, set_cs, and +     * cs_polarity are unused if this is overwritten. Transfer_raw will +     * always be called for the device for every txrx access to the parent bus +     */ +    uint32_t (*transfer_raw)(SSISlave *dev, uint32_t val); +} SSISlaveClass; + +struct SSISlave { +    DeviceState parent_obj; + +    /* Chip select state */ +    bool cs; +}; + +#define FROM_SSI_SLAVE(type, dev) DO_UPCAST(type, ssidev, dev) + +extern const VMStateDescription vmstate_ssi_slave; + +#define VMSTATE_SSI_SLAVE(_field, _state) {                          \ +    .name       = (stringify(_field)),                               \ +    .size       = sizeof(SSISlave),                                  \ +    .vmsd       = &vmstate_ssi_slave,                                \ +    .flags      = VMS_STRUCT,                                        \ +    .offset     = vmstate_offset_value(_state, _field, SSISlave),    \ +} + +DeviceState *ssi_create_slave(SSIBus *bus, const char *name); +DeviceState *ssi_create_slave_no_init(SSIBus *bus, const char *name); + +/* Master interface.  */ +SSIBus *ssi_create_bus(DeviceState *parent, const char *name); + +uint32_t ssi_transfer(SSIBus *bus, uint32_t val); + +/* Automatically connect all children nodes a spi controller as slaves */ +void ssi_auto_connect_slaves(DeviceState *parent, qemu_irq *cs_lines, +                             SSIBus *bus); + +/* max111x.c */ +void max111x_set_input(DeviceState *dev, int line, uint8_t value); + +#endif diff --git a/include/hw/stream.h b/include/hw/stream.h new file mode 100644 index 00000000..30ccc562 --- /dev/null +++ b/include/hw/stream.h @@ -0,0 +1,57 @@ +#ifndef STREAM_H +#define STREAM_H 1 + +#include "qemu-common.h" +#include "qom/object.h" + +/* stream slave. Used until qdev provides a generic way.  */ +#define TYPE_STREAM_SLAVE "stream-slave" + +#define STREAM_SLAVE_CLASS(klass) \ +     OBJECT_CLASS_CHECK(StreamSlaveClass, (klass), TYPE_STREAM_SLAVE) +#define STREAM_SLAVE_GET_CLASS(obj) \ +    OBJECT_GET_CLASS(StreamSlaveClass, (obj), TYPE_STREAM_SLAVE) +#define STREAM_SLAVE(obj) \ +     INTERFACE_CHECK(StreamSlave, (obj), TYPE_STREAM_SLAVE) + +typedef struct StreamSlave { +    Object Parent; +} StreamSlave; + +typedef void (*StreamCanPushNotifyFn)(void *opaque); + +typedef struct StreamSlaveClass { +    InterfaceClass parent; +    /** +     * can push - determine if a stream slave is capable of accepting at least +     * one byte of data. Returns false if cannot accept. If not implemented, the +     * slave is assumed to always be capable of receiving. +     * @notify: Optional callback that the slave will call when the slave is +     * capable of receiving again. Only called if false is returned. +     * @notify_opaque: opaque data to pass to notify call. +     */ +    bool (*can_push)(StreamSlave *obj, StreamCanPushNotifyFn notify, +                     void *notify_opaque); +    /** +     * push - push data to a Stream slave. The number of bytes pushed is +     * returned. If the slave short returns, the master must wait before trying +     * again, the slave may continue to just return 0 waiting for the vm time to +     * advance. The can_push() function can be used to trap the point in time +     * where the slave is ready to receive again, otherwise polling on a QEMU +     * timer will work. +     * @obj: Stream slave to push to +     * @buf: Data to write +     * @len: Maximum number of bytes to write +     */ +    size_t (*push)(StreamSlave *obj, unsigned char *buf, size_t len); +} StreamSlaveClass; + +size_t +stream_push(StreamSlave *sink, uint8_t *buf, size_t len); + +bool +stream_can_push(StreamSlave *sink, StreamCanPushNotifyFn notify, +                void *notify_opaque); + + +#endif /* STREAM_H */ diff --git a/include/hw/sysbus.h b/include/hw/sysbus.h new file mode 100644 index 00000000..cc1dba49 --- /dev/null +++ b/include/hw/sysbus.h @@ -0,0 +1,121 @@ +#ifndef HW_SYSBUS_H +#define HW_SYSBUS_H 1 + +/* Devices attached directly to the main system bus.  */ + +#include "hw/qdev.h" +#include "exec/memory.h" + +#define QDEV_MAX_MMIO 32 +#define QDEV_MAX_PIO 32 + +#define TYPE_SYSTEM_BUS "System" +#define SYSTEM_BUS(obj) OBJECT_CHECK(BusState, (obj), TYPE_SYSTEM_BUS) + +typedef struct SysBusDevice SysBusDevice; + +#define TYPE_SYS_BUS_DEVICE "sys-bus-device" +#define SYS_BUS_DEVICE(obj) \ +     OBJECT_CHECK(SysBusDevice, (obj), TYPE_SYS_BUS_DEVICE) +#define SYS_BUS_DEVICE_CLASS(klass) \ +     OBJECT_CLASS_CHECK(SysBusDeviceClass, (klass), TYPE_SYS_BUS_DEVICE) +#define SYS_BUS_DEVICE_GET_CLASS(obj) \ +     OBJECT_GET_CLASS(SysBusDeviceClass, (obj), TYPE_SYS_BUS_DEVICE) + +/** + * SysBusDeviceClass: + * @init: Callback function invoked when the #DeviceState.realized property + * is changed to %true. Deprecated, new types inheriting directly from + * TYPE_SYS_BUS_DEVICE should use #DeviceClass.realize instead, new leaf + * types should consult their respective parent type. + * + * SysBusDeviceClass is not overriding #DeviceClass.realize, so derived + * classes overriding it are not required to invoke its implementation. + */ + +#define SYSBUS_DEVICE_GPIO_IRQ "sysbus-irq" + +typedef struct SysBusDeviceClass { +    /*< private >*/ +    DeviceClass parent_class; +    /*< public >*/ + +    int (*init)(SysBusDevice *dev); + +    /* +     * Let the sysbus device format its own non-PIO, non-MMIO unit address. +     * +     * Sometimes a class of SysBusDevices has neither MMIO nor PIO resources, +     * yet instances of it would like to distinguish themselves, in +     * OpenFirmware device paths, from other instances of the same class on the +     * sysbus. For that end we expose this callback. +     * +     * The implementation is not supposed to change *@dev, or incur other +     * observable change. +     * +     * The function returns a dynamically allocated string. On error, NULL +     * should be returned; the unit address portion of the OFW node will be +     * omitted then. (This is not considered a fatal error.) +     */ +    char *(*explicit_ofw_unit_address)(const SysBusDevice *dev); +    void (*connect_irq_notifier)(SysBusDevice *dev, qemu_irq irq); +} SysBusDeviceClass; + +struct SysBusDevice { +    /*< private >*/ +    DeviceState parent_obj; +    /*< public >*/ + +    int num_mmio; +    struct { +        hwaddr addr; +        MemoryRegion *memory; +    } mmio[QDEV_MAX_MMIO]; +    int num_pio; +    pio_addr_t pio[QDEV_MAX_PIO]; +}; + +typedef int FindSysbusDeviceFunc(SysBusDevice *sbdev, void *opaque); + +void sysbus_init_mmio(SysBusDevice *dev, MemoryRegion *memory); +MemoryRegion *sysbus_mmio_get_region(SysBusDevice *dev, int n); +void sysbus_init_irq(SysBusDevice *dev, qemu_irq *p); +void sysbus_pass_irq(SysBusDevice *dev, SysBusDevice *target); +void sysbus_init_ioports(SysBusDevice *dev, pio_addr_t ioport, pio_addr_t size); + + +bool sysbus_has_irq(SysBusDevice *dev, int n); +bool sysbus_has_mmio(SysBusDevice *dev, unsigned int n); +void sysbus_connect_irq(SysBusDevice *dev, int n, qemu_irq irq); +bool sysbus_is_irq_connected(SysBusDevice *dev, int n); +qemu_irq sysbus_get_connected_irq(SysBusDevice *dev, int n); +void sysbus_mmio_map(SysBusDevice *dev, int n, hwaddr addr); +void sysbus_mmio_map_overlap(SysBusDevice *dev, int n, hwaddr addr, +                             int priority); +void sysbus_add_io(SysBusDevice *dev, hwaddr addr, +                   MemoryRegion *mem); +MemoryRegion *sysbus_address_space(SysBusDevice *dev); + +/* Call func for every dynamically created sysbus device in the system */ +void foreach_dynamic_sysbus_device(FindSysbusDeviceFunc *func, void *opaque); + +/* Legacy helper function for creating devices.  */ +DeviceState *sysbus_create_varargs(const char *name, +                                 hwaddr addr, ...); +DeviceState *sysbus_try_create_varargs(const char *name, +                                       hwaddr addr, ...); +static inline DeviceState *sysbus_create_simple(const char *name, +                                              hwaddr addr, +                                              qemu_irq irq) +{ +    return sysbus_create_varargs(name, addr, irq, NULL); +} + +static inline DeviceState *sysbus_try_create_simple(const char *name, +                                                    hwaddr addr, +                                                    qemu_irq irq) +{ +    return sysbus_try_create_varargs(name, addr, irq, NULL); +} + +#endif /* !HW_SYSBUS_H */ diff --git a/include/hw/timer/a9gtimer.h b/include/hw/timer/a9gtimer.h new file mode 100644 index 00000000..98d8e0ae --- /dev/null +++ b/include/hw/timer/a9gtimer.h @@ -0,0 +1,97 @@ +/* + * Global peripheral timer block for ARM A9MP + * + * (C) 2013 Xilinx Inc. + * + * Written by François LEGAL + * Written by Peter Crosthwaite <peter.crosthwaite@xilinx.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef HW_TIMER_A9_GTIMER_H_H +#define HW_TIMER_A9_GTIMER_H_H + +#include "hw/sysbus.h" + +#define A9_GTIMER_MAX_CPUS 4 + +#define TYPE_A9_GTIMER "arm.cortex-a9-global-timer" +#define A9_GTIMER(obj) OBJECT_CHECK(A9GTimerState, (obj), TYPE_A9_GTIMER) + +#define R_COUNTER_LO                0x00 +#define R_COUNTER_HI                0x04 + +#define R_CONTROL                   0x08 +#define R_CONTROL_TIMER_ENABLE      (1 << 0) +#define R_CONTROL_COMP_ENABLE       (1 << 1) +#define R_CONTROL_IRQ_ENABLE        (1 << 2) +#define R_CONTROL_AUTO_INCREMENT    (1 << 3) +#define R_CONTROL_PRESCALER_SHIFT   8 +#define R_CONTROL_PRESCALER_LEN     8 +#define R_CONTROL_PRESCALER_MASK    (((1 << R_CONTROL_PRESCALER_LEN) - 1) << \ +                                     R_CONTROL_PRESCALER_SHIFT) + +#define R_CONTROL_BANKED            (R_CONTROL_COMP_ENABLE | \ +                                     R_CONTROL_IRQ_ENABLE | \ +                                     R_CONTROL_AUTO_INCREMENT) +#define R_CONTROL_NEEDS_SYNC        (R_CONTROL_TIMER_ENABLE | \ +                                     R_CONTROL_PRESCALER_MASK) + +#define R_INTERRUPT_STATUS          0x0C +#define R_COMPARATOR_LO             0x10 +#define R_COMPARATOR_HI             0x14 +#define R_AUTO_INCREMENT            0x18 + +typedef struct A9GTimerPerCPU A9GTimerPerCPU; +typedef struct A9GTimerState A9GTimerState; + +struct A9GTimerPerCPU { +    A9GTimerState *parent; + +    uint32_t control; /* only per cpu banked bits valid */ +    uint64_t compare; +    uint32_t status; +    uint32_t inc; + +    MemoryRegion iomem; +    qemu_irq irq; /* PPI interrupts */ +}; + +struct A9GTimerState { +    /*< private >*/ +    SysBusDevice parent_obj; +    /*< public >*/ + +    MemoryRegion iomem; +    /* static props */ +    uint32_t num_cpu; + +    QEMUTimer *timer; + +    uint64_t counter; /* current timer value */ + +    uint64_t ref_counter; +    uint64_t cpu_ref_time; /* the cpu time as of last update of ref_counter */ +    uint32_t control; /* only non per cpu banked bits valid */ + +    A9GTimerPerCPU per_cpu[A9_GTIMER_MAX_CPUS]; +}; + +typedef struct A9GTimerUpdate { +    uint64_t now; +    uint64_t new; +} A9GTimerUpdate; + +#endif /* #ifdef HW_TIMER_A9_GTIMER_H_H */ diff --git a/include/hw/timer/allwinner-a10-pit.h b/include/hw/timer/allwinner-a10-pit.h new file mode 100644 index 00000000..770bdc03 --- /dev/null +++ b/include/hw/timer/allwinner-a10-pit.h @@ -0,0 +1,67 @@ +#ifndef AW_A10_PIT_H +#define AW_A10_PIT_H + +#include "hw/ptimer.h" + +#define TYPE_AW_A10_PIT "allwinner-A10-timer" +#define AW_A10_PIT(obj) OBJECT_CHECK(AwA10PITState, (obj), TYPE_AW_A10_PIT) + +#define AW_A10_PIT_TIMER_NR    6 +#define AW_A10_PIT_TIMER_IRQ   0x1 +#define AW_A10_PIT_WDOG_IRQ    0x100 + +#define AW_A10_PIT_TIMER_IRQ_EN    0 +#define AW_A10_PIT_TIMER_IRQ_ST    0x4 + +#define AW_A10_PIT_TIMER_CONTROL   0x0 +#define AW_A10_PIT_TIMER_EN        0x1 +#define AW_A10_PIT_TIMER_RELOAD    0x2 +#define AW_A10_PIT_TIMER_MODE      0x80 + +#define AW_A10_PIT_TIMER_INTERVAL  0x4 +#define AW_A10_PIT_TIMER_COUNT     0x8 +#define AW_A10_PIT_WDOG_CONTROL    0x90 +#define AW_A10_PIT_WDOG_MODE       0x94 + +#define AW_A10_PIT_COUNT_CTL       0xa0 +#define AW_A10_PIT_COUNT_RL_EN     0x2 +#define AW_A10_PIT_COUNT_CLR_EN    0x1 +#define AW_A10_PIT_COUNT_LO        0xa4 +#define AW_A10_PIT_COUNT_HI        0xa8 + +#define AW_A10_PIT_TIMER_BASE      0x10 +#define AW_A10_PIT_TIMER_BASE_END  \ +    (AW_A10_PIT_TIMER_BASE * 6 + AW_A10_PIT_TIMER_COUNT) + +#define AW_A10_PIT_DEFAULT_CLOCK   0x4 + +typedef struct AwA10PITState AwA10PITState; + +typedef struct AwA10TimerContext { +    AwA10PITState *container; +    int index; +} AwA10TimerContext; + +struct AwA10PITState { +    /*< private >*/ +    SysBusDevice parent_obj; +    /*< public >*/ +    qemu_irq irq[AW_A10_PIT_TIMER_NR]; +    ptimer_state * timer[AW_A10_PIT_TIMER_NR]; +    AwA10TimerContext timer_context[AW_A10_PIT_TIMER_NR]; +    MemoryRegion iomem; +    uint32_t clk_freq[4]; + +    uint32_t irq_enable; +    uint32_t irq_status; +    uint32_t control[AW_A10_PIT_TIMER_NR]; +    uint32_t interval[AW_A10_PIT_TIMER_NR]; +    uint32_t count[AW_A10_PIT_TIMER_NR]; +    uint32_t watch_dog_mode; +    uint32_t watch_dog_control; +    uint32_t count_lo; +    uint32_t count_hi; +    uint32_t count_ctl; +}; + +#endif diff --git a/include/hw/timer/arm_mptimer.h b/include/hw/timer/arm_mptimer.h new file mode 100644 index 00000000..b34cba00 --- /dev/null +++ b/include/hw/timer/arm_mptimer.h @@ -0,0 +1,54 @@ +/* + * Private peripheral timer/watchdog blocks for ARM 11MPCore and A9MP + * + * Copyright (c) 2006-2007 CodeSourcery. + * Copyright (c) 2011 Linaro Limited + * Written by Paul Brook, Peter Maydell + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, see <http://www.gnu.org/licenses/>. + */ +#ifndef HW_TIMER_ARM_MPTIMER_H +#define HW_TIMER_ARM_MPTIMER_H + +#include "hw/sysbus.h" + +#define ARM_MPTIMER_MAX_CPUS 4 + +/* State of a single timer or watchdog block */ +typedef struct { +    uint32_t count; +    uint32_t load; +    uint32_t control; +    uint32_t status; +    int64_t tick; +    QEMUTimer *timer; +    qemu_irq irq; +    MemoryRegion iomem; +} TimerBlock; + +#define TYPE_ARM_MPTIMER "arm_mptimer" +#define ARM_MPTIMER(obj) \ +    OBJECT_CHECK(ARMMPTimerState, (obj), TYPE_ARM_MPTIMER) + +typedef struct { +    /*< private >*/ +    SysBusDevice parent_obj; +    /*< public >*/ + +    uint32_t num_cpu; +    TimerBlock timerblock[ARM_MPTIMER_MAX_CPUS]; +    MemoryRegion iomem; +} ARMMPTimerState; + +#endif diff --git a/include/hw/timer/digic-timer.h b/include/hw/timer/digic-timer.h new file mode 100644 index 00000000..ae913482 --- /dev/null +++ b/include/hw/timer/digic-timer.h @@ -0,0 +1,46 @@ +/* + * Canon DIGIC timer block declarations. + * + * Copyright (C) 2013 Antony Pavlov <antonynpavlov@gmail.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef HW_TIMER_DIGIC_TIMER_H +#define HW_TIMER_DIGIC_TIMER_H + +#include "hw/sysbus.h" +#include "qemu/typedefs.h" +#include "hw/ptimer.h" + +#define TYPE_DIGIC_TIMER "digic-timer" +#define DIGIC_TIMER(obj) OBJECT_CHECK(DigicTimerState, (obj), TYPE_DIGIC_TIMER) + +#define DIGIC_TIMER_CONTROL 0x00 +#define DIGIC_TIMER_CONTROL_RST 0x80000000 +#define DIGIC_TIMER_CONTROL_EN 0x00000001 +#define DIGIC_TIMER_RELVALUE 0x08 +#define DIGIC_TIMER_VALUE 0x0c + +typedef struct DigicTimerState { +    /*< private >*/ +    SysBusDevice parent_obj; +    /*< public >*/ + +    MemoryRegion iomem; +    ptimer_state *ptimer; + +    uint32_t control; +    uint32_t relvalue; +} DigicTimerState; + +#endif /* HW_TIMER_DIGIC_TIMER_H */ diff --git a/include/hw/timer/hpet.h b/include/hw/timer/hpet.h new file mode 100644 index 00000000..773953be --- /dev/null +++ b/include/hw/timer/hpet.h @@ -0,0 +1,84 @@ +/* + * QEMU Emulated HPET support + * + * Copyright IBM, Corp. 2008 + * + * Authors: + *  Beth Kon   <bkon@us.ibm.com> + * + * This work is licensed under the terms of the GNU GPL, version 2.  See + * the COPYING file in the top-level directory. + * + */ +#ifndef QEMU_HPET_EMUL_H +#define QEMU_HPET_EMUL_H + +#include "qom/object.h" + +#define HPET_BASE               0xfed00000 +#define HPET_CLK_PERIOD         10000000ULL /* 10000000 femtoseconds == 10ns*/ + +#define FS_PER_NS 1000000 +#define HPET_MIN_TIMERS         3 +#define HPET_MAX_TIMERS         32 + +#define HPET_NUM_IRQ_ROUTES     32 + +#define HPET_LEGACY_PIT_INT     0 +#define HPET_LEGACY_RTC_INT     1 + +#define HPET_CFG_ENABLE 0x001 +#define HPET_CFG_LEGACY 0x002 + +#define HPET_ID         0x000 +#define HPET_PERIOD     0x004 +#define HPET_CFG        0x010 +#define HPET_STATUS     0x020 +#define HPET_COUNTER    0x0f0 +#define HPET_TN_CFG     0x000 +#define HPET_TN_CMP     0x008 +#define HPET_TN_ROUTE   0x010 +#define HPET_CFG_WRITE_MASK  0x3 + +#define HPET_ID_NUM_TIM_SHIFT   8 +#define HPET_ID_NUM_TIM_MASK    0x1f00 + +#define HPET_TN_TYPE_LEVEL       0x002 +#define HPET_TN_ENABLE           0x004 +#define HPET_TN_PERIODIC         0x008 +#define HPET_TN_PERIODIC_CAP     0x010 +#define HPET_TN_SIZE_CAP         0x020 +#define HPET_TN_SETVAL           0x040 +#define HPET_TN_32BIT            0x100 +#define HPET_TN_INT_ROUTE_MASK  0x3e00 +#define HPET_TN_FSB_ENABLE      0x4000 +#define HPET_TN_FSB_CAP         0x8000 +#define HPET_TN_CFG_WRITE_MASK  0x7f4e +#define HPET_TN_INT_ROUTE_SHIFT      9 +#define HPET_TN_INT_ROUTE_CAP_SHIFT 32 +#define HPET_TN_CFG_BITS_READONLY_OR_RESERVED 0xffff80b1U + +struct hpet_fw_entry +{ +    uint32_t event_timer_block_id; +    uint64_t address; +    uint16_t min_tick; +    uint8_t page_prot; +} QEMU_PACKED; + +struct hpet_fw_config +{ +    uint8_t count; +    struct hpet_fw_entry hpet[8]; +} QEMU_PACKED; + +extern struct hpet_fw_config hpet_cfg; + +#define TYPE_HPET "hpet" + +static inline bool hpet_find(void) +{ +    return object_resolve_path_type("", TYPE_HPET, NULL); +} + +#endif diff --git a/include/hw/timer/i8254.h b/include/hw/timer/i8254.h new file mode 100644 index 00000000..43490334 --- /dev/null +++ b/include/hw/timer/i8254.h @@ -0,0 +1,75 @@ +/* + * QEMU 8253/8254 interval timer emulation + * + * Copyright (c) 2003-2004 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * 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 OTHER + * 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. + */ + +#ifndef HW_I8254_H +#define HW_I8254_H + +#include "hw/hw.h" +#include "hw/isa/isa.h" + +#define PIT_FREQ 1193182 + +typedef struct PITChannelInfo { +    int gate; +    int mode; +    int initial_count; +    int out; +} PITChannelInfo; + +#define TYPE_I8254 "isa-pit" +#define TYPE_KVM_I8254 "kvm-pit" + +static inline ISADevice *pit_init(ISABus *bus, int base, int isa_irq, +                                  qemu_irq alt_irq) +{ +    DeviceState *dev; +    ISADevice *d; + +    d = isa_create(bus, TYPE_I8254); +    dev = DEVICE(d); +    qdev_prop_set_uint32(dev, "iobase", base); +    qdev_init_nofail(dev); +    qdev_connect_gpio_out(dev, 0, +                          isa_irq >= 0 ? isa_get_irq(d, isa_irq) : alt_irq); + +    return d; +} + +static inline ISADevice *kvm_pit_init(ISABus *bus, int base) +{ +    DeviceState *dev; +    ISADevice *d; + +    d = isa_create(bus, TYPE_KVM_I8254); +    dev = DEVICE(d); +    qdev_prop_set_uint32(dev, "iobase", base); +    qdev_init_nofail(dev); + +    return d; +} + +void pit_set_gate(ISADevice *dev, int channel, int val); +void pit_get_channel_info(ISADevice *dev, int channel, PITChannelInfo *info); + +#endif /* !HW_I8254_H */ diff --git a/include/hw/timer/i8254_internal.h b/include/hw/timer/i8254_internal.h new file mode 100644 index 00000000..61a1bfbc --- /dev/null +++ b/include/hw/timer/i8254_internal.h @@ -0,0 +1,84 @@ +/* + * QEMU 8253/8254 - internal interfaces + * + * Copyright (c) 2011 Jan Kiszka, Siemens AG + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * 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 OTHER + * 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. + */ + +#ifndef QEMU_I8254_INTERNAL_H +#define QEMU_I8254_INTERNAL_H + +#include "hw/hw.h" +#include "hw/i386/pc.h" +#include "hw/isa/isa.h" + +typedef struct PITChannelState { +    int count; /* can be 65536 */ +    uint16_t latched_count; +    uint8_t count_latched; +    uint8_t status_latched; +    uint8_t status; +    uint8_t read_state; +    uint8_t write_state; +    uint8_t write_latch; +    uint8_t rw_mode; +    uint8_t mode; +    uint8_t bcd; /* not supported */ +    uint8_t gate; /* timer start */ +    int64_t count_load_time; +    /* irq handling */ +    int64_t next_transition_time; +    QEMUTimer *irq_timer; +    qemu_irq irq; +    uint32_t irq_disabled; +} PITChannelState; + +typedef struct PITCommonState { +    ISADevice dev; +    MemoryRegion ioports; +    uint32_t iobase; +    PITChannelState channels[3]; +} PITCommonState; + +#define TYPE_PIT_COMMON "pit-common" +#define PIT_COMMON(obj) \ +     OBJECT_CHECK(PITCommonState, (obj), TYPE_PIT_COMMON) +#define PIT_COMMON_CLASS(klass) \ +     OBJECT_CLASS_CHECK(PITCommonClass, (klass), TYPE_PIT_COMMON) +#define PIT_COMMON_GET_CLASS(obj) \ +     OBJECT_GET_CLASS(PITCommonClass, (obj), TYPE_PIT_COMMON) + +typedef struct PITCommonClass { +    ISADeviceClass parent_class; + +    void (*set_channel_gate)(PITCommonState *s, PITChannelState *sc, int val); +    void (*get_channel_info)(PITCommonState *s, PITChannelState *sc, +                             PITChannelInfo *info); +    void (*pre_save)(PITCommonState *s); +    void (*post_load)(PITCommonState *s); +} PITCommonClass; + +int pit_get_out(PITChannelState *s, int64_t current_time); +int64_t pit_get_next_transition_time(PITChannelState *s, int64_t current_time); +void pit_get_channel_info_common(PITCommonState *s, PITChannelState *sc, +                                 PITChannelInfo *info); +void pit_reset_common(PITCommonState *s); + +#endif /* !QEMU_I8254_INTERNAL_H */ diff --git a/include/hw/timer/m48t59.h b/include/hw/timer/m48t59.h new file mode 100644 index 00000000..33679236 --- /dev/null +++ b/include/hw/timer/m48t59.h @@ -0,0 +1,34 @@ +#ifndef NVRAM_H +#define NVRAM_H + +#include "qemu-common.h" +#include "qom/object.h" + +#define TYPE_NVRAM "nvram" + +#define NVRAM_CLASS(klass) \ +    OBJECT_CLASS_CHECK(NvramClass, (klass), TYPE_NVRAM) +#define NVRAM_GET_CLASS(obj) \ +    OBJECT_GET_CLASS(NvramClass, (obj), TYPE_NVRAM) +#define NVRAM(obj) \ +    INTERFACE_CHECK(Nvram, (obj), TYPE_NVRAM) + +typedef struct Nvram { +    Object parent; +} Nvram; + +typedef struct NvramClass { +    InterfaceClass parent; + +    uint32_t (*read)(Nvram *obj, uint32_t addr); +    void (*write)(Nvram *obj, uint32_t addr, uint32_t val); +    void (*toggle_lock)(Nvram *obj, int lock); +} NvramClass; + +Nvram *m48t59_init_isa(ISABus *bus, uint32_t io_base, uint16_t size, +                       int base_year, int type); +Nvram *m48t59_init(qemu_irq IRQ, hwaddr mem_base, +                   uint32_t io_base, uint16_t size, int base_year, +                   int type); + +#endif /* !NVRAM_H */ diff --git a/include/hw/timer/mc146818rtc.h b/include/hw/timer/mc146818rtc.h new file mode 100644 index 00000000..eaf64976 --- /dev/null +++ b/include/hw/timer/mc146818rtc.h @@ -0,0 +1,13 @@ +#ifndef MC146818RTC_H +#define MC146818RTC_H + +#include "hw/isa/isa.h" +#include "hw/timer/mc146818rtc_regs.h" + +#define TYPE_MC146818_RTC "mc146818rtc" + +ISADevice *rtc_init(ISABus *bus, int base_year, qemu_irq intercept_irq); +void rtc_set_memory(ISADevice *dev, int addr, int val); +int rtc_get_memory(ISADevice *dev, int addr); + +#endif /* !MC146818RTC_H */ diff --git a/include/hw/timer/mc146818rtc_regs.h b/include/hw/timer/mc146818rtc_regs.h new file mode 100644 index 00000000..ccdee42b --- /dev/null +++ b/include/hw/timer/mc146818rtc_regs.h @@ -0,0 +1,67 @@ +/* + * QEMU MC146818 RTC emulation + * + * Copyright (c) 2003-2004 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * 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 OTHER + * 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. + */ +#ifndef RTC_REGS_H +#define RTC_REGS_H + +#define RTC_ISA_IRQ 8 + +#define RTC_SECONDS             0 +#define RTC_SECONDS_ALARM       1 +#define RTC_MINUTES             2 +#define RTC_MINUTES_ALARM       3 +#define RTC_HOURS               4 +#define RTC_HOURS_ALARM         5 +#define RTC_ALARM_DONT_CARE    0xC0 + +#define RTC_DAY_OF_WEEK         6 +#define RTC_DAY_OF_MONTH        7 +#define RTC_MONTH               8 +#define RTC_YEAR                9 + +#define RTC_REG_A               10 +#define RTC_REG_B               11 +#define RTC_REG_C               12 +#define RTC_REG_D               13 + +/* PC cmos mappings */ +#define RTC_CENTURY              0x32 +#define RTC_IBM_PS2_CENTURY_BYTE 0x37 + +#define REG_A_UIP 0x80 + +#define REG_B_SET  0x80 +#define REG_B_PIE  0x40 +#define REG_B_AIE  0x20 +#define REG_B_UIE  0x10 +#define REG_B_SQWE 0x08 +#define REG_B_DM   0x04 +#define REG_B_24H  0x02 + +#define REG_C_UF   0x10 +#define REG_C_IRQF 0x80 +#define REG_C_PF   0x40 +#define REG_C_AF   0x20 +#define REG_C_MASK 0x70 + +#endif diff --git a/include/hw/timer/stm32f2xx_timer.h b/include/hw/timer/stm32f2xx_timer.h new file mode 100644 index 00000000..e6a83237 --- /dev/null +++ b/include/hw/timer/stm32f2xx_timer.h @@ -0,0 +1,101 @@ +/* + * STM32F2XX Timer + * + * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me> + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * 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 OTHER + * 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. + */ + +#ifndef HW_STM32F2XX_TIMER_H +#define HW_STM32F2XX_TIMER_H + +#include "hw/sysbus.h" +#include "qemu/timer.h" +#include "sysemu/sysemu.h" + +#define TIM_CR1      0x00 +#define TIM_CR2      0x04 +#define TIM_SMCR     0x08 +#define TIM_DIER     0x0C +#define TIM_SR       0x10 +#define TIM_EGR      0x14 +#define TIM_CCMR1    0x18 +#define TIM_CCMR2    0x1C +#define TIM_CCER     0x20 +#define TIM_CNT      0x24 +#define TIM_PSC      0x28 +#define TIM_ARR      0x2C +#define TIM_CCR1     0x34 +#define TIM_CCR2     0x38 +#define TIM_CCR3     0x3C +#define TIM_CCR4     0x40 +#define TIM_DCR      0x48 +#define TIM_DMAR     0x4C +#define TIM_OR       0x50 + +#define TIM_CR1_CEN   1 + +#define TIM_EGR_UG 1 + +#define TIM_CCER_CC2E   (1 << 4) +#define TIM_CCMR1_OC2M2 (1 << 14) +#define TIM_CCMR1_OC2M1 (1 << 13) +#define TIM_CCMR1_OC2M0 (1 << 12) +#define TIM_CCMR1_OC2PE (1 << 11) + +#define TIM_DIER_UIE  1 + +#define TYPE_STM32F2XX_TIMER "stm32f2xx-timer" +#define STM32F2XXTIMER(obj) OBJECT_CHECK(STM32F2XXTimerState, \ +                            (obj), TYPE_STM32F2XX_TIMER) + +typedef struct STM32F2XXTimerState { +    /* <private> */ +    SysBusDevice parent_obj; + +    /* <public> */ +    MemoryRegion iomem; +    QEMUTimer *timer; +    qemu_irq irq; + +    int64_t tick_offset; +    uint64_t hit_time; +    uint64_t freq_hz; + +    uint32_t tim_cr1; +    uint32_t tim_cr2; +    uint32_t tim_smcr; +    uint32_t tim_dier; +    uint32_t tim_sr; +    uint32_t tim_egr; +    uint32_t tim_ccmr1; +    uint32_t tim_ccmr2; +    uint32_t tim_ccer; +    uint32_t tim_psc; +    uint32_t tim_arr; +    uint32_t tim_ccr1; +    uint32_t tim_ccr2; +    uint32_t tim_ccr3; +    uint32_t tim_ccr4; +    uint32_t tim_dcr; +    uint32_t tim_dmar; +    uint32_t tim_or; +} STM32F2XXTimerState; + +#endif /* HW_STM32F2XX_TIMER_H */ diff --git a/include/hw/tricore/tricore.h b/include/hw/tricore/tricore.h new file mode 100644 index 00000000..5f132527 --- /dev/null +++ b/include/hw/tricore/tricore.h @@ -0,0 +1,11 @@ +#ifndef TRICORE_MISC_H +#define TRICORE_MISC_H 1 + +#include "exec/memory.h" +#include "hw/irq.h" + +struct tricore_boot_info { +    uint64_t ram_size; +    const char *kernel_filename; +}; +#endif diff --git a/include/hw/unicore32/puv3.h b/include/hw/unicore32/puv3.h new file mode 100644 index 00000000..f37adcb6 --- /dev/null +++ b/include/hw/unicore32/puv3.h @@ -0,0 +1,49 @@ +/* + * Misc PKUnity SoC declarations + * + * Copyright (C) 2010-2012 Guan Xuetao + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation, or any later version. + * See the COPYING file in the top-level directory. + */ +#ifndef QEMU_HW_PUV3_H +#define QEMU_HW_PUV3_H + +#define PUV3_REGS_OFFSET        (0x1000) /* 4K is reasonable */ + +/* PKUnity System bus (AHB): 0xc0000000 - 0xedffffff (640MB) */ +#define PUV3_DMA_BASE           (0xc0200000) /* AHB-4 */ + +/* PKUnity Peripheral bus (APB): 0xee000000 - 0xefffffff (128MB) */ +#define PUV3_GPIO_BASE          (0xee500000) /* APB-5 */ +#define PUV3_INTC_BASE          (0xee600000) /* APB-6 */ +#define PUV3_OST_BASE           (0xee800000) /* APB-8 */ +#define PUV3_PM_BASE            (0xeea00000) /* APB-10 */ +#define PUV3_PS2_BASE           (0xeeb00000) /* APB-11 */ + +/* Hardware interrupts */ +#define PUV3_IRQS_NR            (32) + +#define PUV3_IRQS_GPIOLOW0      (0) +#define PUV3_IRQS_GPIOLOW1      (1) +#define PUV3_IRQS_GPIOLOW2      (2) +#define PUV3_IRQS_GPIOLOW3      (3) +#define PUV3_IRQS_GPIOLOW4      (4) +#define PUV3_IRQS_GPIOLOW5      (5) +#define PUV3_IRQS_GPIOLOW6      (6) +#define PUV3_IRQS_GPIOLOW7      (7) +#define PUV3_IRQS_GPIOHIGH      (8) +#define PUV3_IRQS_PS2_KBD       (22) +#define PUV3_IRQS_PS2_AUX       (23) +#define PUV3_IRQS_OST0          (26) + +/* All puv3_*.c use DPRINTF for debug. */ +#ifdef DEBUG_PUV3 +#define DPRINTF(fmt, ...) printf("%s: " fmt , __func__, ## __VA_ARGS__) +#else +#define DPRINTF(fmt, ...) do {} while (0) +#endif + +#endif /* !QEMU_HW_PUV3_H */ diff --git a/include/hw/usb.h b/include/hw/usb.h new file mode 100644 index 00000000..c8b6e7b5 --- /dev/null +++ b/include/hw/usb.h @@ -0,0 +1,611 @@ +#ifndef QEMU_USB_H +#define QEMU_USB_H + +/* + * QEMU USB API + * + * Copyright (c) 2005 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * 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 OTHER + * 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 "hw/qdev.h" +#include "qemu/queue.h" + +/* Constants related to the USB / PCI interaction */ +#define USB_SBRN    0x60 /* Serial Bus Release Number Register */ +#define USB_RELEASE_1  0x10 /* USB 1.0 */ +#define USB_RELEASE_2  0x20 /* USB 2.0 */ +#define USB_RELEASE_3  0x30 /* USB 3.0 */ + +#define USB_TOKEN_SETUP 0x2d +#define USB_TOKEN_IN    0x69 /* device -> host */ +#define USB_TOKEN_OUT   0xe1 /* host -> device */ + +#define USB_RET_SUCCESS           (0) +#define USB_RET_NODEV             (-1) +#define USB_RET_NAK               (-2) +#define USB_RET_STALL             (-3) +#define USB_RET_BABBLE            (-4) +#define USB_RET_IOERROR           (-5) +#define USB_RET_ASYNC             (-6) +#define USB_RET_ADD_TO_QUEUE      (-7) +#define USB_RET_REMOVE_FROM_QUEUE (-8) + +#define USB_SPEED_LOW   0 +#define USB_SPEED_FULL  1 +#define USB_SPEED_HIGH  2 +#define USB_SPEED_SUPER 3 + +#define USB_SPEED_MASK_LOW   (1 << USB_SPEED_LOW) +#define USB_SPEED_MASK_FULL  (1 << USB_SPEED_FULL) +#define USB_SPEED_MASK_HIGH  (1 << USB_SPEED_HIGH) +#define USB_SPEED_MASK_SUPER (1 << USB_SPEED_SUPER) + +#define USB_STATE_NOTATTACHED 0 +#define USB_STATE_ATTACHED    1 +//#define USB_STATE_POWERED     2 +#define USB_STATE_DEFAULT     3 +//#define USB_STATE_ADDRESS     4 +//#define	USB_STATE_CONFIGURED  5 +#define USB_STATE_SUSPENDED   6 + +#define USB_CLASS_AUDIO			1 +#define USB_CLASS_COMM			2 +#define USB_CLASS_HID			3 +#define USB_CLASS_PHYSICAL		5 +#define USB_CLASS_STILL_IMAGE		6 +#define USB_CLASS_PRINTER		7 +#define USB_CLASS_MASS_STORAGE		8 +#define USB_CLASS_HUB			9 +#define USB_CLASS_CDC_DATA		0x0a +#define USB_CLASS_CSCID			0x0b +#define USB_CLASS_CONTENT_SEC		0x0d +#define USB_CLASS_APP_SPEC		0xfe +#define USB_CLASS_VENDOR_SPEC		0xff + +#define USB_SUBCLASS_UNDEFINED          0 +#define USB_SUBCLASS_AUDIO_CONTROL      1 +#define USB_SUBCLASS_AUDIO_STREAMING    2 +#define USB_SUBCLASS_AUDIO_MIDISTREAMING 3 + +#define USB_DIR_OUT			0 +#define USB_DIR_IN			0x80 + +#define USB_TYPE_MASK			(0x03 << 5) +#define USB_TYPE_STANDARD		(0x00 << 5) +#define USB_TYPE_CLASS			(0x01 << 5) +#define USB_TYPE_VENDOR			(0x02 << 5) +#define USB_TYPE_RESERVED		(0x03 << 5) + +#define USB_RECIP_MASK			0x1f +#define USB_RECIP_DEVICE		0x00 +#define USB_RECIP_INTERFACE		0x01 +#define USB_RECIP_ENDPOINT		0x02 +#define USB_RECIP_OTHER			0x03 + +#define DeviceRequest ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE)<<8) +#define DeviceOutRequest ((USB_DIR_OUT|USB_TYPE_STANDARD|USB_RECIP_DEVICE)<<8) +#define VendorDeviceRequest ((USB_DIR_IN|USB_TYPE_VENDOR|USB_RECIP_DEVICE)<<8) +#define VendorDeviceOutRequest \ +        ((USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_DEVICE)<<8) + +#define InterfaceRequest                                        \ +        ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_INTERFACE)<<8) +#define InterfaceOutRequest \ +        ((USB_DIR_OUT|USB_TYPE_STANDARD|USB_RECIP_INTERFACE)<<8) +#define ClassInterfaceRequest \ +        ((USB_DIR_IN|USB_TYPE_CLASS|USB_RECIP_INTERFACE)<<8) +#define ClassInterfaceOutRequest \ +        ((USB_DIR_OUT|USB_TYPE_CLASS|USB_RECIP_INTERFACE)<<8) +#define VendorInterfaceRequest \ +        ((USB_DIR_IN|USB_TYPE_VENDOR|USB_RECIP_INTERFACE)<<8) +#define VendorInterfaceOutRequest \ +        ((USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_INTERFACE)<<8) + +#define EndpointRequest ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_ENDPOINT)<<8) +#define EndpointOutRequest \ +        ((USB_DIR_OUT|USB_TYPE_STANDARD|USB_RECIP_ENDPOINT)<<8) + +#define USB_REQ_GET_STATUS		0x00 +#define USB_REQ_CLEAR_FEATURE		0x01 +#define USB_REQ_SET_FEATURE		0x03 +#define USB_REQ_SET_ADDRESS		0x05 +#define USB_REQ_GET_DESCRIPTOR		0x06 +#define USB_REQ_SET_DESCRIPTOR		0x07 +#define USB_REQ_GET_CONFIGURATION	0x08 +#define USB_REQ_SET_CONFIGURATION	0x09 +#define USB_REQ_GET_INTERFACE		0x0A +#define USB_REQ_SET_INTERFACE		0x0B +#define USB_REQ_SYNCH_FRAME		0x0C + +#define USB_DEVICE_SELF_POWERED		0 +#define USB_DEVICE_REMOTE_WAKEUP	1 + +#define USB_DT_DEVICE			0x01 +#define USB_DT_CONFIG			0x02 +#define USB_DT_STRING			0x03 +#define USB_DT_INTERFACE		0x04 +#define USB_DT_ENDPOINT			0x05 +#define USB_DT_DEVICE_QUALIFIER         0x06 +#define USB_DT_OTHER_SPEED_CONFIG       0x07 +#define USB_DT_DEBUG                    0x0A +#define USB_DT_INTERFACE_ASSOC          0x0B +#define USB_DT_BOS                      0x0F +#define USB_DT_DEVICE_CAPABILITY        0x10 +#define USB_DT_CS_INTERFACE             0x24 +#define USB_DT_CS_ENDPOINT              0x25 +#define USB_DT_ENDPOINT_COMPANION       0x30 + +#define USB_DEV_CAP_WIRELESS            0x01 +#define USB_DEV_CAP_USB2_EXT            0x02 +#define USB_DEV_CAP_SUPERSPEED          0x03 + +#define USB_CFG_ATT_ONE              (1 << 7) /* should always be set */ +#define USB_CFG_ATT_SELFPOWER        (1 << 6) +#define USB_CFG_ATT_WAKEUP           (1 << 5) +#define USB_CFG_ATT_BATTERY          (1 << 4) + +#define USB_ENDPOINT_XFER_CONTROL	0 +#define USB_ENDPOINT_XFER_ISOC		1 +#define USB_ENDPOINT_XFER_BULK		2 +#define USB_ENDPOINT_XFER_INT		3 +#define USB_ENDPOINT_XFER_INVALID     255 + +#define USB_INTERFACE_INVALID         255 + +typedef struct USBBus USBBus; +typedef struct USBBusOps USBBusOps; +typedef struct USBPort USBPort; +typedef struct USBDevice USBDevice; +typedef struct USBPacket USBPacket; +typedef struct USBCombinedPacket USBCombinedPacket; +typedef struct USBEndpoint USBEndpoint; + +typedef struct USBDesc USBDesc; +typedef struct USBDescID USBDescID; +typedef struct USBDescDevice USBDescDevice; +typedef struct USBDescConfig USBDescConfig; +typedef struct USBDescIfaceAssoc USBDescIfaceAssoc; +typedef struct USBDescIface USBDescIface; +typedef struct USBDescEndpoint USBDescEndpoint; +typedef struct USBDescOther USBDescOther; +typedef struct USBDescString USBDescString; +typedef struct USBDescMSOS USBDescMSOS; + +struct USBDescString { +    uint8_t index; +    char *str; +    QLIST_ENTRY(USBDescString) next; +}; + +#define USB_MAX_ENDPOINTS  15 +#define USB_MAX_INTERFACES 16 + +struct USBEndpoint { +    uint8_t nr; +    uint8_t pid; +    uint8_t type; +    uint8_t ifnum; +    int max_packet_size; +    int max_streams; +    bool pipeline; +    bool halted; +    USBDevice *dev; +    QTAILQ_HEAD(, USBPacket) queue; +}; + +enum USBDeviceFlags { +    USB_DEV_FLAG_FULL_PATH, +    USB_DEV_FLAG_IS_HOST, +    USB_DEV_FLAG_MSOS_DESC_ENABLE, +    USB_DEV_FLAG_MSOS_DESC_IN_USE, +}; + +/* definition of a USB device */ +struct USBDevice { +    DeviceState qdev; +    USBPort *port; +    char *port_path; +    char *serial; +    void *opaque; +    uint32_t flags; + +    /* Actual connected speed */ +    int speed; +    /* Supported speeds, not in info because it may be variable (hostdevs) */ +    int speedmask; +    uint8_t addr; +    char product_desc[32]; +    int auto_attach; +    int attached; + +    int32_t state; +    uint8_t setup_buf[8]; +    uint8_t data_buf[4096]; +    int32_t remote_wakeup; +    int32_t setup_state; +    int32_t setup_len; +    int32_t setup_index; + +    USBEndpoint ep_ctl; +    USBEndpoint ep_in[USB_MAX_ENDPOINTS]; +    USBEndpoint ep_out[USB_MAX_ENDPOINTS]; + +    QLIST_HEAD(, USBDescString) strings; +    const USBDesc *usb_desc; /* Overrides class usb_desc if not NULL */ +    const USBDescDevice *device; + +    int configuration; +    int ninterfaces; +    int altsetting[USB_MAX_INTERFACES]; +    const USBDescConfig *config; +    const USBDescIface  *ifaces[USB_MAX_INTERFACES]; +}; + +#define TYPE_USB_DEVICE "usb-device" +#define USB_DEVICE(obj) \ +     OBJECT_CHECK(USBDevice, (obj), TYPE_USB_DEVICE) +#define USB_DEVICE_CLASS(klass) \ +     OBJECT_CLASS_CHECK(USBDeviceClass, (klass), TYPE_USB_DEVICE) +#define USB_DEVICE_GET_CLASS(obj) \ +     OBJECT_GET_CLASS(USBDeviceClass, (obj), TYPE_USB_DEVICE) + +typedef void (*USBDeviceRealize)(USBDevice *dev, Error **errp); +typedef void (*USBDeviceUnrealize)(USBDevice *dev, Error **errp); + +typedef struct USBDeviceClass { +    DeviceClass parent_class; + +    USBDeviceRealize realize; +    USBDeviceUnrealize unrealize; + +    /* +     * Walk (enabled) downstream ports, check for a matching device. +     * Only hubs implement this. +     */ +    USBDevice *(*find_device)(USBDevice *dev, uint8_t addr); + +    /* +     * Called when a packet is canceled. +     */ +    void (*cancel_packet)(USBDevice *dev, USBPacket *p); + +    /* +     * Called when device is destroyed. +     */ +    void (*handle_destroy)(USBDevice *dev); + +    /* +     * Attach the device +     */ +    void (*handle_attach)(USBDevice *dev); + +    /* +     * Reset the device +     */ +    void (*handle_reset)(USBDevice *dev); + +    /* +     * Process control request. +     * Called from handle_packet(). +     * +     * Status gets stored in p->status, and if p->status == USB_RET_SUCCESS +     * then the number of bytes transferred is stored in p->actual_length +     */ +    void (*handle_control)(USBDevice *dev, USBPacket *p, int request, int value, +                           int index, int length, uint8_t *data); + +    /* +     * Process data transfers (both BULK and ISOC). +     * Called from handle_packet(). +     * +     * Status gets stored in p->status, and if p->status == USB_RET_SUCCESS +     * then the number of bytes transferred is stored in p->actual_length +     */ +    void (*handle_data)(USBDevice *dev, USBPacket *p); + +    void (*set_interface)(USBDevice *dev, int interface, +                          int alt_old, int alt_new); + +    /* +     * Called when the hcd is done queuing packets for an endpoint, only +     * necessary for devices which can return USB_RET_ADD_TO_QUEUE. +     */ +    void (*flush_ep_queue)(USBDevice *dev, USBEndpoint *ep); + +    /* +     * Called by the hcd to let the device know the queue for an endpoint +     * has been unlinked / stopped. Optional may be NULL. +     */ +    void (*ep_stopped)(USBDevice *dev, USBEndpoint *ep); + +    /* +     * Called by the hcd to alloc / free streams on a bulk endpoint. +     * Optional may be NULL. +     */ +    int (*alloc_streams)(USBDevice *dev, USBEndpoint **eps, int nr_eps, +                         int streams); +    void (*free_streams)(USBDevice *dev, USBEndpoint **eps, int nr_eps); + +    const char *product_desc; +    const USBDesc *usb_desc; +} USBDeviceClass; + +typedef struct USBPortOps { +    void (*attach)(USBPort *port); +    void (*detach)(USBPort *port); +    /* +     * This gets called when a device downstream from the device attached to +     * the port (iow attached through a hub) gets detached. +     */ +    void (*child_detach)(USBPort *port, USBDevice *child); +    void (*wakeup)(USBPort *port); +    /* +     * Note that port->dev will be different then the device from which +     * the packet originated when a hub is involved. +     */ +    void (*complete)(USBPort *port, USBPacket *p); +} USBPortOps; + +/* USB port on which a device can be connected */ +struct USBPort { +    USBDevice *dev; +    int speedmask; +    int hubcount; +    char path[16]; +    USBPortOps *ops; +    void *opaque; +    int index; /* internal port index, may be used with the opaque */ +    QTAILQ_ENTRY(USBPort) next; +}; + +typedef void USBCallback(USBPacket * packet, void *opaque); + +typedef enum USBPacketState { +    USB_PACKET_UNDEFINED = 0, +    USB_PACKET_SETUP, +    USB_PACKET_QUEUED, +    USB_PACKET_ASYNC, +    USB_PACKET_COMPLETE, +    USB_PACKET_CANCELED, +} USBPacketState; + +/* Structure used to hold information about an active USB packet.  */ +struct USBPacket { +    /* Data fields for use by the driver.  */ +    int pid; +    uint64_t id; +    USBEndpoint *ep; +    unsigned int stream; +    QEMUIOVector iov; +    uint64_t parameter; /* control transfers */ +    bool short_not_ok; +    bool int_req; +    int status; /* USB_RET_* status code */ +    int actual_length; /* Number of bytes actually transferred */ +    /* Internal use by the USB layer.  */ +    USBPacketState state; +    USBCombinedPacket *combined; +    QTAILQ_ENTRY(USBPacket) queue; +    QTAILQ_ENTRY(USBPacket) combined_entry; +}; + +struct USBCombinedPacket { +    USBPacket *first; +    QTAILQ_HEAD(packets_head, USBPacket) packets; +    QEMUIOVector iov; +}; + +void usb_packet_init(USBPacket *p); +void usb_packet_set_state(USBPacket *p, USBPacketState state); +void usb_packet_check_state(USBPacket *p, USBPacketState expected); +void usb_packet_setup(USBPacket *p, int pid, +                      USBEndpoint *ep, unsigned int stream, +                      uint64_t id, bool short_not_ok, bool int_req); +void usb_packet_addbuf(USBPacket *p, void *ptr, size_t len); +int usb_packet_map(USBPacket *p, QEMUSGList *sgl); +void usb_packet_unmap(USBPacket *p, QEMUSGList *sgl); +void usb_packet_copy(USBPacket *p, void *ptr, size_t bytes); +void usb_packet_skip(USBPacket *p, size_t bytes); +size_t usb_packet_size(USBPacket *p); +void usb_packet_cleanup(USBPacket *p); + +static inline bool usb_packet_is_inflight(USBPacket *p) +{ +    return (p->state == USB_PACKET_QUEUED || +            p->state == USB_PACKET_ASYNC); +} + +USBDevice *usb_find_device(USBPort *port, uint8_t addr); + +void usb_handle_packet(USBDevice *dev, USBPacket *p); +void usb_packet_complete(USBDevice *dev, USBPacket *p); +void usb_packet_complete_one(USBDevice *dev, USBPacket *p); +void usb_cancel_packet(USBPacket * p); + +void usb_ep_init(USBDevice *dev); +void usb_ep_reset(USBDevice *dev); +void usb_ep_dump(USBDevice *dev); +struct USBEndpoint *usb_ep_get(USBDevice *dev, int pid, int ep); +uint8_t usb_ep_get_type(USBDevice *dev, int pid, int ep); +void usb_ep_set_type(USBDevice *dev, int pid, int ep, uint8_t type); +void usb_ep_set_ifnum(USBDevice *dev, int pid, int ep, uint8_t ifnum); +void usb_ep_set_max_packet_size(USBDevice *dev, int pid, int ep, +                                uint16_t raw); +void usb_ep_set_max_streams(USBDevice *dev, int pid, int ep, uint8_t raw); +void usb_ep_set_halted(USBDevice *dev, int pid, int ep, bool halted); +USBPacket *usb_ep_find_packet_by_id(USBDevice *dev, int pid, int ep, +                                    uint64_t id); + +void usb_ep_combine_input_packets(USBEndpoint *ep); +void usb_combined_input_packet_complete(USBDevice *dev, USBPacket *p); +void usb_combined_packet_cancel(USBDevice *dev, USBPacket *p); + +void usb_pick_speed(USBPort *port); +void usb_attach(USBPort *port); +void usb_detach(USBPort *port); +void usb_port_reset(USBPort *port); +void usb_device_reset(USBDevice *dev); +void usb_wakeup(USBEndpoint *ep, unsigned int stream); +void usb_generic_async_ctrl_complete(USBDevice *s, USBPacket *p); + +/* usb-linux.c */ +USBDevice *usb_host_device_open(USBBus *bus, const char *devname); +void hmp_info_usbhost(Monitor *mon, const QDict *qdict); + +/* usb ports of the VM */ + +#define VM_USB_HUB_SIZE 8 + +/* hw/usb/hdc-musb.c */ + +enum musb_irq_source_e { +    musb_irq_suspend = 0, +    musb_irq_resume, +    musb_irq_rst_babble, +    musb_irq_sof, +    musb_irq_connect, +    musb_irq_disconnect, +    musb_irq_vbus_request, +    musb_irq_vbus_error, +    musb_irq_rx, +    musb_irq_tx, +    musb_set_vbus, +    musb_set_session, +    /* Add new interrupts here */ +    musb_irq_max, /* total number of interrupts defined */ +}; + +typedef struct MUSBState MUSBState; + +extern CPUReadMemoryFunc * const musb_read[]; +extern CPUWriteMemoryFunc * const musb_write[]; + +MUSBState *musb_init(DeviceState *parent_device, int gpio_base); +void musb_reset(MUSBState *s); +uint32_t musb_core_intr_get(MUSBState *s); +void musb_core_intr_clear(MUSBState *s, uint32_t mask); +void musb_set_size(MUSBState *s, int epnum, int size, int is_tx); + +/* usb-bus.c */ + +#define TYPE_USB_BUS "usb-bus" +#define USB_BUS(obj) OBJECT_CHECK(USBBus, (obj), TYPE_USB_BUS) + +struct USBBus { +    BusState qbus; +    USBBusOps *ops; +    int busnr; +    int nfree; +    int nused; +    QTAILQ_HEAD(, USBPort) free; +    QTAILQ_HEAD(, USBPort) used; +    QTAILQ_ENTRY(USBBus) next; +}; + +struct USBBusOps { +    void (*register_companion)(USBBus *bus, USBPort *ports[], +                               uint32_t portcount, uint32_t firstport, +                               Error **errp); +    void (*wakeup_endpoint)(USBBus *bus, USBEndpoint *ep, unsigned int stream); +}; + +void usb_bus_new(USBBus *bus, size_t bus_size, +                 USBBusOps *ops, DeviceState *host); +void usb_bus_release(USBBus *bus); +USBBus *usb_bus_find(int busnr); +void usb_legacy_register(const char *typename, const char *usbdevice_name, +                         USBDevice *(*usbdevice_init)(USBBus *bus, +                                                      const char *params)); +USBDevice *usb_create(USBBus *bus, const char *name); +USBDevice *usb_create_simple(USBBus *bus, const char *name); +USBDevice *usbdevice_create(const char *cmdline); +void usb_register_port(USBBus *bus, USBPort *port, void *opaque, int index, +                       USBPortOps *ops, int speedmask); +void usb_register_companion(const char *masterbus, USBPort *ports[], +                            uint32_t portcount, uint32_t firstport, +                            void *opaque, USBPortOps *ops, int speedmask, +                            Error **errp); +void usb_port_location(USBPort *downstream, USBPort *upstream, int portnr); +void usb_unregister_port(USBBus *bus, USBPort *port); +void usb_claim_port(USBDevice *dev, Error **errp); +void usb_release_port(USBDevice *dev); +void usb_device_attach(USBDevice *dev, Error **errp); +int usb_device_detach(USBDevice *dev); +int usb_device_delete_addr(int busnr, int addr); +void usb_check_attach(USBDevice *dev, Error **errp); + +static inline USBBus *usb_bus_from_device(USBDevice *d) +{ +    return DO_UPCAST(USBBus, qbus, d->qdev.parent_bus); +} + +extern const VMStateDescription vmstate_usb_device; + +#define VMSTATE_USB_DEVICE(_field, _state) {                         \ +    .name       = (stringify(_field)),                               \ +    .size       = sizeof(USBDevice),                                 \ +    .vmsd       = &vmstate_usb_device,                               \ +    .flags      = VMS_STRUCT,                                        \ +    .offset     = vmstate_offset_value(_state, _field, USBDevice),   \ +} + +USBDevice *usb_device_find_device(USBDevice *dev, uint8_t addr); + +void usb_device_cancel_packet(USBDevice *dev, USBPacket *p); + +void usb_device_handle_attach(USBDevice *dev); + +void usb_device_handle_reset(USBDevice *dev); + +void usb_device_handle_control(USBDevice *dev, USBPacket *p, int request, +                               int val, int index, int length, uint8_t *data); + +void usb_device_handle_data(USBDevice *dev, USBPacket *p); + +void usb_device_set_interface(USBDevice *dev, int interface, +                              int alt_old, int alt_new); + +void usb_device_flush_ep_queue(USBDevice *dev, USBEndpoint *ep); + +void usb_device_ep_stopped(USBDevice *dev, USBEndpoint *ep); + +int usb_device_alloc_streams(USBDevice *dev, USBEndpoint **eps, int nr_eps, +                             int streams); +void usb_device_free_streams(USBDevice *dev, USBEndpoint **eps, int nr_eps); + +const char *usb_device_get_product_desc(USBDevice *dev); + +const USBDesc *usb_device_get_usb_desc(USBDevice *dev); + +int ehci_create_ich9_with_companions(PCIBus *bus, int slot); + +/* quirks.c */ + +/* In bulk endpoints are streaming data sources (iow behave like isoc eps) */ +#define USB_QUIRK_BUFFER_BULK_IN	0x01 +/* Bulk pkts in FTDI format, need special handling when combining packets */ +#define USB_QUIRK_IS_FTDI		0x02 + +int usb_get_quirks(uint16_t vendor_id, uint16_t product_id, +                   uint8_t interface_class, uint8_t interface_subclass, +                   uint8_t interface_protocol); + +#endif diff --git a/include/hw/usb/ehci-regs.h b/include/hw/usb/ehci-regs.h new file mode 100644 index 00000000..616f1b88 --- /dev/null +++ b/include/hw/usb/ehci-regs.h @@ -0,0 +1,82 @@ +#ifndef HW_USB_EHCI_REGS_H +#define HW_USB_EHCI_REGS_H 1 + +/* Capability Registers Base Address - section 2.2 */ +#define CAPLENGTH        0x0000  /* 1-byte, 0x0001 reserved */ +#define HCIVERSION       0x0002  /* 2-bytes, i/f version # */ +#define HCSPARAMS        0x0004  /* 4-bytes, structural params */ +#define HCCPARAMS        0x0008  /* 4-bytes, capability params */ +#define EECP             HCCPARAMS + 1 +#define HCSPPORTROUTE1   0x000c +#define HCSPPORTROUTE2   0x0010 + +#define USBCMD           0x0000 +#define USBCMD_RUNSTOP   (1 << 0)      // run / Stop +#define USBCMD_HCRESET   (1 << 1)      // HC Reset +#define USBCMD_FLS       (3 << 2)      // Frame List Size +#define USBCMD_FLS_SH    2             // Frame List Size Shift +#define USBCMD_PSE       (1 << 4)      // Periodic Schedule Enable +#define USBCMD_ASE       (1 << 5)      // Asynch Schedule Enable +#define USBCMD_IAAD      (1 << 6)      // Int Asynch Advance Doorbell +#define USBCMD_LHCR      (1 << 7)      // Light Host Controller Reset +#define USBCMD_ASPMC     (3 << 8)      // Async Sched Park Mode Count +#define USBCMD_ASPME     (1 << 11)     // Async Sched Park Mode Enable +#define USBCMD_ITC       (0x7f << 16)  // Int Threshold Control +#define USBCMD_ITC_SH    16            // Int Threshold Control Shift + +#define USBSTS           0x0004 +#define USBSTS_RO_MASK   0x0000003f +#define USBSTS_INT       (1 << 0)      // USB Interrupt +#define USBSTS_ERRINT    (1 << 1)      // Error Interrupt +#define USBSTS_PCD       (1 << 2)      // Port Change Detect +#define USBSTS_FLR       (1 << 3)      // Frame List Rollover +#define USBSTS_HSE       (1 << 4)      // Host System Error +#define USBSTS_IAA       (1 << 5)      // Interrupt on Async Advance +#define USBSTS_HALT      (1 << 12)     // HC Halted +#define USBSTS_REC       (1 << 13)     // Reclamation +#define USBSTS_PSS       (1 << 14)     // Periodic Schedule Status +#define USBSTS_ASS       (1 << 15)     // Asynchronous Schedule Status + +/* + *  Interrupt enable bits correspond to the interrupt active bits in USBSTS + *  so no need to redefine here. + */ +#define USBINTR              0x0008 +#define USBINTR_MASK         0x0000003f + +#define FRINDEX              0x000c +#define CTRLDSSEGMENT        0x0010 +#define PERIODICLISTBASE     0x0014 +#define ASYNCLISTADDR        0x0018 +#define ASYNCLISTADDR_MASK   0xffffffe0 + +#define CONFIGFLAG           0x0040 + +/* + * Bits that are reserved or are read-only are masked out of values + * written to us by software + */ +#define PORTSC_RO_MASK       0x007001c0 +#define PORTSC_RWC_MASK      0x0000002a +#define PORTSC_WKOC_E        (1 << 22)    // Wake on Over Current Enable +#define PORTSC_WKDS_E        (1 << 21)    // Wake on Disconnect Enable +#define PORTSC_WKCN_E        (1 << 20)    // Wake on Connect Enable +#define PORTSC_PTC           (15 << 16)   // Port Test Control +#define PORTSC_PTC_SH        16           // Port Test Control shift +#define PORTSC_PIC           (3 << 14)    // Port Indicator Control +#define PORTSC_PIC_SH        14           // Port Indicator Control Shift +#define PORTSC_POWNER        (1 << 13)    // Port Owner +#define PORTSC_PPOWER        (1 << 12)    // Port Power +#define PORTSC_LINESTAT      (3 << 10)    // Port Line Status +#define PORTSC_LINESTAT_SH   10           // Port Line Status Shift +#define PORTSC_PRESET        (1 << 8)     // Port Reset +#define PORTSC_SUSPEND       (1 << 7)     // Port Suspend +#define PORTSC_FPRES         (1 << 6)     // Force Port Resume +#define PORTSC_OCC           (1 << 5)     // Over Current Change +#define PORTSC_OCA           (1 << 4)     // Over Current Active +#define PORTSC_PEDC          (1 << 3)     // Port Enable/Disable Change +#define PORTSC_PED           (1 << 2)     // Port Enable/Disable +#define PORTSC_CSC           (1 << 1)     // Connect Status Change +#define PORTSC_CONNECT       (1 << 0)     // Current Connect Status + +#endif /* HW_USB_EHCI_REGS_H */ diff --git a/include/hw/usb/uhci-regs.h b/include/hw/usb/uhci-regs.h new file mode 100644 index 00000000..c7315c5e --- /dev/null +++ b/include/hw/usb/uhci-regs.h @@ -0,0 +1,40 @@ +#ifndef HW_USB_UHCI_REGS_H +#define HW_USB_UHCI_REGS_H 1 + +#define UHCI_CMD_FGR      (1 << 4) +#define UHCI_CMD_EGSM     (1 << 3) +#define UHCI_CMD_GRESET   (1 << 2) +#define UHCI_CMD_HCRESET  (1 << 1) +#define UHCI_CMD_RS       (1 << 0) + +#define UHCI_STS_HCHALTED (1 << 5) +#define UHCI_STS_HCPERR   (1 << 4) +#define UHCI_STS_HSERR    (1 << 3) +#define UHCI_STS_RD       (1 << 2) +#define UHCI_STS_USBERR   (1 << 1) +#define UHCI_STS_USBINT   (1 << 0) + +#define TD_CTRL_SPD     (1 << 29) +#define TD_CTRL_ERROR_SHIFT  27 +#define TD_CTRL_IOS     (1 << 25) +#define TD_CTRL_IOC     (1 << 24) +#define TD_CTRL_ACTIVE  (1 << 23) +#define TD_CTRL_STALL   (1 << 22) +#define TD_CTRL_BABBLE  (1 << 20) +#define TD_CTRL_NAK     (1 << 19) +#define TD_CTRL_TIMEOUT (1 << 18) + +#define UHCI_PORT_SUSPEND (1 << 12) +#define UHCI_PORT_RESET (1 << 9) +#define UHCI_PORT_LSDA  (1 << 8) +#define UHCI_PORT_RSVD1 (1 << 7) +#define UHCI_PORT_RD    (1 << 6) +#define UHCI_PORT_ENC   (1 << 3) +#define UHCI_PORT_EN    (1 << 2) +#define UHCI_PORT_CSC   (1 << 1) +#define UHCI_PORT_CCS   (1 << 0) + +#define UHCI_PORT_READ_ONLY    (0x1bb) +#define UHCI_PORT_WRITE_CLEAR  (UHCI_PORT_CSC | UHCI_PORT_ENC) + +#endif /* HW_USB_UHCI_REGS_H */ diff --git a/include/hw/vfio/vfio-calxeda-xgmac.h b/include/hw/vfio/vfio-calxeda-xgmac.h new file mode 100644 index 00000000..f994775c --- /dev/null +++ b/include/hw/vfio/vfio-calxeda-xgmac.h @@ -0,0 +1,46 @@ +/* + * VFIO calxeda xgmac device + * + * Copyright Linaro Limited, 2014 + * + * Authors: + *  Eric Auger <eric.auger@linaro.org> + * + * This work is licensed under the terms of the GNU GPL, version 2.  See + * the COPYING file in the top-level directory. + * + */ + +#ifndef HW_VFIO_VFIO_CALXEDA_XGMAC_H +#define HW_VFIO_VFIO_CALXEDA_XGMAC_H + +#include "hw/vfio/vfio-platform.h" + +#define TYPE_VFIO_CALXEDA_XGMAC "vfio-calxeda-xgmac" + +/** + * This device exposes: + * - a single MMIO region corresponding to its register space + * - 3 IRQS (main and 2 power related IRQs) + */ +typedef struct VFIOCalxedaXgmacDevice { +    VFIOPlatformDevice vdev; +} VFIOCalxedaXgmacDevice; + +typedef struct VFIOCalxedaXgmacDeviceClass { +    /*< private >*/ +    VFIOPlatformDeviceClass parent_class; +    /*< public >*/ +    DeviceRealize parent_realize; +} VFIOCalxedaXgmacDeviceClass; + +#define VFIO_CALXEDA_XGMAC_DEVICE(obj) \ +     OBJECT_CHECK(VFIOCalxedaXgmacDevice, (obj), TYPE_VFIO_CALXEDA_XGMAC) +#define VFIO_CALXEDA_XGMAC_DEVICE_CLASS(klass) \ +     OBJECT_CLASS_CHECK(VFIOCalxedaXgmacDeviceClass, (klass), \ +                        TYPE_VFIO_CALXEDA_XGMAC) +#define VFIO_CALXEDA_XGMAC_DEVICE_GET_CLASS(obj) \ +     OBJECT_GET_CLASS(VFIOCalxedaXgmacDeviceClass, (obj), \ +                      TYPE_VFIO_CALXEDA_XGMAC) + +#endif diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h new file mode 100644 index 00000000..59a321d4 --- /dev/null +++ b/include/hw/vfio/vfio-common.h @@ -0,0 +1,149 @@ +/* + * common header for vfio based device assignment support + * + * Copyright Red Hat, Inc. 2012 + * + * Authors: + *  Alex Williamson <alex.williamson@redhat.com> + * + * This work is licensed under the terms of the GNU GPL, version 2.  See + * the COPYING file in the top-level directory. + * + * Based on qemu-kvm device-assignment: + *  Adapted for KVM by Qumranet. + *  Copyright (c) 2007, Neocleus, Alex Novik (alex@neocleus.com) + *  Copyright (c) 2007, Neocleus, Guy Zana (guy@neocleus.com) + *  Copyright (C) 2008, Qumranet, Amit Shah (amit.shah@qumranet.com) + *  Copyright (C) 2008, Red Hat, Amit Shah (amit.shah@redhat.com) + *  Copyright (C) 2008, IBM, Muli Ben-Yehuda (muli@il.ibm.com) + */ +#ifndef HW_VFIO_VFIO_COMMON_H +#define HW_VFIO_VFIO_COMMON_H + +#include "qemu-common.h" +#include "exec/address-spaces.h" +#include "exec/memory.h" +#include "qemu/queue.h" +#include "qemu/notify.h" + +/*#define DEBUG_VFIO*/ +#ifdef DEBUG_VFIO +#define DPRINTF(fmt, ...) \ +    do { fprintf(stderr, "vfio: " fmt, ## __VA_ARGS__); } while (0) +#else +#define DPRINTF(fmt, ...) \ +    do { } while (0) +#endif + +/* Extra debugging, trap acceleration paths for more logging */ +#define VFIO_ALLOW_KVM_INTX 1 +#define VFIO_ALLOW_KVM_MSI 1 +#define VFIO_ALLOW_KVM_MSIX 1 + +enum { +    VFIO_DEVICE_TYPE_PCI = 0, +    VFIO_DEVICE_TYPE_PLATFORM = 1, +}; + +typedef struct VFIORegion { +    struct VFIODevice *vbasedev; +    off_t fd_offset; /* offset of region within device fd */ +    MemoryRegion mem; /* slow, read/write access */ +    MemoryRegion mmap_mem; /* direct mapped access */ +    void *mmap; +    size_t size; +    uint32_t flags; /* VFIO region flags (rd/wr/mmap) */ +    uint8_t nr; /* cache the region number for debug */ +} VFIORegion; + +typedef struct VFIOAddressSpace { +    AddressSpace *as; +    QLIST_HEAD(, VFIOContainer) containers; +    QLIST_ENTRY(VFIOAddressSpace) list; +} VFIOAddressSpace; + +struct VFIOGroup; + +typedef struct VFIOType1 { +    MemoryListener listener; +    int error; +    bool initialized; +} VFIOType1; + +typedef struct VFIOContainer { +    VFIOAddressSpace *space; +    int fd; /* /dev/vfio/vfio, empowered by the attached groups */ +    struct { +        /* enable abstraction to support various iommu backends */ +        union { +            VFIOType1 type1; +        }; +        void (*release)(struct VFIOContainer *); +    } iommu_data; +    QLIST_HEAD(, VFIOGuestIOMMU) giommu_list; +    QLIST_HEAD(, VFIOGroup) group_list; +    QLIST_ENTRY(VFIOContainer) next; +} VFIOContainer; + +typedef struct VFIOGuestIOMMU { +    VFIOContainer *container; +    MemoryRegion *iommu; +    Notifier n; +    QLIST_ENTRY(VFIOGuestIOMMU) giommu_next; +} VFIOGuestIOMMU; + +typedef struct VFIODeviceOps VFIODeviceOps; + +typedef struct VFIODevice { +    QLIST_ENTRY(VFIODevice) next; +    struct VFIOGroup *group; +    char *name; +    int fd; +    int type; +    bool reset_works; +    bool needs_reset; +    bool allow_mmap; +    VFIODeviceOps *ops; +    unsigned int num_irqs; +    unsigned int num_regions; +    unsigned int flags; +} VFIODevice; + +struct VFIODeviceOps { +    void (*vfio_compute_needs_reset)(VFIODevice *vdev); +    int (*vfio_hot_reset_multi)(VFIODevice *vdev); +    void (*vfio_eoi)(VFIODevice *vdev); +}; + +typedef struct VFIOGroup { +    int fd; +    int groupid; +    VFIOContainer *container; +    QLIST_HEAD(, VFIODevice) device_list; +    QLIST_ENTRY(VFIOGroup) next; +    QLIST_ENTRY(VFIOGroup) container_next; +} VFIOGroup; + +void vfio_put_base_device(VFIODevice *vbasedev); +void vfio_disable_irqindex(VFIODevice *vbasedev, int index); +void vfio_unmask_single_irqindex(VFIODevice *vbasedev, int index); +void vfio_mask_single_irqindex(VFIODevice *vbasedev, int index); +void vfio_region_write(void *opaque, hwaddr addr, +                           uint64_t data, unsigned size); +uint64_t vfio_region_read(void *opaque, +                          hwaddr addr, unsigned size); +int vfio_mmap_region(Object *vdev, VFIORegion *region, +                     MemoryRegion *mem, MemoryRegion *submem, +                     void **map, size_t size, off_t offset, +                     const char *name); +void vfio_reset_handler(void *opaque); +VFIOGroup *vfio_get_group(int groupid, AddressSpace *as); +void vfio_put_group(VFIOGroup *group); +int vfio_get_device(VFIOGroup *group, const char *name, +                    VFIODevice *vbasedev); + +extern const MemoryRegionOps vfio_region_ops; +extern QLIST_HEAD(vfio_group_head, VFIOGroup) vfio_group_list; +extern QLIST_HEAD(vfio_as_head, VFIOAddressSpace) vfio_address_spaces; + +#endif /* !HW_VFIO_VFIO_COMMON_H */ diff --git a/include/hw/vfio/vfio-platform.h b/include/hw/vfio/vfio-platform.h new file mode 100644 index 00000000..c5cf1d79 --- /dev/null +++ b/include/hw/vfio/vfio-platform.h @@ -0,0 +1,77 @@ +/* + * vfio based device assignment support - platform devices + * + * Copyright Linaro Limited, 2014 + * + * Authors: + *  Kim Phillips <kim.phillips@linaro.org> + * + * This work is licensed under the terms of the GNU GPL, version 2.  See + * the COPYING file in the top-level directory. + * + * Based on vfio based PCI device assignment support: + *  Copyright Red Hat, Inc. 2012 + */ + +#ifndef HW_VFIO_VFIO_PLATFORM_H +#define HW_VFIO_VFIO_PLATFORM_H + +#include "hw/sysbus.h" +#include "hw/vfio/vfio-common.h" +#include "qemu/event_notifier.h" +#include "qemu/queue.h" +#include "hw/irq.h" + +#define TYPE_VFIO_PLATFORM "vfio-platform" + +enum { +    VFIO_IRQ_INACTIVE = 0, +    VFIO_IRQ_PENDING = 1, +    VFIO_IRQ_ACTIVE = 2, +    /* VFIO_IRQ_ACTIVE_AND_PENDING cannot happen with VFIO */ +}; + +typedef struct VFIOINTp { +    QLIST_ENTRY(VFIOINTp) next; /* entry for IRQ list */ +    QSIMPLEQ_ENTRY(VFIOINTp) pqnext; /* entry for pending IRQ queue */ +    EventNotifier interrupt; /* eventfd triggered on interrupt */ +    EventNotifier unmask; /* eventfd for unmask on QEMU bypass */ +    qemu_irq qemuirq; +    struct VFIOPlatformDevice *vdev; /* back pointer to device */ +    int state; /* inactive, pending, active */ +    uint8_t pin; /* index */ +    uint32_t flags; /* IRQ info flags */ +    bool kvm_accel; /* set when QEMU bypass through KVM enabled */ +} VFIOINTp; + +/* function type for user side eventfd handler */ +typedef void (*eventfd_user_side_handler_t)(VFIOINTp *intp); + +typedef struct VFIOPlatformDevice { +    SysBusDevice sbdev; +    VFIODevice vbasedev; /* not a QOM object */ +    VFIORegion **regions; +    QLIST_HEAD(, VFIOINTp) intp_list; /* list of IRQs */ +    /* queue of pending IRQs */ +    QSIMPLEQ_HEAD(pending_intp_queue, VFIOINTp) pending_intp_queue; +    char *compat; /* compatibility string */ +    uint32_t mmap_timeout; /* delay to re-enable mmaps after interrupt */ +    QEMUTimer *mmap_timer; /* allows fast-path resume after IRQ hit */ +    QemuMutex intp_mutex; /* protect the intp_list IRQ state */ +    bool irqfd_allowed; /* debug option to force irqfd on/off */ +} VFIOPlatformDevice; + +typedef struct VFIOPlatformDeviceClass { +    /*< private >*/ +    SysBusDeviceClass parent_class; +    /*< public >*/ +} VFIOPlatformDeviceClass; + +#define VFIO_PLATFORM_DEVICE(obj) \ +     OBJECT_CHECK(VFIOPlatformDevice, (obj), TYPE_VFIO_PLATFORM) +#define VFIO_PLATFORM_DEVICE_CLASS(klass) \ +     OBJECT_CLASS_CHECK(VFIOPlatformDeviceClass, (klass), TYPE_VFIO_PLATFORM) +#define VFIO_PLATFORM_DEVICE_GET_CLASS(obj) \ +     OBJECT_GET_CLASS(VFIOPlatformDeviceClass, (obj), TYPE_VFIO_PLATFORM) + +#endif /*HW_VFIO_VFIO_PLATFORM_H*/ diff --git a/include/hw/vfio/vfio.h b/include/hw/vfio/vfio.h new file mode 100644 index 00000000..0b26cd8e --- /dev/null +++ b/include/hw/vfio/vfio.h @@ -0,0 +1,9 @@ +#ifndef VFIO_API_H +#define VFIO_API_H + +#include "qemu/typedefs.h" + +extern int vfio_container_ioctl(AddressSpace *as, int32_t groupid, +                                int req, void *param); + +#endif diff --git a/include/hw/virtio/dataplane/vring-accessors.h b/include/hw/virtio/dataplane/vring-accessors.h new file mode 100644 index 00000000..815c19b6 --- /dev/null +++ b/include/hw/virtio/dataplane/vring-accessors.h @@ -0,0 +1,75 @@ +#ifndef VRING_ACCESSORS_H +#define VRING_ACCESSORS_H + +#include "standard-headers/linux/virtio_ring.h" +#include "hw/virtio/virtio.h" +#include "hw/virtio/virtio-access.h" + +static inline uint16_t vring_get_used_idx(VirtIODevice *vdev, Vring *vring) +{ +    return virtio_tswap16(vdev, vring->vr.used->idx); +} + +static inline void vring_set_used_idx(VirtIODevice *vdev, Vring *vring, +                                      uint16_t idx) +{ +    vring->vr.used->idx = virtio_tswap16(vdev, idx); +} + +static inline uint16_t vring_get_avail_idx(VirtIODevice *vdev, Vring *vring) +{ +    return virtio_tswap16(vdev, vring->vr.avail->idx); +} + +static inline uint16_t vring_get_avail_ring(VirtIODevice *vdev, Vring *vring, +                                            int i) +{ +    return virtio_tswap16(vdev, vring->vr.avail->ring[i]); +} + +static inline void vring_set_used_ring_id(VirtIODevice *vdev, Vring *vring, +                                          int i, uint32_t id) +{ +    vring->vr.used->ring[i].id = virtio_tswap32(vdev, id); +} + +static inline void vring_set_used_ring_len(VirtIODevice *vdev, Vring *vring, +                                          int i, uint32_t len) +{ +    vring->vr.used->ring[i].len = virtio_tswap32(vdev, len); +} + +static inline uint16_t vring_get_used_flags(VirtIODevice *vdev, Vring *vring) +{ +    return virtio_tswap16(vdev, vring->vr.used->flags); +} + +static inline uint16_t vring_get_avail_flags(VirtIODevice *vdev, Vring *vring) +{ +    return virtio_tswap16(vdev, vring->vr.avail->flags); +} + +static inline void vring_set_used_flags(VirtIODevice *vdev, Vring *vring, +                                        uint16_t flags) +{ +    vring->vr.used->flags |= virtio_tswap16(vdev, flags); +} + +static inline void vring_clear_used_flags(VirtIODevice *vdev, Vring *vring, +                                          uint16_t flags) +{ +    vring->vr.used->flags &= virtio_tswap16(vdev, ~flags); +} + +static inline unsigned int vring_get_num(Vring *vring) +{ +    return vring->vr.num; +} + +/* Are there more descriptors available? */ +static inline bool vring_more_avail(VirtIODevice *vdev, Vring *vring) +{ +    return vring_get_avail_idx(vdev, vring) != vring->last_avail_idx; +} + +#endif diff --git a/include/hw/virtio/dataplane/vring.h b/include/hw/virtio/dataplane/vring.h new file mode 100644 index 00000000..a596e4c1 --- /dev/null +++ b/include/hw/virtio/dataplane/vring.h @@ -0,0 +1,51 @@ +/* Copyright 2012 Red Hat, Inc. and/or its affiliates + * Copyright IBM, Corp. 2012 + * + * Based on Linux 2.6.39 vhost code: + * Copyright (C) 2009 Red Hat, Inc. + * Copyright (C) 2006 Rusty Russell IBM Corporation + * + * Author: Michael S. Tsirkin <mst@redhat.com> + *         Stefan Hajnoczi <stefanha@redhat.com> + * + * Inspiration, some code, and most witty comments come from + * Documentation/virtual/lguest/lguest.c, by Rusty Russell + * + * This work is licensed under the terms of the GNU GPL, version 2. + */ + +#ifndef VRING_H +#define VRING_H + +#include "qemu-common.h" +#include "standard-headers/linux/virtio_ring.h" +#include "hw/virtio/virtio.h" + +typedef struct { +    MemoryRegion *mr_desc;          /* memory region for the vring desc */ +    MemoryRegion *mr_avail;         /* memory region for the vring avail */ +    MemoryRegion *mr_used;          /* memory region for the vring used */ +    struct vring vr;                /* virtqueue vring mapped to host memory */ +    uint16_t last_avail_idx;        /* last processed avail ring index */ +    uint16_t last_used_idx;         /* last processed used ring index */ +    uint16_t signalled_used;        /* EVENT_IDX state */ +    bool signalled_used_valid; +    bool broken;                    /* was there a fatal error? */ +} Vring; + +/* Fail future vring_pop() and vring_push() calls until reset */ +static inline void vring_set_broken(Vring *vring) +{ +    vring->broken = true; +} + +bool vring_setup(Vring *vring, VirtIODevice *vdev, int n); +void vring_teardown(Vring *vring, VirtIODevice *vdev, int n); +void vring_disable_notification(VirtIODevice *vdev, Vring *vring); +bool vring_enable_notification(VirtIODevice *vdev, Vring *vring); +bool vring_should_notify(VirtIODevice *vdev, Vring *vring); +int vring_pop(VirtIODevice *vdev, Vring *vring, VirtQueueElement *elem); +void vring_push(VirtIODevice *vdev, Vring *vring, VirtQueueElement *elem, +                int len); + +#endif /* VRING_H */ diff --git a/include/hw/virtio/vhost-backend.h b/include/hw/virtio/vhost-backend.h new file mode 100644 index 00000000..e472f297 --- /dev/null +++ b/include/hw/virtio/vhost-backend.h @@ -0,0 +1,40 @@ +/* + * vhost-backend + * + * Copyright (c) 2013 Virtual Open Systems Sarl. + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ + +#ifndef VHOST_BACKEND_H_ +#define VHOST_BACKEND_H_ + +typedef enum VhostBackendType { +    VHOST_BACKEND_TYPE_NONE = 0, +    VHOST_BACKEND_TYPE_KERNEL = 1, +    VHOST_BACKEND_TYPE_USER = 2, +    VHOST_BACKEND_TYPE_MAX = 3, +} VhostBackendType; + +struct vhost_dev; + +typedef int (*vhost_call)(struct vhost_dev *dev, unsigned long int request, +             void *arg); +typedef int (*vhost_backend_init)(struct vhost_dev *dev, void *opaque); +typedef int (*vhost_backend_cleanup)(struct vhost_dev *dev); + +typedef struct VhostOps { +    VhostBackendType backend_type; +    vhost_call vhost_call; +    vhost_backend_init vhost_backend_init; +    vhost_backend_cleanup vhost_backend_cleanup; +} VhostOps; + +extern const VhostOps user_ops; + +int vhost_set_backend_type(struct vhost_dev *dev, +                           VhostBackendType backend_type); + +#endif /* VHOST_BACKEND_H_ */ diff --git a/include/hw/virtio/vhost-scsi.h b/include/hw/virtio/vhost-scsi.h new file mode 100644 index 00000000..701bfee6 --- /dev/null +++ b/include/hw/virtio/vhost-scsi.h @@ -0,0 +1,69 @@ +/* + * vhost_scsi host device + * + * Copyright IBM, Corp. 2011 + * + * Authors: + *  Stefan Hajnoczi   <stefanha@linux.vnet.ibm.com> + * + * This work is licensed under the terms of the GNU LGPL, version 2 or later. + * See the COPYING.LIB file in the top-level directory. + * + */ + +#ifndef VHOST_SCSI_H +#define VHOST_SCSI_H + +#include "qemu-common.h" +#include "hw/qdev.h" +#include "hw/virtio/virtio-scsi.h" +#include "hw/virtio/vhost.h" + +/* + * Used by QEMU userspace to ensure a consistent vhost-scsi ABI. + * + * ABI Rev 0: July 2012 version starting point for v3.6-rc merge candidate + + *            RFC-v2 vhost-scsi userspace.  Add GET_ABI_VERSION ioctl usage + * ABI Rev 1: January 2013. Ignore vhost_tpgt filed in struct vhost_scsi_target. + * 	      All the targets under vhost_wwpn can be seen and used by guest. + */ + +#define VHOST_SCSI_ABI_VERSION 1 + +/* TODO #include <linux/vhost.h> properly */ +/* For VHOST_SCSI_SET_ENDPOINT/VHOST_SCSI_CLEAR_ENDPOINT ioctl */ +struct vhost_scsi_target { +    int abi_version; +    char vhost_wwpn[224]; +    unsigned short vhost_tpgt; +    unsigned short reserved; +}; + +enum vhost_scsi_vq_list { +    VHOST_SCSI_VQ_CONTROL = 0, +    VHOST_SCSI_VQ_EVENT = 1, +    VHOST_SCSI_VQ_NUM_FIXED = 2, +}; + +#define VHOST_VIRTIO 0xAF +#define VHOST_SCSI_SET_ENDPOINT _IOW(VHOST_VIRTIO, 0x40, struct vhost_scsi_target) +#define VHOST_SCSI_CLEAR_ENDPOINT _IOW(VHOST_VIRTIO, 0x41, struct vhost_scsi_target) +#define VHOST_SCSI_GET_ABI_VERSION _IOW(VHOST_VIRTIO, 0x42, int) + +#define TYPE_VHOST_SCSI "vhost-scsi" +#define VHOST_SCSI(obj) \ +        OBJECT_CHECK(VHostSCSI, (obj), TYPE_VHOST_SCSI) + +typedef struct VHostSCSI { +    VirtIOSCSICommon parent_obj; + +    Error *migration_blocker; + +    struct vhost_dev dev; +    int32_t bootindex; +    int channel; +    int target; +    int lun; +} VHostSCSI; + +#endif diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h new file mode 100644 index 00000000..dd510509 --- /dev/null +++ b/include/hw/virtio/vhost.h @@ -0,0 +1,84 @@ +#ifndef VHOST_H +#define VHOST_H + +#include "hw/hw.h" +#include "hw/virtio/vhost-backend.h" +#include "hw/virtio/virtio.h" +#include "exec/memory.h" + +/* Generic structures common for any vhost based device. */ +struct vhost_virtqueue { +    int kick; +    int call; +    void *desc; +    void *avail; +    void *used; +    int num; +    unsigned long long used_phys; +    unsigned used_size; +    void *ring; +    unsigned long long ring_phys; +    unsigned ring_size; +    EventNotifier masked_notifier; +}; + +typedef unsigned long vhost_log_chunk_t; +#define VHOST_LOG_PAGE 0x1000 +#define VHOST_LOG_BITS (8 * sizeof(vhost_log_chunk_t)) +#define VHOST_LOG_CHUNK (VHOST_LOG_PAGE * VHOST_LOG_BITS) +#define VHOST_INVALID_FEATURE_BIT   (0xff) + +struct vhost_log { +    unsigned long long size; +    int refcnt; +    vhost_log_chunk_t log[0]; +}; + +struct vhost_memory; +struct vhost_dev { +    MemoryListener memory_listener; +    struct vhost_memory *mem; +    int n_mem_sections; +    MemoryRegionSection *mem_sections; +    struct vhost_virtqueue *vqs; +    int nvqs; +    /* the first virtqueue which would be used by this vhost dev */ +    int vq_index; +    unsigned long long features; +    unsigned long long acked_features; +    unsigned long long backend_features; +    bool started; +    bool log_enabled; +    unsigned long long log_size; +    Error *migration_blocker; +    bool memory_changed; +    hwaddr mem_changed_start_addr; +    hwaddr mem_changed_end_addr; +    const VhostOps *vhost_ops; +    void *opaque; +    struct vhost_log *log; +}; + +int vhost_dev_init(struct vhost_dev *hdev, void *opaque, +                   VhostBackendType backend_type); +void vhost_dev_cleanup(struct vhost_dev *hdev); +bool vhost_dev_query(struct vhost_dev *hdev, VirtIODevice *vdev); +int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev); +void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev); +int vhost_dev_enable_notifiers(struct vhost_dev *hdev, VirtIODevice *vdev); +void vhost_dev_disable_notifiers(struct vhost_dev *hdev, VirtIODevice *vdev); + +/* Test and clear masked event pending status. + * Should be called after unmask to avoid losing events. + */ +bool vhost_virtqueue_pending(struct vhost_dev *hdev, int n); + +/* Mask/unmask events from this vq. + */ +void vhost_virtqueue_mask(struct vhost_dev *hdev, VirtIODevice *vdev, int n, +                          bool mask); +uint64_t vhost_get_features(struct vhost_dev *hdev, const int *feature_bits, +                            uint64_t features); +void vhost_ack_features(struct vhost_dev *hdev, const int *feature_bits, +                        uint64_t features); +#endif diff --git a/include/hw/virtio/virtio-9p.h b/include/hw/virtio/virtio-9p.h new file mode 100644 index 00000000..65789db1 --- /dev/null +++ b/include/hw/virtio/virtio-9p.h @@ -0,0 +1,24 @@ +/* + * Virtio 9p + * + * Copyright IBM, Corp. 2010 + * + * Authors: + *  Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> + * + * This work is licensed under the terms of the GNU GPL, version 2.  See + * the COPYING file in the top-level directory. + * + */ + +#ifndef QEMU_VIRTIO_9P_DEVICE_H +#define QEMU_VIRTIO_9P_DEVICE_H + +typedef struct V9fsConf +{ +    /* tag name for the device */ +    char *tag; +    char *fsdev_id; +} V9fsConf; + +#endif diff --git a/include/hw/virtio/virtio-access.h b/include/hw/virtio/virtio-access.h new file mode 100644 index 00000000..8aec843c --- /dev/null +++ b/include/hw/virtio/virtio-access.h @@ -0,0 +1,196 @@ +/* + * Virtio Accessor Support: In case your target can change endian. + * + * Copyright IBM, Corp. 2013 + * + * Authors: + *  Rusty Russell   <rusty@au.ibm.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + */ +#ifndef _QEMU_VIRTIO_ACCESS_H +#define _QEMU_VIRTIO_ACCESS_H +#include "hw/virtio/virtio.h" +#include "exec/address-spaces.h" + +static inline bool virtio_access_is_big_endian(VirtIODevice *vdev) +{ +    if (virtio_vdev_has_feature(vdev, VIRTIO_F_VERSION_1)) { +        /* Devices conforming to VIRTIO 1.0 or later are always LE. */ +        return false; +    } +#if defined(TARGET_IS_BIENDIAN) +    return virtio_is_big_endian(vdev); +#elif defined(TARGET_WORDS_BIGENDIAN) +    return true; +#else +    return false; +#endif +} + +static inline bool virtio_legacy_is_cross_endian(VirtIODevice *vdev) +{ +#ifdef TARGET_IS_BIENDIAN +#ifdef HOST_WORDS_BIGENDIAN +    return !virtio_is_big_endian(vdev); +#else +    return virtio_is_big_endian(vdev); +#endif +#else +    return false; +#endif +} + +static inline uint16_t virtio_lduw_phys(VirtIODevice *vdev, hwaddr pa) +{ +    if (virtio_access_is_big_endian(vdev)) { +        return lduw_be_phys(&address_space_memory, pa); +    } +    return lduw_le_phys(&address_space_memory, pa); +} + +static inline uint32_t virtio_ldl_phys(VirtIODevice *vdev, hwaddr pa) +{ +    if (virtio_access_is_big_endian(vdev)) { +        return ldl_be_phys(&address_space_memory, pa); +    } +    return ldl_le_phys(&address_space_memory, pa); +} + +static inline uint64_t virtio_ldq_phys(VirtIODevice *vdev, hwaddr pa) +{ +    if (virtio_access_is_big_endian(vdev)) { +        return ldq_be_phys(&address_space_memory, pa); +    } +    return ldq_le_phys(&address_space_memory, pa); +} + +static inline void virtio_stw_phys(VirtIODevice *vdev, hwaddr pa, +                                   uint16_t value) +{ +    if (virtio_access_is_big_endian(vdev)) { +        stw_be_phys(&address_space_memory, pa, value); +    } else { +        stw_le_phys(&address_space_memory, pa, value); +    } +} + +static inline void virtio_stl_phys(VirtIODevice *vdev, hwaddr pa, +                                   uint32_t value) +{ +    if (virtio_access_is_big_endian(vdev)) { +        stl_be_phys(&address_space_memory, pa, value); +    } else { +        stl_le_phys(&address_space_memory, pa, value); +    } +} + +static inline void virtio_stw_p(VirtIODevice *vdev, void *ptr, uint16_t v) +{ +    if (virtio_access_is_big_endian(vdev)) { +        stw_be_p(ptr, v); +    } else { +        stw_le_p(ptr, v); +    } +} + +static inline void virtio_stl_p(VirtIODevice *vdev, void *ptr, uint32_t v) +{ +    if (virtio_access_is_big_endian(vdev)) { +        stl_be_p(ptr, v); +    } else { +        stl_le_p(ptr, v); +    } +} + +static inline void virtio_stq_p(VirtIODevice *vdev, void *ptr, uint64_t v) +{ +    if (virtio_access_is_big_endian(vdev)) { +        stq_be_p(ptr, v); +    } else { +        stq_le_p(ptr, v); +    } +} + +static inline int virtio_lduw_p(VirtIODevice *vdev, const void *ptr) +{ +    if (virtio_access_is_big_endian(vdev)) { +        return lduw_be_p(ptr); +    } else { +        return lduw_le_p(ptr); +    } +} + +static inline int virtio_ldl_p(VirtIODevice *vdev, const void *ptr) +{ +    if (virtio_access_is_big_endian(vdev)) { +        return ldl_be_p(ptr); +    } else { +        return ldl_le_p(ptr); +    } +} + +static inline uint64_t virtio_ldq_p(VirtIODevice *vdev, const void *ptr) +{ +    if (virtio_access_is_big_endian(vdev)) { +        return ldq_be_p(ptr); +    } else { +        return ldq_le_p(ptr); +    } +} + +static inline bool virtio_needs_swap(VirtIODevice *vdev) +{ +#ifdef HOST_WORDS_BIGENDIAN +    return virtio_access_is_big_endian(vdev) ? false : true; +#else +    return virtio_access_is_big_endian(vdev) ? true : false; +#endif +} + +static inline uint16_t virtio_tswap16(VirtIODevice *vdev, uint16_t s) +{ +#ifdef HOST_WORDS_BIGENDIAN +    return virtio_access_is_big_endian(vdev) ? s : bswap16(s); +#else +    return virtio_access_is_big_endian(vdev) ? bswap16(s) : s; +#endif +} + +static inline void virtio_tswap16s(VirtIODevice *vdev, uint16_t *s) +{ +    *s = virtio_tswap16(vdev, *s); +} + +static inline uint32_t virtio_tswap32(VirtIODevice *vdev, uint32_t s) +{ +#ifdef HOST_WORDS_BIGENDIAN +    return virtio_access_is_big_endian(vdev) ? s : bswap32(s); +#else +    return virtio_access_is_big_endian(vdev) ? bswap32(s) : s; +#endif +} + +static inline void virtio_tswap32s(VirtIODevice *vdev, uint32_t *s) +{ +    *s = virtio_tswap32(vdev, *s); +} + +static inline uint64_t virtio_tswap64(VirtIODevice *vdev, uint64_t s) +{ +#ifdef HOST_WORDS_BIGENDIAN +    return virtio_access_is_big_endian(vdev) ? s : bswap64(s); +#else +    return virtio_access_is_big_endian(vdev) ? bswap64(s) : s; +#endif +} + +static inline void virtio_tswap64s(VirtIODevice *vdev, uint64_t *s) +{ +    *s = virtio_tswap64(vdev, *s); +} +#endif /* _QEMU_VIRTIO_ACCESS_H */ diff --git a/include/hw/virtio/virtio-balloon.h b/include/hw/virtio/virtio-balloon.h new file mode 100644 index 00000000..09c2ce4d --- /dev/null +++ b/include/hw/virtio/virtio-balloon.h @@ -0,0 +1,48 @@ +/* + * Virtio Support + * + * Copyright IBM, Corp. 2007-2008 + * + * Authors: + *  Anthony Liguori   <aliguori@us.ibm.com> + *  Rusty Russell     <rusty@rustcorp.com.au> + * + * This work is licensed under the terms of the GNU GPL, version 2.  See + * the COPYING file in the top-level directory. + * + */ + +#ifndef _QEMU_VIRTIO_BALLOON_H +#define _QEMU_VIRTIO_BALLOON_H + +#include "standard-headers/linux/virtio_balloon.h" +#include "hw/virtio/virtio.h" +#include "hw/pci/pci.h" + +#define TYPE_VIRTIO_BALLOON "virtio-balloon-device" +#define VIRTIO_BALLOON(obj) \ +        OBJECT_CHECK(VirtIOBalloon, (obj), TYPE_VIRTIO_BALLOON) + +typedef struct virtio_balloon_stat VirtIOBalloonStat; + +typedef struct virtio_balloon_stat_modern { +       uint16_t tag; +       uint8_t reserved[6]; +       uint64_t val; +} VirtIOBalloonStatModern; + +typedef struct VirtIOBalloon { +    VirtIODevice parent_obj; +    VirtQueue *ivq, *dvq, *svq; +    uint32_t num_pages; +    uint32_t actual; +    uint64_t stats[VIRTIO_BALLOON_S_NR]; +    VirtQueueElement stats_vq_elem; +    size_t stats_vq_offset; +    QEMUTimer *stats_timer; +    int64_t stats_last_update; +    int64_t stats_poll_interval; +    uint32_t host_features; +} VirtIOBalloon; + +#endif diff --git a/include/hw/virtio/virtio-blk.h b/include/hw/virtio/virtio-blk.h new file mode 100644 index 00000000..6bf5905c --- /dev/null +++ b/include/hw/virtio/virtio-blk.h @@ -0,0 +1,92 @@ +/* + * Virtio Block Device + * + * Copyright IBM, Corp. 2007 + * + * Authors: + *  Anthony Liguori   <aliguori@us.ibm.com> + * + * This work is licensed under the terms of the GNU GPL, version 2.  See + * the COPYING file in the top-level directory. + * + */ + +#ifndef _QEMU_VIRTIO_BLK_H +#define _QEMU_VIRTIO_BLK_H + +#include "standard-headers/linux/virtio_blk.h" +#include "hw/virtio/virtio.h" +#include "hw/block/block.h" +#include "sysemu/iothread.h" +#include "sysemu/block-backend.h" + +#define TYPE_VIRTIO_BLK "virtio-blk-device" +#define VIRTIO_BLK(obj) \ +        OBJECT_CHECK(VirtIOBlock, (obj), TYPE_VIRTIO_BLK) + +/* This is the last element of the write scatter-gather list */ +struct virtio_blk_inhdr +{ +    unsigned char status; +}; + +struct VirtIOBlkConf +{ +    BlockConf conf; +    IOThread *iothread; +    char *serial; +    uint32_t scsi; +    uint32_t config_wce; +    uint32_t data_plane; +    uint32_t request_merging; +}; + +struct VirtIOBlockDataPlane; + +struct VirtIOBlockReq; +typedef struct VirtIOBlock { +    VirtIODevice parent_obj; +    BlockBackend *blk; +    VirtQueue *vq; +    void *rq; +    QEMUBH *bh; +    VirtIOBlkConf conf; +    unsigned short sector_mask; +    bool original_wce; +    VMChangeStateEntry *change; +    /* Function to push to vq and notify guest */ +    void (*complete_request)(struct VirtIOBlockReq *req, unsigned char status); +    Notifier migration_state_notifier; +    struct VirtIOBlockDataPlane *dataplane; +} VirtIOBlock; + +typedef struct VirtIOBlockReq { +    int64_t sector_num; +    VirtIOBlock *dev; +    VirtQueueElement elem; +    struct virtio_blk_inhdr *in; +    struct virtio_blk_outhdr out; +    QEMUIOVector qiov; +    size_t in_len; +    struct VirtIOBlockReq *next; +    struct VirtIOBlockReq *mr_next; +    BlockAcctCookie acct; +} VirtIOBlockReq; + +#define VIRTIO_BLK_MAX_MERGE_REQS 32 + +typedef struct MultiReqBuffer { +    VirtIOBlockReq *reqs[VIRTIO_BLK_MAX_MERGE_REQS]; +    unsigned int num_reqs; +    bool is_write; +} MultiReqBuffer; + +VirtIOBlockReq *virtio_blk_alloc_request(VirtIOBlock *s); + +void virtio_blk_free_request(VirtIOBlockReq *req); + +void virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb); + +void virtio_blk_submit_multireq(BlockBackend *blk, MultiReqBuffer *mrb); + +#endif diff --git a/include/hw/virtio/virtio-bus.h b/include/hw/virtio/virtio-bus.h new file mode 100644 index 00000000..8811415f --- /dev/null +++ b/include/hw/virtio/virtio-bus.h @@ -0,0 +1,106 @@ +/* + * VirtioBus + * + *  Copyright (C) 2012 : GreenSocs Ltd + *      http://www.greensocs.com/ , email: info@greensocs.com + * + *  Developed by : + *  Frederic Konrad   <fred.konrad@greensocs.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, see <http://www.gnu.org/licenses/>. + * + */ + +#ifndef VIRTIO_BUS_H +#define VIRTIO_BUS_H + +#include "hw/qdev.h" +#include "sysemu/sysemu.h" +#include "hw/virtio/virtio.h" + +#define TYPE_VIRTIO_BUS "virtio-bus" +#define VIRTIO_BUS_GET_CLASS(obj) \ +        OBJECT_GET_CLASS(VirtioBusClass, obj, TYPE_VIRTIO_BUS) +#define VIRTIO_BUS_CLASS(klass) \ +        OBJECT_CLASS_CHECK(VirtioBusClass, klass, TYPE_VIRTIO_BUS) +#define VIRTIO_BUS(obj) OBJECT_CHECK(VirtioBusState, (obj), TYPE_VIRTIO_BUS) + +typedef struct VirtioBusState VirtioBusState; + +typedef struct VirtioBusClass { +    /* This is what a VirtioBus must implement */ +    BusClass parent; +    void (*notify)(DeviceState *d, uint16_t vector); +    void (*save_config)(DeviceState *d, QEMUFile *f); +    void (*save_queue)(DeviceState *d, int n, QEMUFile *f); +    int (*load_config)(DeviceState *d, QEMUFile *f); +    int (*load_queue)(DeviceState *d, int n, QEMUFile *f); +    int (*load_done)(DeviceState *d, QEMUFile *f); +    bool (*query_guest_notifiers)(DeviceState *d); +    int (*set_guest_notifiers)(DeviceState *d, int nvqs, bool assign); +    int (*set_host_notifier)(DeviceState *d, int n, bool assigned); +    void (*vmstate_change)(DeviceState *d, bool running); +    /* +     * transport independent init function. +     * This is called by virtio-bus just after the device is plugged. +     */ +    void (*device_plugged)(DeviceState *d, Error **errp); +    /* +     * transport independent exit function. +     * This is called by virtio-bus just before the device is unplugged. +     */ +    void (*device_unplugged)(DeviceState *d); +    int (*query_nvectors)(DeviceState *d); +    /* +     * Does the transport have variable vring alignment? +     * (ie can it ever call virtio_queue_set_align()?) +     * Note that changing this will break migration for this transport. +     */ +    bool has_variable_vring_alignment; +} VirtioBusClass; + +struct VirtioBusState { +    BusState parent_obj; +}; + +void virtio_bus_device_plugged(VirtIODevice *vdev, Error **errp); +void virtio_bus_reset(VirtioBusState *bus); +void virtio_bus_device_unplugged(VirtIODevice *bus); +/* Get the device id of the plugged device. */ +uint16_t virtio_bus_get_vdev_id(VirtioBusState *bus); +/* Get the config_len field of the plugged device. */ +size_t virtio_bus_get_vdev_config_len(VirtioBusState *bus); +/* Get the features of the plugged device. */ +uint32_t virtio_bus_get_vdev_features(VirtioBusState *bus, +                                    uint32_t requested_features); +/* Get bad features of the plugged device. */ +uint32_t virtio_bus_get_vdev_bad_features(VirtioBusState *bus); +/* Get config of the plugged device. */ +void virtio_bus_get_vdev_config(VirtioBusState *bus, uint8_t *config); +/* Set config of the plugged device. */ +void virtio_bus_set_vdev_config(VirtioBusState *bus, uint8_t *config); + +static inline VirtIODevice *virtio_bus_get_device(VirtioBusState *bus) +{ +    BusState *qbus = &bus->parent_obj; +    BusChild *kid = QTAILQ_FIRST(&qbus->children); +    DeviceState *qdev = kid ? kid->child : NULL; + +    /* This is used on the data path, the cast is guaranteed +     * to succeed by the qdev machinery. +     */ +    return (VirtIODevice *)qdev; +} + +#endif /* VIRTIO_BUS_H */ diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h new file mode 100644 index 00000000..88967614 --- /dev/null +++ b/include/hw/virtio/virtio-gpu.h @@ -0,0 +1,142 @@ +/* + * Virtio GPU Device + * + * Copyright Red Hat, Inc. 2013-2014 + * + * Authors: + *     Dave Airlie <airlied@redhat.com> + *     Gerd Hoffmann <kraxel@redhat.com> + * + * This work is licensed under the terms of the GNU GPL, version 2. + * See the COPYING file in the top-level directory. + */ + +#ifndef _QEMU_VIRTIO_VGA_H +#define _QEMU_VIRTIO_VGA_H + +#include "qemu/queue.h" +#include "ui/qemu-pixman.h" +#include "ui/console.h" +#include "hw/virtio/virtio.h" +#include "hw/pci/pci.h" + +#include "standard-headers/linux/virtio_gpu.h" +#define TYPE_VIRTIO_GPU "virtio-gpu-device" +#define VIRTIO_GPU(obj)                                        \ +        OBJECT_CHECK(VirtIOGPU, (obj), TYPE_VIRTIO_GPU) + +#define VIRTIO_ID_GPU 16 + +#define VIRTIO_GPU_MAX_SCANOUT 4 + +struct virtio_gpu_simple_resource { +    uint32_t resource_id; +    uint32_t width; +    uint32_t height; +    uint32_t format; +    struct iovec *iov; +    unsigned int iov_cnt; +    uint32_t scanout_bitmask; +    pixman_image_t *image; +    QTAILQ_ENTRY(virtio_gpu_simple_resource) next; +}; + +struct virtio_gpu_scanout { +    QemuConsole *con; +    DisplaySurface *ds; +    uint32_t width, height; +    int x, y; +    int invalidate; +    uint32_t resource_id; +    QEMUCursor *current_cursor; +}; + +struct virtio_gpu_requested_state { +    uint32_t width, height; +    int x, y; +}; + +struct virtio_gpu_conf { +    uint32_t max_outputs; +}; + +struct virtio_gpu_ctrl_command { +    VirtQueueElement elem; +    VirtQueue *vq; +    struct virtio_gpu_ctrl_hdr cmd_hdr; +    uint32_t error; +    bool finished; +    QTAILQ_ENTRY(virtio_gpu_ctrl_command) next; +}; + +typedef struct VirtIOGPU { +    VirtIODevice parent_obj; + +    QEMUBH *ctrl_bh; +    QEMUBH *cursor_bh; +    VirtQueue *ctrl_vq; +    VirtQueue *cursor_vq; + +    int enable; + +    int config_size; +    DeviceState *qdev; + +    QTAILQ_HEAD(, virtio_gpu_simple_resource) reslist; +    QTAILQ_HEAD(, virtio_gpu_ctrl_command) fenceq; + +    struct virtio_gpu_scanout scanout[VIRTIO_GPU_MAX_SCANOUT]; +    struct virtio_gpu_requested_state req_state[VIRTIO_GPU_MAX_SCANOUT]; + +    struct virtio_gpu_conf conf; +    int enabled_output_bitmask; +    struct virtio_gpu_config virtio_config; + +    QEMUTimer *fence_poll; +    QEMUTimer *print_stats; + +    struct { +        uint32_t inflight; +        uint32_t max_inflight; +        uint32_t requests; +        uint32_t req_3d; +        uint32_t bytes_3d; +    } stats; +} VirtIOGPU; + +extern const GraphicHwOps virtio_gpu_ops; + +/* to share between PCI and VGA */ +#define DEFINE_VIRTIO_GPU_PCI_PROPERTIES(_state)               \ +    DEFINE_PROP_BIT("ioeventfd", _state, flags,                \ +                    VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, false), \ +    DEFINE_PROP_UINT32("vectors", _state, nvectors, 3) + +#define VIRTIO_GPU_FILL_CMD(out) do {                                   \ +        size_t s;                                                       \ +        s = iov_to_buf(cmd->elem.out_sg, cmd->elem.out_num, 0,          \ +                       &out, sizeof(out));                              \ +        if (s != sizeof(out)) {                                         \ +            qemu_log_mask(LOG_GUEST_ERROR,                              \ +                          "%s: command size incorrect %zu vs %zu\n",    \ +                          __func__, s, sizeof(out));                    \ +            return;                                                     \ +        }                                                               \ +    } while (0) + +/* virtio-gpu.c */ +void virtio_gpu_ctrl_response(VirtIOGPU *g, +                              struct virtio_gpu_ctrl_command *cmd, +                              struct virtio_gpu_ctrl_hdr *resp, +                              size_t resp_len); +void virtio_gpu_ctrl_response_nodata(VirtIOGPU *g, +                                     struct virtio_gpu_ctrl_command *cmd, +                                     enum virtio_gpu_ctrl_type type); +void virtio_gpu_get_display_info(VirtIOGPU *g, +                                 struct virtio_gpu_ctrl_command *cmd); +int virtio_gpu_create_mapping_iov(struct virtio_gpu_resource_attach_backing *ab, +                                  struct virtio_gpu_ctrl_command *cmd, +                                  struct iovec **iov); +void virtio_gpu_cleanup_mapping_iov(struct iovec *iov, uint32_t count); + +#endif diff --git a/include/hw/virtio/virtio-input.h b/include/hw/virtio/virtio-input.h new file mode 100644 index 00000000..af1c207a --- /dev/null +++ b/include/hw/virtio/virtio-input.h @@ -0,0 +1,119 @@ +#ifndef _QEMU_VIRTIO_INPUT_H +#define _QEMU_VIRTIO_INPUT_H + +#include "ui/input.h" + +/* ----------------------------------------------------------------- */ +/* virtio input protocol                                             */ + +#include "standard-headers/linux/virtio_ids.h" +#include "standard-headers/linux/virtio_input.h" + +typedef struct virtio_input_absinfo virtio_input_absinfo; +typedef struct virtio_input_config virtio_input_config; +typedef struct virtio_input_event virtio_input_event; + +#if defined(HOST_WORDS_BIGENDIAN) +# define const_le32(_x)                          \ +    (((_x & 0x000000ffU) << 24) |                \ +     ((_x & 0x0000ff00U) <<  8) |                \ +     ((_x & 0x00ff0000U) >>  8) |                \ +     ((_x & 0xff000000U) >> 24)) +# define const_le16(_x)                          \ +    (((_x & 0x00ff) << 8) |                      \ +     ((_x & 0xff00) >> 8)) +#else +# define const_le32(_x) (_x) +# define const_le16(_x) (_x) +#endif + +/* ----------------------------------------------------------------- */ +/* qemu internals                                                    */ + +#define TYPE_VIRTIO_INPUT "virtio-input-device" +#define VIRTIO_INPUT(obj) \ +        OBJECT_CHECK(VirtIOInput, (obj), TYPE_VIRTIO_INPUT) +#define VIRTIO_INPUT_GET_PARENT_CLASS(obj) \ +        OBJECT_GET_PARENT_CLASS(obj, TYPE_VIRTIO_INPUT) +#define VIRTIO_INPUT_GET_CLASS(obj) \ +        OBJECT_GET_CLASS(VirtIOInputClass, obj, TYPE_VIRTIO_INPUT) +#define VIRTIO_INPUT_CLASS(klass) \ +        OBJECT_CLASS_CHECK(VirtIOInputClass, klass, TYPE_VIRTIO_INPUT) + +#define TYPE_VIRTIO_INPUT_HID "virtio-input-hid-device" +#define TYPE_VIRTIO_KEYBOARD  "virtio-keyboard-device" +#define TYPE_VIRTIO_MOUSE     "virtio-mouse-device" +#define TYPE_VIRTIO_TABLET    "virtio-tablet-device" + +#define VIRTIO_INPUT_HID(obj) \ +        OBJECT_CHECK(VirtIOInputHID, (obj), TYPE_VIRTIO_INPUT_HID) +#define VIRTIO_INPUT_HID_GET_PARENT_CLASS(obj) \ +        OBJECT_GET_PARENT_CLASS(obj, TYPE_VIRTIO_INPUT_HID) + +#define TYPE_VIRTIO_INPUT_HOST   "virtio-input-host-device" +#define VIRTIO_INPUT_HOST(obj) \ +        OBJECT_CHECK(VirtIOInputHost, (obj), TYPE_VIRTIO_INPUT_HOST) +#define VIRTIO_INPUT_HOST_GET_PARENT_CLASS(obj) \ +        OBJECT_GET_PARENT_CLASS(obj, TYPE_VIRTIO_INPUT_HOST) + +typedef struct VirtIOInput VirtIOInput; +typedef struct VirtIOInputClass VirtIOInputClass; +typedef struct VirtIOInputConfig VirtIOInputConfig; +typedef struct VirtIOInputHID VirtIOInputHID; +typedef struct VirtIOInputHost VirtIOInputHost; + +struct VirtIOInputConfig { +    virtio_input_config               config; +    QTAILQ_ENTRY(VirtIOInputConfig)   node; +}; + +struct VirtIOInput { +    VirtIODevice                      parent_obj; +    uint8_t                           cfg_select; +    uint8_t                           cfg_subsel; +    uint32_t                          cfg_size; +    QTAILQ_HEAD(, VirtIOInputConfig)  cfg_list; +    VirtQueue                         *evt, *sts; +    char                              *serial; + +    virtio_input_event                *queue; +    uint32_t                          qindex, qsize; + +    bool                              active; +}; + +struct VirtIOInputClass { +    /*< private >*/ +    VirtioDeviceClass parent; +    /*< public >*/ + +    DeviceRealize realize; +    DeviceUnrealize unrealize; +    void (*change_active)(VirtIOInput *vinput); +    void (*handle_status)(VirtIOInput *vinput, virtio_input_event *event); +}; + +struct VirtIOInputHID { +    VirtIOInput                       parent_obj; +    char                              *display; +    uint32_t                          head; +    QemuInputHandler                  *handler; +    QemuInputHandlerState             *hs; +    int                               ledstate; +}; + +struct VirtIOInputHost { +    VirtIOInput                       parent_obj; +    char                              *evdev; +    int                               fd; +}; + +void virtio_input_send(VirtIOInput *vinput, virtio_input_event *event); +void virtio_input_init_config(VirtIOInput *vinput, +                              virtio_input_config *config); +void virtio_input_add_config(VirtIOInput *vinput, +                             virtio_input_config *config); +void virtio_input_idstr_config(VirtIOInput *vinput, +                               uint8_t select, const char *string); + +#endif /* _QEMU_VIRTIO_INPUT_H */ diff --git a/include/hw/virtio/virtio-net.h b/include/hw/virtio/virtio-net.h new file mode 100644 index 00000000..60b11d5c --- /dev/null +++ b/include/hw/virtio/virtio-net.h @@ -0,0 +1,103 @@ +/* + * Virtio Network Device + * + * Copyright IBM, Corp. 2007 + * + * Authors: + *  Anthony Liguori   <aliguori@us.ibm.com> + * + * This work is licensed under the terms of the GNU GPL, version 2.  See + * the COPYING file in the top-level directory. + * + */ + +#ifndef _QEMU_VIRTIO_NET_H +#define _QEMU_VIRTIO_NET_H + +#include "standard-headers/linux/virtio_net.h" +#include "hw/virtio/virtio.h" + +#define TYPE_VIRTIO_NET "virtio-net-device" +#define VIRTIO_NET(obj) \ +        OBJECT_CHECK(VirtIONet, (obj), TYPE_VIRTIO_NET) + +#define TX_TIMER_INTERVAL 150000 /* 150 us */ + +/* Limit the number of packets that can be sent via a single flush + * of the TX queue.  This gives us a guaranteed exit condition and + * ensures fairness in the io path.  256 conveniently matches the + * length of the TX queue and shows a good balance of performance + * and latency. */ +#define TX_BURST 256 + +typedef struct virtio_net_conf +{ +    uint32_t txtimer; +    int32_t txburst; +    char *tx; +} virtio_net_conf; + +/* Maximum packet size we can receive from tap device: header + 64k */ +#define VIRTIO_NET_MAX_BUFSIZE (sizeof(struct virtio_net_hdr) + (64 << 10)) + +typedef struct VirtIONetQueue { +    VirtQueue *rx_vq; +    VirtQueue *tx_vq; +    QEMUTimer *tx_timer; +    QEMUBH *tx_bh; +    int tx_waiting; +    struct { +        VirtQueueElement elem; +        ssize_t len; +    } async_tx; +    struct VirtIONet *n; +} VirtIONetQueue; + +typedef struct VirtIONet { +    VirtIODevice parent_obj; +    uint8_t mac[ETH_ALEN]; +    uint16_t status; +    VirtIONetQueue *vqs; +    VirtQueue *ctrl_vq; +    NICState *nic; +    uint32_t tx_timeout; +    int32_t tx_burst; +    uint32_t has_vnet_hdr; +    size_t host_hdr_len; +    size_t guest_hdr_len; +    uint32_t host_features; +    uint8_t has_ufo; +    int mergeable_rx_bufs; +    uint8_t promisc; +    uint8_t allmulti; +    uint8_t alluni; +    uint8_t nomulti; +    uint8_t nouni; +    uint8_t nobcast; +    uint8_t vhost_started; +    struct { +        uint32_t in_use; +        uint32_t first_multi; +        uint8_t multi_overflow; +        uint8_t uni_overflow; +        uint8_t *macs; +    } mac_table; +    uint32_t *vlans; +    virtio_net_conf net_conf; +    NICConf nic_conf; +    DeviceState *qdev; +    int multiqueue; +    uint16_t max_queues; +    uint16_t curr_queues; +    size_t config_size; +    char *netclient_name; +    char *netclient_type; +    uint64_t curr_guest_offloads; +    QEMUTimer *announce_timer; +    int announce_counter; +} VirtIONet; + +void virtio_net_set_netclient_name(VirtIONet *n, const char *name, +                                   const char *type); + +#endif diff --git a/include/hw/virtio/virtio-rng.h b/include/hw/virtio/virtio-rng.h new file mode 100644 index 00000000..3f07de70 --- /dev/null +++ b/include/hw/virtio/virtio-rng.h @@ -0,0 +1,50 @@ +/* + * Virtio RNG Support + * + * Copyright Red Hat, Inc. 2012 + * Copyright Amit Shah <amit.shah@redhat.com> + * + * This work is licensed under the terms of the GNU GPL, version 2 or + * (at your option) any later version.  See the COPYING file in the + * top-level directory. + */ + +#ifndef _QEMU_VIRTIO_RNG_H +#define _QEMU_VIRTIO_RNG_H + +#include "sysemu/rng.h" +#include "sysemu/rng-random.h" +#include "standard-headers/linux/virtio_rng.h" + +#define TYPE_VIRTIO_RNG "virtio-rng-device" +#define VIRTIO_RNG(obj) \ +        OBJECT_CHECK(VirtIORNG, (obj), TYPE_VIRTIO_RNG) +#define VIRTIO_RNG_GET_PARENT_CLASS(obj) \ +        OBJECT_GET_PARENT_CLASS(obj, TYPE_VIRTIO_RNG) + +struct VirtIORNGConf { +    RngBackend *rng; +    uint64_t max_bytes; +    uint32_t period_ms; +    RndRandom *default_backend; +}; + +typedef struct VirtIORNG { +    VirtIODevice parent_obj; + +    /* Only one vq - guest puts buffer(s) on it when it needs entropy */ +    VirtQueue *vq; + +    VirtIORNGConf conf; + +    RngBackend *rng; + +    /* We purposefully don't migrate this state.  The quota will reset on the +     * destination as a result.  Rate limiting is host state, not guest state. +     */ +    QEMUTimer *rate_limit_timer; +    int64_t quota_remaining; +    bool activate_timer; +} VirtIORNG; + +#endif diff --git a/include/hw/virtio/virtio-scsi.h b/include/hw/virtio/virtio-scsi.h new file mode 100644 index 00000000..088fe9f4 --- /dev/null +++ b/include/hw/virtio/virtio-scsi.h @@ -0,0 +1,166 @@ +/* + * Virtio SCSI HBA + * + * Copyright IBM, Corp. 2010 + * + * Authors: + *  Stefan Hajnoczi    <stefanha@linux.vnet.ibm.com> + * + * This work is licensed under the terms of the GNU GPL, version 2.  See + * the COPYING file in the top-level directory. + * + */ + +#ifndef _QEMU_VIRTIO_SCSI_H +#define _QEMU_VIRTIO_SCSI_H + +/* Override CDB/sense data size: they are dynamic (guest controlled) in QEMU */ +#define VIRTIO_SCSI_CDB_SIZE 0 +#define VIRTIO_SCSI_SENSE_SIZE 0 +#include "standard-headers/linux/virtio_scsi.h" +#include "hw/virtio/virtio.h" +#include "hw/pci/pci.h" +#include "hw/scsi/scsi.h" +#include "sysemu/iothread.h" +#include "hw/virtio/dataplane/vring.h" + +#define TYPE_VIRTIO_SCSI_COMMON "virtio-scsi-common" +#define VIRTIO_SCSI_COMMON(obj) \ +        OBJECT_CHECK(VirtIOSCSICommon, (obj), TYPE_VIRTIO_SCSI_COMMON) + +#define TYPE_VIRTIO_SCSI "virtio-scsi-device" +#define VIRTIO_SCSI(obj) \ +        OBJECT_CHECK(VirtIOSCSI, (obj), TYPE_VIRTIO_SCSI) + +#define VIRTIO_SCSI_VQ_SIZE     128 +#define VIRTIO_SCSI_MAX_CHANNEL 0 +#define VIRTIO_SCSI_MAX_TARGET  255 +#define VIRTIO_SCSI_MAX_LUN     16383 + +typedef struct virtio_scsi_cmd_req VirtIOSCSICmdReq; +typedef struct virtio_scsi_cmd_resp VirtIOSCSICmdResp; +typedef struct virtio_scsi_ctrl_tmf_req VirtIOSCSICtrlTMFReq; +typedef struct virtio_scsi_ctrl_tmf_resp VirtIOSCSICtrlTMFResp; +typedef struct virtio_scsi_ctrl_an_req VirtIOSCSICtrlANReq; +typedef struct virtio_scsi_ctrl_an_resp VirtIOSCSICtrlANResp; +typedef struct virtio_scsi_event VirtIOSCSIEvent; +typedef struct virtio_scsi_config VirtIOSCSIConfig; + +struct VirtIOSCSIConf { +    uint32_t num_queues; +    uint32_t max_sectors; +    uint32_t cmd_per_lun; +    char *vhostfd; +    char *wwpn; +    uint32_t boot_tpgt; +    IOThread *iothread; +}; + +struct VirtIOSCSI; + +typedef struct { +    struct VirtIOSCSI *parent; +    Vring vring; +    EventNotifier host_notifier; +    EventNotifier guest_notifier; +} VirtIOSCSIVring; + +typedef struct VirtIOSCSICommon { +    VirtIODevice parent_obj; +    VirtIOSCSIConf conf; + +    uint32_t sense_size; +    uint32_t cdb_size; +    VirtQueue *ctrl_vq; +    VirtQueue *event_vq; +    VirtQueue **cmd_vqs; +} VirtIOSCSICommon; + +typedef struct VirtIOSCSI { +    VirtIOSCSICommon parent_obj; + +    SCSIBus bus; +    int resetting; +    bool events_dropped; + +    /* Fields for dataplane below */ +    AioContext *ctx; /* one iothread per virtio-scsi-pci for now */ + +    /* Vring is used instead of vq in dataplane code, because of the underlying +     * memory layer thread safety */ +    VirtIOSCSIVring *ctrl_vring; +    VirtIOSCSIVring *event_vring; +    VirtIOSCSIVring **cmd_vrings; +    bool dataplane_started; +    bool dataplane_starting; +    bool dataplane_stopping; +    bool dataplane_disabled; +    bool dataplane_fenced; +    Error *blocker; +    Notifier migration_state_notifier; +    uint32_t host_features; +} VirtIOSCSI; + +typedef struct VirtIOSCSIReq { +    VirtIOSCSI *dev; +    VirtQueue *vq; +    QEMUSGList qsgl; +    QEMUIOVector resp_iov; + +    /* Note: +     * - fields before elem are initialized by virtio_scsi_init_req; +     * - elem is uninitialized at the time of allocation. +     * - fields after elem are zeroed by virtio_scsi_init_req. +     * */ + +    VirtQueueElement elem; +    /* Set by dataplane code. */ +    VirtIOSCSIVring *vring; + +    union { +        /* Used for two-stage request submission */ +        QTAILQ_ENTRY(VirtIOSCSIReq) next; + +        /* Used for cancellation of request during TMFs */ +        int remaining; +    }; + +    SCSIRequest *sreq; +    size_t resp_size; +    enum SCSIXferMode mode; +    union { +        VirtIOSCSICmdResp     cmd; +        VirtIOSCSICtrlTMFResp tmf; +        VirtIOSCSICtrlANResp  an; +        VirtIOSCSIEvent       event; +    } resp; +    union { +        VirtIOSCSICmdReq      cmd; +        VirtIOSCSICtrlTMFReq  tmf; +        VirtIOSCSICtrlANReq   an; +    } req; +} VirtIOSCSIReq; + +typedef void (*HandleOutput)(VirtIODevice *, VirtQueue *); + +void virtio_scsi_common_realize(DeviceState *dev, Error **errp, +                                HandleOutput ctrl, HandleOutput evt, +                                HandleOutput cmd); + +void virtio_scsi_common_unrealize(DeviceState *dev, Error **errp); +void virtio_scsi_handle_ctrl_req(VirtIOSCSI *s, VirtIOSCSIReq *req); +bool virtio_scsi_handle_cmd_req_prepare(VirtIOSCSI *s, VirtIOSCSIReq *req); +void virtio_scsi_handle_cmd_req_submit(VirtIOSCSI *s, VirtIOSCSIReq *req); +VirtIOSCSIReq *virtio_scsi_init_req(VirtIOSCSI *s, VirtQueue *vq); +void virtio_scsi_free_req(VirtIOSCSIReq *req); +void virtio_scsi_push_event(VirtIOSCSI *s, SCSIDevice *dev, +                            uint32_t event, uint32_t reason); + +void virtio_scsi_set_iothread(VirtIOSCSI *s, IOThread *iothread); +void virtio_scsi_dataplane_start(VirtIOSCSI *s); +void virtio_scsi_dataplane_stop(VirtIOSCSI *s); +void virtio_scsi_vring_push_notify(VirtIOSCSIReq *req); +VirtIOSCSIReq *virtio_scsi_pop_req_vring(VirtIOSCSI *s, +                                         VirtIOSCSIVring *vring); + +#endif /* _QEMU_VIRTIO_SCSI_H */ diff --git a/include/hw/virtio/virtio-serial.h b/include/hw/virtio/virtio-serial.h new file mode 100644 index 00000000..527d0bf6 --- /dev/null +++ b/include/hw/virtio/virtio-serial.h @@ -0,0 +1,224 @@ +/* + * Virtio Serial / Console Support + * + * Copyright IBM, Corp. 2008 + * Copyright Red Hat, Inc. 2009, 2010 + * + * Authors: + *  Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com> + *  Amit Shah <amit.shah@redhat.com> + * + * This work is licensed under the terms of the GNU GPL, version 2.  See + * the COPYING file in the top-level directory. + * + */ +#ifndef _QEMU_VIRTIO_SERIAL_H +#define _QEMU_VIRTIO_SERIAL_H + +#include "standard-headers/linux/virtio_console.h" +#include "hw/qdev.h" +#include "hw/virtio/virtio.h" + +struct virtio_serial_conf { +    /* Max. number of ports we can have for a virtio-serial device */ +    uint32_t max_virtserial_ports; +}; + +#define TYPE_VIRTIO_SERIAL_PORT "virtio-serial-port" +#define VIRTIO_SERIAL_PORT(obj) \ +     OBJECT_CHECK(VirtIOSerialPort, (obj), TYPE_VIRTIO_SERIAL_PORT) +#define VIRTIO_SERIAL_PORT_CLASS(klass) \ +     OBJECT_CLASS_CHECK(VirtIOSerialPortClass, (klass), TYPE_VIRTIO_SERIAL_PORT) +#define VIRTIO_SERIAL_PORT_GET_CLASS(obj) \ +     OBJECT_GET_CLASS(VirtIOSerialPortClass, (obj), TYPE_VIRTIO_SERIAL_PORT) + +typedef struct VirtIOSerial VirtIOSerial; +typedef struct VirtIOSerialBus VirtIOSerialBus; +typedef struct VirtIOSerialPort VirtIOSerialPort; + +typedef struct VirtIOSerialPortClass { +    DeviceClass parent_class; + +    /* Is this a device that binds with hvc in the guest? */ +    bool is_console; + +    /* +     * The per-port (or per-app) realize function that's called when a +     * new device is found on the bus. +     */ +    DeviceRealize realize; +    /* +     * Per-port unrealize function that's called when a port gets +     * hot-unplugged or removed. +     */ +    DeviceUnrealize unrealize; + +    /* Callbacks for guest events */ +        /* Guest opened/closed device. */ +    void (*set_guest_connected)(VirtIOSerialPort *port, int guest_connected); + +        /* Guest is now ready to accept data (virtqueues set up). */ +    void (*guest_ready)(VirtIOSerialPort *port); + +        /* +         * Guest has enqueued a buffer for the host to write into. +         * Called each time a buffer is enqueued by the guest; +         * irrespective of whether there already were free buffers the +         * host could have consumed. +         * +         * This is dependent on both the guest and host end being +         * connected. +         */ +    void (*guest_writable)(VirtIOSerialPort *port); + +    /* +     * Guest wrote some data to the port. This data is handed over to +     * the app via this callback.  The app can return a size less than +     * 'len'.  In this case, throttling will be enabled for this port. +     */ +    ssize_t (*have_data)(VirtIOSerialPort *port, const uint8_t *buf, +                         ssize_t len); +} VirtIOSerialPortClass; + +/* + * This is the state that's shared between all the ports.  Some of the + * state is configurable via command-line options. Some of it can be + * set by individual devices in their initfn routines. Some of the + * state is set by the generic qdev device init routine. + */ +struct VirtIOSerialPort { +    DeviceState dev; + +    QTAILQ_ENTRY(VirtIOSerialPort) next; + +    /* +     * This field gives us the virtio device as well as the qdev bus +     * that we are associated with +     */ +    VirtIOSerial *vser; + +    VirtQueue *ivq, *ovq; + +    /* +     * This name is sent to the guest and exported via sysfs. +     * The guest could create symlinks based on this information. +     * The name is in the reverse fqdn format, like org.qemu.console.0 +     */ +    char *name; + +    /* +     * This id helps identify ports between the guest and the host. +     * The guest sends a "header" with this id with each data packet +     * that it sends and the host can then find out which associated +     * device to send out this data to +     */ +    uint32_t id; + +    /* +     * This is the elem that we pop from the virtqueue.  A slow +     * backend that consumes guest data (e.g. the file backend for +     * qemu chardevs) can cause the guest to block till all the output +     * is flushed.  This isn't desired, so we keep a note of the last +     * element popped and continue consuming it once the backend +     * becomes writable again. +     */ +    VirtQueueElement elem; + +    /* +     * The index and the offset into the iov buffer that was popped in +     * elem above. +     */ +    uint32_t iov_idx; +    uint64_t iov_offset; + +    /* +     * When unthrottling we use a bottom-half to call flush_queued_data. +     */ +    QEMUBH *bh; + +    /* Is the corresponding guest device open? */ +    bool guest_connected; +    /* Is this device open for IO on the host? */ +    bool host_connected; +    /* Do apps not want to receive data? */ +    bool throttled; +}; + +/* The virtio-serial bus on top of which the ports will ride as devices */ +struct VirtIOSerialBus { +    BusState qbus; + +    /* This is the parent device that provides the bus for ports. */ +    VirtIOSerial *vser; + +    /* The maximum number of ports that can ride on top of this bus */ +    uint32_t max_nr_ports; +}; + +typedef struct VirtIOSerialPostLoad { +    QEMUTimer *timer; +    uint32_t nr_active_ports; +    struct { +        VirtIOSerialPort *port; +        uint8_t host_connected; +    } *connected; +} VirtIOSerialPostLoad; + +struct VirtIOSerial { +    VirtIODevice parent_obj; + +    VirtQueue *c_ivq, *c_ovq; +    /* Arrays of ivqs and ovqs: one per port */ +    VirtQueue **ivqs, **ovqs; + +    VirtIOSerialBus bus; + +    QTAILQ_HEAD(, VirtIOSerialPort) ports; + +    QLIST_ENTRY(VirtIOSerial) next; + +    /* bitmap for identifying active ports */ +    uint32_t *ports_map; + +    struct VirtIOSerialPostLoad *post_load; + +    virtio_serial_conf serial; +}; + +/* Interface to the virtio-serial bus */ + +/* + * Open a connection to the port + *   Returns 0 on success (always). + */ +int virtio_serial_open(VirtIOSerialPort *port); + +/* + * Close the connection to the port + *   Returns 0 on success (always). + */ +int virtio_serial_close(VirtIOSerialPort *port); + +/* + * Send data to Guest + */ +ssize_t virtio_serial_write(VirtIOSerialPort *port, const uint8_t *buf, +                            size_t size); + +/* + * Query whether a guest is ready to receive data. + */ +size_t virtio_serial_guest_ready(VirtIOSerialPort *port); + +/* + * Flow control: Ports can signal to the virtio-serial core to stop + * sending data or re-start sending data, depending on the 'throttle' + * value here. + */ +void virtio_serial_throttle_port(VirtIOSerialPort *port, bool throttle); + +#define TYPE_VIRTIO_SERIAL "virtio-serial-device" +#define VIRTIO_SERIAL(obj) \ +        OBJECT_CHECK(VirtIOSerial, (obj), TYPE_VIRTIO_SERIAL) + +#endif diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h new file mode 100644 index 00000000..9d09115f --- /dev/null +++ b/include/hw/virtio/virtio.h @@ -0,0 +1,293 @@ +/* + * Virtio Support + * + * Copyright IBM, Corp. 2007 + * + * Authors: + *  Anthony Liguori   <aliguori@us.ibm.com> + * + * This work is licensed under the terms of the GNU GPL, version 2.  See + * the COPYING file in the top-level directory. + * + */ + +#ifndef _QEMU_VIRTIO_H +#define _QEMU_VIRTIO_H + +#include "hw/hw.h" +#include "net/net.h" +#include "hw/qdev.h" +#include "sysemu/sysemu.h" +#include "qemu/event_notifier.h" +#include "standard-headers/linux/virtio_config.h" +#include "standard-headers/linux/virtio_ring.h" + +/* A guest should never accept this.  It implies negotiation is broken. */ +#define VIRTIO_F_BAD_FEATURE		30 + +#define VIRTIO_LEGACY_FEATURES ((0x1ULL << VIRTIO_F_BAD_FEATURE) | \ +                                (0x1ULL << VIRTIO_F_NOTIFY_ON_EMPTY) | \ +                                (0x1ULL << VIRTIO_F_ANY_LAYOUT)) + +struct VirtQueue; + +static inline hwaddr vring_align(hwaddr addr, +                                             unsigned long align) +{ +    return (addr + align - 1) & ~(align - 1); +} + +typedef struct VirtQueue VirtQueue; + +#define VIRTQUEUE_MAX_SIZE 1024 + +typedef struct VirtQueueElement +{ +    unsigned int index; +    unsigned int out_num; +    unsigned int in_num; +    hwaddr in_addr[VIRTQUEUE_MAX_SIZE]; +    hwaddr out_addr[VIRTQUEUE_MAX_SIZE]; +    struct iovec in_sg[VIRTQUEUE_MAX_SIZE]; +    struct iovec out_sg[VIRTQUEUE_MAX_SIZE]; +} VirtQueueElement; + +#define VIRTIO_QUEUE_MAX 1024 + +#define VIRTIO_NO_VECTOR 0xffff + +#define TYPE_VIRTIO_DEVICE "virtio-device" +#define VIRTIO_DEVICE_GET_CLASS(obj) \ +        OBJECT_GET_CLASS(VirtioDeviceClass, obj, TYPE_VIRTIO_DEVICE) +#define VIRTIO_DEVICE_CLASS(klass) \ +        OBJECT_CLASS_CHECK(VirtioDeviceClass, klass, TYPE_VIRTIO_DEVICE) +#define VIRTIO_DEVICE(obj) \ +        OBJECT_CHECK(VirtIODevice, (obj), TYPE_VIRTIO_DEVICE) + +enum virtio_device_endian { +    VIRTIO_DEVICE_ENDIAN_UNKNOWN, +    VIRTIO_DEVICE_ENDIAN_LITTLE, +    VIRTIO_DEVICE_ENDIAN_BIG, +}; + +struct VirtIODevice +{ +    DeviceState parent_obj; +    const char *name; +    uint8_t status; +    uint8_t isr; +    uint16_t queue_sel; +    uint64_t guest_features; +    uint64_t host_features; +    size_t config_len; +    void *config; +    uint16_t config_vector; +    uint32_t generation; +    int nvectors; +    VirtQueue *vq; +    uint16_t device_id; +    bool vm_running; +    VMChangeStateEntry *vmstate; +    char *bus_name; +    uint8_t device_endian; +    QLIST_HEAD(, VirtQueue) *vector_queues; +}; + +typedef struct VirtioDeviceClass { +    /*< private >*/ +    DeviceClass parent; +    /*< public >*/ + +    /* This is what a VirtioDevice must implement */ +    DeviceRealize realize; +    DeviceUnrealize unrealize; +    uint64_t (*get_features)(VirtIODevice *vdev, +                             uint64_t requested_features, +                             Error **errp); +    uint64_t (*bad_features)(VirtIODevice *vdev); +    void (*set_features)(VirtIODevice *vdev, uint64_t val); +    int (*validate_features)(VirtIODevice *vdev); +    void (*get_config)(VirtIODevice *vdev, uint8_t *config); +    void (*set_config)(VirtIODevice *vdev, const uint8_t *config); +    void (*reset)(VirtIODevice *vdev); +    void (*set_status)(VirtIODevice *vdev, uint8_t val); +    /* Test and clear event pending status. +     * Should be called after unmask to avoid losing events. +     * If backend does not support masking, +     * must check in frontend instead. +     */ +    bool (*guest_notifier_pending)(VirtIODevice *vdev, int n); +    /* Mask/unmask events from this vq. Any events reported +     * while masked will become pending. +     * If backend does not support masking, +     * must mask in frontend instead. +     */ +    void (*guest_notifier_mask)(VirtIODevice *vdev, int n, bool mask); +    void (*save)(VirtIODevice *vdev, QEMUFile *f); +    int (*load)(VirtIODevice *vdev, QEMUFile *f, int version_id); +} VirtioDeviceClass; + +void virtio_instance_init_common(Object *proxy_obj, void *data, +                                 size_t vdev_size, const char *vdev_name); + +void virtio_init(VirtIODevice *vdev, const char *name, +                         uint16_t device_id, size_t config_size); +void virtio_cleanup(VirtIODevice *vdev); + +/* Set the child bus name. */ +void virtio_device_set_child_bus_name(VirtIODevice *vdev, char *bus_name); + +VirtQueue *virtio_add_queue(VirtIODevice *vdev, int queue_size, +                            void (*handle_output)(VirtIODevice *, +                                                  VirtQueue *)); + +void virtio_del_queue(VirtIODevice *vdev, int n); + +void virtqueue_push(VirtQueue *vq, const VirtQueueElement *elem, +                    unsigned int len); +void virtqueue_flush(VirtQueue *vq, unsigned int count); +void virtqueue_discard(VirtQueue *vq, const VirtQueueElement *elem, +                       unsigned int len); +void virtqueue_fill(VirtQueue *vq, const VirtQueueElement *elem, +                    unsigned int len, unsigned int idx); + +void virtqueue_map_sg(struct iovec *sg, hwaddr *addr, +    size_t num_sg, int is_write); +int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem); +int virtqueue_avail_bytes(VirtQueue *vq, unsigned int in_bytes, +                          unsigned int out_bytes); +void virtqueue_get_avail_bytes(VirtQueue *vq, unsigned int *in_bytes, +                               unsigned int *out_bytes, +                               unsigned max_in_bytes, unsigned max_out_bytes); + +void virtio_notify(VirtIODevice *vdev, VirtQueue *vq); + +void virtio_save(VirtIODevice *vdev, QEMUFile *f); + +int virtio_load(VirtIODevice *vdev, QEMUFile *f, int version_id); + +void virtio_notify_config(VirtIODevice *vdev); + +void virtio_queue_set_notification(VirtQueue *vq, int enable); + +int virtio_queue_ready(VirtQueue *vq); + +int virtio_queue_empty(VirtQueue *vq); + +/* Host binding interface.  */ + +uint32_t virtio_config_readb(VirtIODevice *vdev, uint32_t addr); +uint32_t virtio_config_readw(VirtIODevice *vdev, uint32_t addr); +uint32_t virtio_config_readl(VirtIODevice *vdev, uint32_t addr); +void virtio_config_writeb(VirtIODevice *vdev, uint32_t addr, uint32_t data); +void virtio_config_writew(VirtIODevice *vdev, uint32_t addr, uint32_t data); +void virtio_config_writel(VirtIODevice *vdev, uint32_t addr, uint32_t data); +uint32_t virtio_config_modern_readb(VirtIODevice *vdev, uint32_t addr); +uint32_t virtio_config_modern_readw(VirtIODevice *vdev, uint32_t addr); +uint32_t virtio_config_modern_readl(VirtIODevice *vdev, uint32_t addr); +void virtio_config_modern_writeb(VirtIODevice *vdev, +                                 uint32_t addr, uint32_t data); +void virtio_config_modern_writew(VirtIODevice *vdev, +                                 uint32_t addr, uint32_t data); +void virtio_config_modern_writel(VirtIODevice *vdev, +                                 uint32_t addr, uint32_t data); +void virtio_queue_set_addr(VirtIODevice *vdev, int n, hwaddr addr); +hwaddr virtio_queue_get_addr(VirtIODevice *vdev, int n); +void virtio_queue_set_num(VirtIODevice *vdev, int n, int num); +int virtio_queue_get_num(VirtIODevice *vdev, int n); +int virtio_get_num_queues(VirtIODevice *vdev); +void virtio_queue_set_rings(VirtIODevice *vdev, int n, hwaddr desc, +                            hwaddr avail, hwaddr used); +void virtio_queue_update_rings(VirtIODevice *vdev, int n); +void virtio_queue_set_align(VirtIODevice *vdev, int n, int align); +void virtio_queue_notify(VirtIODevice *vdev, int n); +uint16_t virtio_queue_vector(VirtIODevice *vdev, int n); +void virtio_queue_set_vector(VirtIODevice *vdev, int n, uint16_t vector); +int virtio_set_status(VirtIODevice *vdev, uint8_t val); +void virtio_reset(void *opaque); +void virtio_update_irq(VirtIODevice *vdev); +int virtio_set_features(VirtIODevice *vdev, uint64_t val); + +/* Base devices.  */ +typedef struct VirtIOBlkConf VirtIOBlkConf; +struct virtio_net_conf; +typedef struct virtio_serial_conf virtio_serial_conf; +typedef struct virtio_input_conf virtio_input_conf; +typedef struct VirtIOSCSIConf VirtIOSCSIConf; +typedef struct VirtIORNGConf VirtIORNGConf; + +#define DEFINE_VIRTIO_COMMON_FEATURES(_state, _field) \ +    DEFINE_PROP_BIT64("indirect_desc", _state, _field,    \ +                      VIRTIO_RING_F_INDIRECT_DESC, true), \ +    DEFINE_PROP_BIT64("event_idx", _state, _field,        \ +                      VIRTIO_RING_F_EVENT_IDX, true),     \ +    DEFINE_PROP_BIT64("notify_on_empty", _state, _field,  \ +                      VIRTIO_F_NOTIFY_ON_EMPTY, true), \ +    DEFINE_PROP_BIT64("any_layout", _state, _field, \ +                      VIRTIO_F_ANY_LAYOUT, true) + +hwaddr virtio_queue_get_desc_addr(VirtIODevice *vdev, int n); +hwaddr virtio_queue_get_avail_addr(VirtIODevice *vdev, int n); +hwaddr virtio_queue_get_used_addr(VirtIODevice *vdev, int n); +hwaddr virtio_queue_get_ring_addr(VirtIODevice *vdev, int n); +hwaddr virtio_queue_get_desc_size(VirtIODevice *vdev, int n); +hwaddr virtio_queue_get_avail_size(VirtIODevice *vdev, int n); +hwaddr virtio_queue_get_used_size(VirtIODevice *vdev, int n); +hwaddr virtio_queue_get_ring_size(VirtIODevice *vdev, int n); +uint16_t virtio_queue_get_last_avail_idx(VirtIODevice *vdev, int n); +void virtio_queue_set_last_avail_idx(VirtIODevice *vdev, int n, uint16_t idx); +void virtio_queue_invalidate_signalled_used(VirtIODevice *vdev, int n); +VirtQueue *virtio_get_queue(VirtIODevice *vdev, int n); +uint16_t virtio_get_queue_index(VirtQueue *vq); +int virtio_queue_get_id(VirtQueue *vq); +EventNotifier *virtio_queue_get_guest_notifier(VirtQueue *vq); +void virtio_queue_set_guest_notifier_fd_handler(VirtQueue *vq, bool assign, +                                                bool with_irqfd); +EventNotifier *virtio_queue_get_host_notifier(VirtQueue *vq); +void virtio_queue_set_host_notifier_fd_handler(VirtQueue *vq, bool assign, +                                               bool set_handler); +void virtio_queue_notify_vq(VirtQueue *vq); +void virtio_irq(VirtQueue *vq); +VirtQueue *virtio_vector_first_queue(VirtIODevice *vdev, uint16_t vector); +VirtQueue *virtio_vector_next_queue(VirtQueue *vq); + +static inline void virtio_add_feature(uint64_t *features, unsigned int fbit) +{ +    assert(fbit < 64); +    *features |= (1ULL << fbit); +} + +static inline void virtio_clear_feature(uint64_t *features, unsigned int fbit) +{ +    assert(fbit < 64); +    *features &= ~(1ULL << fbit); +} + +static inline bool virtio_has_feature(uint64_t features, unsigned int fbit) +{ +    assert(fbit < 64); +    return !!(features & (1ULL << fbit)); +} + +static inline bool virtio_vdev_has_feature(VirtIODevice *vdev, +                                           unsigned int fbit) +{ +    return virtio_has_feature(vdev->guest_features, fbit); +} + +static inline bool virtio_host_has_feature(VirtIODevice *vdev, +                                           unsigned int fbit) +{ +    return virtio_has_feature(vdev->host_features, fbit); +} + +static inline bool virtio_is_big_endian(VirtIODevice *vdev) +{ +    if (!virtio_vdev_has_feature(vdev, VIRTIO_F_VERSION_1)) { +        assert(vdev->device_endian != VIRTIO_DEVICE_ENDIAN_UNKNOWN); +        return vdev->device_endian == VIRTIO_DEVICE_ENDIAN_BIG; +    } +    /* Devices conforming to VIRTIO 1.0 or later are always LE. */ +    return false; +} +#endif diff --git a/include/hw/watchdog/wdt_diag288.h b/include/hw/watchdog/wdt_diag288.h new file mode 100644 index 00000000..7f3fd450 --- /dev/null +++ b/include/hw/watchdog/wdt_diag288.h @@ -0,0 +1,36 @@ +#ifndef WDT_DIAG288_H +#define WDT_DIAG288_H + +#include "hw/qdev.h" + +#define TYPE_WDT_DIAG288 "diag288" +#define DIAG288(obj) \ +    OBJECT_CHECK(DIAG288State, (obj), TYPE_WDT_DIAG288) +#define DIAG288_CLASS(klass) \ +    OBJECT_CLASS_CHECK(DIAG288Class, (klass), TYPE_WDT_DIAG288) +#define DIAG288_GET_CLASS(obj) \ +    OBJECT_GET_CLASS(DIAG288Class, (obj), TYPE_WDT_DIAG288) + +#define WDT_DIAG288_INIT      0 +#define WDT_DIAG288_CHANGE    1 +#define WDT_DIAG288_CANCEL    2 + +typedef struct DIAG288State { +    /*< private >*/ +    DeviceState parent_obj; +    QEMUTimer *timer; +    bool enabled; + +    /*< public >*/ +} DIAG288State; + +typedef struct DIAG288Class { +    /*< private >*/ +    DeviceClass parent_class; + +    /*< public >*/ +    int (*handle_timer)(DIAG288State *dev, +                        uint64_t func, uint64_t timeout); +} DIAG288Class; + +#endif  /* WDT_DIAG288_H */ diff --git a/include/hw/xen/xen.h b/include/hw/xen/xen.h new file mode 100644 index 00000000..4356af45 --- /dev/null +++ b/include/hw/xen/xen.h @@ -0,0 +1,54 @@ +#ifndef QEMU_HW_XEN_H +#define QEMU_HW_XEN_H 1 +/* + * public xen header + *   stuff needed outside xen-*.c, i.e. interfaces to qemu. + *   must not depend on any xen headers being present in + *   /usr/include/xen, so it can be included unconditionally. + */ +#include <inttypes.h> + +#include "hw/irq.h" +#include "qemu-common.h" + +/* xen-machine.c */ +enum xen_mode { +    XEN_EMULATE = 0,  // xen emulation, using xenner (default) +    XEN_CREATE,       // create xen domain +    XEN_ATTACH        // attach to xen domain created by xend +}; + +extern uint32_t xen_domid; +extern enum xen_mode xen_mode; + +extern bool xen_allowed; + +static inline bool xen_enabled(void) +{ +    return xen_allowed; +} + +int xen_pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num); +void xen_piix3_set_irq(void *opaque, int irq_num, int level); +void xen_piix_pci_write_config_client(uint32_t address, uint32_t val, int len); +void xen_hvm_inject_msi(uint64_t addr, uint32_t data); + +qemu_irq *xen_interrupt_controller_init(void); + +void xenstore_store_pv_console_info(int i, struct CharDriverState *chr); + +#if defined(NEED_CPU_H) && !defined(CONFIG_USER_ONLY) +int xen_hvm_init(ram_addr_t *below_4g_mem_size, ram_addr_t *above_4g_mem_size, +                 MemoryRegion **ram_memory); +void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size, +                   struct MemoryRegion *mr); +void xen_modified_memory(ram_addr_t start, ram_addr_t length); +#endif + +void xen_register_framebuffer(struct MemoryRegion *mr); + +#if defined(CONFIG_XEN) && CONFIG_XEN_CTRL_INTERFACE_VERSION < 400 +#  define HVM_MAX_VCPUS 32 +#endif + +#endif /* QEMU_HW_XEN_H */ diff --git a/include/hw/xen/xen_backend.h b/include/hw/xen/xen_backend.h new file mode 100644 index 00000000..3b4125e3 --- /dev/null +++ b/include/hw/xen/xen_backend.h @@ -0,0 +1,111 @@ +#ifndef QEMU_HW_XEN_BACKEND_H +#define QEMU_HW_XEN_BACKEND_H 1 + +#include "hw/xen/xen_common.h" +#include "sysemu/sysemu.h" +#include "net/net.h" + +/* ------------------------------------------------------------- */ + +#define XEN_BUFSIZE 1024 + +struct XenDevice; + +/* driver uses grant tables  ->  open gntdev device (xendev->gnttabdev) */ +#define DEVOPS_FLAG_NEED_GNTDEV   1 +/* don't expect frontend doing correct state transitions (aka console quirk) */ +#define DEVOPS_FLAG_IGNORE_STATE  2 + +struct XenDevOps { +    size_t    size; +    uint32_t  flags; +    void      (*alloc)(struct XenDevice *xendev); +    int       (*init)(struct XenDevice *xendev); +    int       (*initialise)(struct XenDevice *xendev); +    void      (*connected)(struct XenDevice *xendev); +    void      (*event)(struct XenDevice *xendev); +    void      (*disconnect)(struct XenDevice *xendev); +    int       (*free)(struct XenDevice *xendev); +    void      (*backend_changed)(struct XenDevice *xendev, const char *node); +    void      (*frontend_changed)(struct XenDevice *xendev, const char *node); +}; + +struct XenDevice { +    const char         *type; +    int                dom; +    int                dev; +    char               name[64]; +    int                debug; + +    enum xenbus_state  be_state; +    enum xenbus_state  fe_state; +    int                online; +    char               be[XEN_BUFSIZE]; +    char               *fe; +    char               *protocol; +    int                remote_port; +    int                local_port; + +    XenEvtchn          evtchndev; +    XenGnttab          gnttabdev; + +    struct XenDevOps   *ops; +    QTAILQ_ENTRY(XenDevice) next; +}; + +/* ------------------------------------------------------------- */ + +/* variables */ +extern XenXC xen_xc; +extern struct xs_handle *xenstore; +extern const char *xen_protocol; + +/* xenstore helper functions */ +int xenstore_write_str(const char *base, const char *node, const char *val); +int xenstore_write_int(const char *base, const char *node, int ival); +int xenstore_write_int64(const char *base, const char *node, int64_t ival); +char *xenstore_read_str(const char *base, const char *node); +int xenstore_read_int(const char *base, const char *node, int *ival); + +int xenstore_write_be_str(struct XenDevice *xendev, const char *node, const char *val); +int xenstore_write_be_int(struct XenDevice *xendev, const char *node, int ival); +int xenstore_write_be_int64(struct XenDevice *xendev, const char *node, int64_t ival); +char *xenstore_read_be_str(struct XenDevice *xendev, const char *node); +int xenstore_read_be_int(struct XenDevice *xendev, const char *node, int *ival); +char *xenstore_read_fe_str(struct XenDevice *xendev, const char *node); +int xenstore_read_fe_int(struct XenDevice *xendev, const char *node, int *ival); +int xenstore_read_uint64(const char *base, const char *node, uint64_t *uval); +int xenstore_read_fe_uint64(struct XenDevice *xendev, const char *node, uint64_t *uval); + +const char *xenbus_strstate(enum xenbus_state state); +struct XenDevice *xen_be_find_xendev(const char *type, int dom, int dev); +void xen_be_check_state(struct XenDevice *xendev); + +/* xen backend driver bits */ +int xen_be_init(void); +int xen_be_register(const char *type, struct XenDevOps *ops); +int xen_be_set_state(struct XenDevice *xendev, enum xenbus_state state); +int xen_be_bind_evtchn(struct XenDevice *xendev); +void xen_be_unbind_evtchn(struct XenDevice *xendev); +int xen_be_send_notify(struct XenDevice *xendev); +void xen_be_printf(struct XenDevice *xendev, int msg_level, const char *fmt, ...) +    GCC_FMT_ATTR(3, 4); + +/* actual backend drivers */ +extern struct XenDevOps xen_console_ops;      /* xen_console.c     */ +extern struct XenDevOps xen_kbdmouse_ops;     /* xen_framebuffer.c */ +extern struct XenDevOps xen_framebuffer_ops;  /* xen_framebuffer.c */ +extern struct XenDevOps xen_blkdev_ops;       /* xen_disk.c        */ +extern struct XenDevOps xen_netdev_ops;       /* xen_nic.c         */ + +void xen_init_display(int domid); + +/* configuration (aka xenbus setup) */ +void xen_config_cleanup(void); +int xen_config_dev_blk(DriveInfo *disk); +int xen_config_dev_nic(NICInfo *nic); +int xen_config_dev_vfb(int vdev, const char *type); +int xen_config_dev_vkbd(int vdev); +int xen_config_dev_console(int vdev); + +#endif /* QEMU_HW_XEN_BACKEND_H */ diff --git a/include/hw/xen/xen_common.h b/include/hw/xen/xen_common.h new file mode 100644 index 00000000..ed5fd3e1 --- /dev/null +++ b/include/hw/xen/xen_common.h @@ -0,0 +1,410 @@ +#ifndef QEMU_HW_XEN_COMMON_H +#define QEMU_HW_XEN_COMMON_H 1 + +#include "config-host.h" + +#include <stddef.h> +#include <inttypes.h> + +#include <xenctrl.h> +#if CONFIG_XEN_CTRL_INTERFACE_VERSION < 420 +#  include <xs.h> +#else +#  include <xenstore.h> +#endif +#include <xen/io/xenbus.h> + +#include "hw/hw.h" +#include "hw/xen/xen.h" +#include "hw/pci/pci.h" +#include "qemu/queue.h" +#include "trace.h" + +/* + * We don't support Xen prior to 3.3.0. + */ + +/* Xen before 4.0 */ +#if CONFIG_XEN_CTRL_INTERFACE_VERSION < 400 +static inline void *xc_map_foreign_bulk(int xc_handle, uint32_t dom, int prot, +                                        xen_pfn_t *arr, int *err, +                                        unsigned int num) +{ +    return xc_map_foreign_batch(xc_handle, dom, prot, arr, num); +} +#endif + + +/* Xen before 4.1 */ +#if CONFIG_XEN_CTRL_INTERFACE_VERSION < 410 + +typedef int XenXC; +typedef int XenEvtchn; +typedef int XenGnttab; + +#  define XC_INTERFACE_FMT "%i" +#  define XC_HANDLER_INITIAL_VALUE    -1 + +static inline XenEvtchn xen_xc_evtchn_open(void *logger, +                                           unsigned int open_flags) +{ +    return xc_evtchn_open(); +} + +static inline XenGnttab xen_xc_gnttab_open(void *logger, +                                           unsigned int open_flags) +{ +    return xc_gnttab_open(); +} + +static inline XenXC xen_xc_interface_open(void *logger, void *dombuild_logger, +                                          unsigned int open_flags) +{ +    return xc_interface_open(); +} + +static inline int xc_fd(int xen_xc) +{ +    return xen_xc; +} + + +static inline int xc_domain_populate_physmap_exact +    (XenXC xc_handle, uint32_t domid, unsigned long nr_extents, +     unsigned int extent_order, unsigned int mem_flags, xen_pfn_t *extent_start) +{ +    return xc_domain_memory_populate_physmap +        (xc_handle, domid, nr_extents, extent_order, mem_flags, extent_start); +} + +static inline int xc_domain_add_to_physmap(int xc_handle, uint32_t domid, +                                           unsigned int space, unsigned long idx, +                                           xen_pfn_t gpfn) +{ +    struct xen_add_to_physmap xatp = { +        .domid = domid, +        .space = space, +        .idx = idx, +        .gpfn = gpfn, +    }; + +    return xc_memory_op(xc_handle, XENMEM_add_to_physmap, &xatp); +} + +static inline struct xs_handle *xs_open(unsigned long flags) +{ +    return xs_daemon_open(); +} + +static inline void xs_close(struct xs_handle *xsh) +{ +    if (xsh != NULL) { +        xs_daemon_close(xsh); +    } +} + + +/* Xen 4.1 */ +#else + +typedef xc_interface *XenXC; +typedef xc_evtchn *XenEvtchn; +typedef xc_gnttab *XenGnttab; + +#  define XC_INTERFACE_FMT "%p" +#  define XC_HANDLER_INITIAL_VALUE    NULL + +static inline XenEvtchn xen_xc_evtchn_open(void *logger, +                                           unsigned int open_flags) +{ +    return xc_evtchn_open(logger, open_flags); +} + +static inline XenGnttab xen_xc_gnttab_open(void *logger, +                                           unsigned int open_flags) +{ +    return xc_gnttab_open(logger, open_flags); +} + +static inline XenXC xen_xc_interface_open(void *logger, void *dombuild_logger, +                                          unsigned int open_flags) +{ +    return xc_interface_open(logger, dombuild_logger, open_flags); +} + +/* FIXME There is now way to have the xen fd */ +static inline int xc_fd(xc_interface *xen_xc) +{ +    return -1; +} +#endif + +/* Xen before 4.2 */ +#if CONFIG_XEN_CTRL_INTERFACE_VERSION < 420 +static inline int xen_xc_hvm_inject_msi(XenXC xen_xc, domid_t dom, +        uint64_t addr, uint32_t data) +{ +    return -ENOSYS; +} +/* The followings are only to compile op_discard related code on older + * Xen releases. */ +#define BLKIF_OP_DISCARD 5 +struct blkif_request_discard { +    uint64_t nr_sectors; +    uint64_t sector_number; +}; +#else +static inline int xen_xc_hvm_inject_msi(XenXC xen_xc, domid_t dom, +        uint64_t addr, uint32_t data) +{ +    return xc_hvm_inject_msi(xen_xc, dom, addr, data); +} +#endif + +void destroy_hvm_domain(bool reboot); + +/* shutdown/destroy current domain because of an error */ +void xen_shutdown_fatal_error(const char *fmt, ...) GCC_FMT_ATTR(1, 2); + +#ifdef HVM_PARAM_VMPORT_REGS_PFN +static inline int xen_get_vmport_regs_pfn(XenXC xc, domid_t dom, +                                          xen_pfn_t *vmport_regs_pfn) +{ +    int rc; +    uint64_t value; +    rc = xc_hvm_param_get(xc, dom, HVM_PARAM_VMPORT_REGS_PFN, &value); +    if (rc >= 0) { +        *vmport_regs_pfn = (xen_pfn_t) value; +    } +    return rc; +} +#else +static inline int xen_get_vmport_regs_pfn(XenXC xc, domid_t dom, +                                          xen_pfn_t *vmport_regs_pfn) +{ +    return -ENOSYS; +} +#endif + +/* Xen before 4.5 */ +#if CONFIG_XEN_CTRL_INTERFACE_VERSION < 450 + +#ifndef HVM_PARAM_BUFIOREQ_EVTCHN +#define HVM_PARAM_BUFIOREQ_EVTCHN 26 +#endif + +#define IOREQ_TYPE_PCI_CONFIG 2 + +typedef uint16_t ioservid_t; + +static inline void xen_map_memory_section(XenXC xc, domid_t dom, +                                          ioservid_t ioservid, +                                          MemoryRegionSection *section) +{ +} + +static inline void xen_unmap_memory_section(XenXC xc, domid_t dom, +                                            ioservid_t ioservid, +                                            MemoryRegionSection *section) +{ +} + +static inline void xen_map_io_section(XenXC xc, domid_t dom, +                                      ioservid_t ioservid, +                                      MemoryRegionSection *section) +{ +} + +static inline void xen_unmap_io_section(XenXC xc, domid_t dom, +                                        ioservid_t ioservid, +                                        MemoryRegionSection *section) +{ +} + +static inline void xen_map_pcidev(XenXC xc, domid_t dom, +                                  ioservid_t ioservid, +                                  PCIDevice *pci_dev) +{ +} + +static inline void xen_unmap_pcidev(XenXC xc, domid_t dom, +                                    ioservid_t ioservid, +                                    PCIDevice *pci_dev) +{ +} + +static inline int xen_create_ioreq_server(XenXC xc, domid_t dom, +                                          ioservid_t *ioservid) +{ +    return 0; +} + +static inline void xen_destroy_ioreq_server(XenXC xc, domid_t dom, +                                            ioservid_t ioservid) +{ +} + +static inline int xen_get_ioreq_server_info(XenXC xc, domid_t dom, +                                            ioservid_t ioservid, +                                            xen_pfn_t *ioreq_pfn, +                                            xen_pfn_t *bufioreq_pfn, +                                            evtchn_port_t *bufioreq_evtchn) +{ +    unsigned long param; +    int rc; + +    rc = xc_get_hvm_param(xc, dom, HVM_PARAM_IOREQ_PFN, ¶m); +    if (rc < 0) { +        fprintf(stderr, "failed to get HVM_PARAM_IOREQ_PFN\n"); +        return -1; +    } + +    *ioreq_pfn = param; + +    rc = xc_get_hvm_param(xc, dom, HVM_PARAM_BUFIOREQ_PFN, ¶m); +    if (rc < 0) { +        fprintf(stderr, "failed to get HVM_PARAM_BUFIOREQ_PFN\n"); +        return -1; +    } + +    *bufioreq_pfn = param; + +    rc = xc_get_hvm_param(xc, dom, HVM_PARAM_BUFIOREQ_EVTCHN, +                          ¶m); +    if (rc < 0) { +        fprintf(stderr, "failed to get HVM_PARAM_BUFIOREQ_EVTCHN\n"); +        return -1; +    } + +    *bufioreq_evtchn = param; + +    return 0; +} + +static inline int xen_set_ioreq_server_state(XenXC xc, domid_t dom, +                                             ioservid_t ioservid, +                                             bool enable) +{ +    return 0; +} + +/* Xen 4.5 */ +#else + +static inline void xen_map_memory_section(XenXC xc, domid_t dom, +                                          ioservid_t ioservid, +                                          MemoryRegionSection *section) +{ +    hwaddr start_addr = section->offset_within_address_space; +    ram_addr_t size = int128_get64(section->size); +    hwaddr end_addr = start_addr + size - 1; + +    trace_xen_map_mmio_range(ioservid, start_addr, end_addr); +    xc_hvm_map_io_range_to_ioreq_server(xc, dom, ioservid, 1, +                                        start_addr, end_addr); +} + +static inline void xen_unmap_memory_section(XenXC xc, domid_t dom, +                                            ioservid_t ioservid, +                                            MemoryRegionSection *section) +{ +    hwaddr start_addr = section->offset_within_address_space; +    ram_addr_t size = int128_get64(section->size); +    hwaddr end_addr = start_addr + size - 1; + +    trace_xen_unmap_mmio_range(ioservid, start_addr, end_addr); +    xc_hvm_unmap_io_range_from_ioreq_server(xc, dom, ioservid, 1, +                                            start_addr, end_addr); +} + +static inline void xen_map_io_section(XenXC xc, domid_t dom, +                                      ioservid_t ioservid, +                                      MemoryRegionSection *section) +{ +    hwaddr start_addr = section->offset_within_address_space; +    ram_addr_t size = int128_get64(section->size); +    hwaddr end_addr = start_addr + size - 1; + +    trace_xen_map_portio_range(ioservid, start_addr, end_addr); +    xc_hvm_map_io_range_to_ioreq_server(xc, dom, ioservid, 0, +                                        start_addr, end_addr); +} + +static inline void xen_unmap_io_section(XenXC xc, domid_t dom, +                                        ioservid_t ioservid, +                                        MemoryRegionSection *section) +{ +    hwaddr start_addr = section->offset_within_address_space; +    ram_addr_t size = int128_get64(section->size); +    hwaddr end_addr = start_addr + size - 1; + +    trace_xen_unmap_portio_range(ioservid, start_addr, end_addr); +    xc_hvm_unmap_io_range_from_ioreq_server(xc, dom, ioservid, 0, +                                            start_addr, end_addr); +} + +static inline void xen_map_pcidev(XenXC xc, domid_t dom, +                                  ioservid_t ioservid, +                                  PCIDevice *pci_dev) +{ +    trace_xen_map_pcidev(ioservid, pci_bus_num(pci_dev->bus), +                         PCI_SLOT(pci_dev->devfn), PCI_FUNC(pci_dev->devfn)); +    xc_hvm_map_pcidev_to_ioreq_server(xc, dom, ioservid, +                                      0, pci_bus_num(pci_dev->bus), +                                      PCI_SLOT(pci_dev->devfn), +                                      PCI_FUNC(pci_dev->devfn)); +} + +static inline void xen_unmap_pcidev(XenXC xc, domid_t dom, +                                    ioservid_t ioservid, +                                    PCIDevice *pci_dev) +{ +    trace_xen_unmap_pcidev(ioservid, pci_bus_num(pci_dev->bus), +                           PCI_SLOT(pci_dev->devfn), PCI_FUNC(pci_dev->devfn)); +    xc_hvm_unmap_pcidev_from_ioreq_server(xc, dom, ioservid, +                                          0, pci_bus_num(pci_dev->bus), +                                          PCI_SLOT(pci_dev->devfn), +                                          PCI_FUNC(pci_dev->devfn)); +} + +static inline int xen_create_ioreq_server(XenXC xc, domid_t dom, +                                          ioservid_t *ioservid) +{ +    int rc = xc_hvm_create_ioreq_server(xc, dom, 1, ioservid); + +    if (rc == 0) { +        trace_xen_ioreq_server_create(*ioservid); +    } + +    return rc; +} + +static inline void xen_destroy_ioreq_server(XenXC xc, domid_t dom, +                                            ioservid_t ioservid) +{ +    trace_xen_ioreq_server_destroy(ioservid); +    xc_hvm_destroy_ioreq_server(xc, dom, ioservid); +} + +static inline int xen_get_ioreq_server_info(XenXC xc, domid_t dom, +                                            ioservid_t ioservid, +                                            xen_pfn_t *ioreq_pfn, +                                            xen_pfn_t *bufioreq_pfn, +                                            evtchn_port_t *bufioreq_evtchn) +{ +    return xc_hvm_get_ioreq_server_info(xc, dom, ioservid, +                                        ioreq_pfn, bufioreq_pfn, +                                        bufioreq_evtchn); +} + +static inline int xen_set_ioreq_server_state(XenXC xc, domid_t dom, +                                             ioservid_t ioservid, +                                             bool enable) +{ +    trace_xen_ioreq_server_state(ioservid, enable); +    return xc_hvm_set_ioreq_server_state(xc, dom, ioservid, enable); +} + +#endif + +#endif /* QEMU_HW_XEN_COMMON_H */  | 
