18135aeedSIsaku Yamahata /* 28135aeedSIsaku Yamahata * ioh3420.c 38135aeedSIsaku Yamahata * Intel X58 north bridge IOH 48135aeedSIsaku Yamahata * PCI Express root port device id 3420 58135aeedSIsaku Yamahata * 68135aeedSIsaku Yamahata * Copyright (c) 2010 Isaku Yamahata <yamahata at valinux co jp> 78135aeedSIsaku Yamahata * VA Linux Systems Japan K.K. 88135aeedSIsaku Yamahata * 98135aeedSIsaku Yamahata * This program is free software; you can redistribute it and/or modify 108135aeedSIsaku Yamahata * it under the terms of the GNU General Public License as published by 118135aeedSIsaku Yamahata * the Free Software Foundation; either version 2 of the License, or 128135aeedSIsaku Yamahata * (at your option) any later version. 138135aeedSIsaku Yamahata * 148135aeedSIsaku Yamahata * This program is distributed in the hope that it will be useful, 158135aeedSIsaku Yamahata * but WITHOUT ANY WARRANTY; without even the implied warranty of 168135aeedSIsaku Yamahata * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 178135aeedSIsaku Yamahata * GNU General Public License for more details. 188135aeedSIsaku Yamahata * 198135aeedSIsaku Yamahata * You should have received a copy of the GNU General Public License along 208135aeedSIsaku Yamahata * with this program; if not, see <http://www.gnu.org/licenses/>. 218135aeedSIsaku Yamahata */ 228135aeedSIsaku Yamahata 2397d5408fSPeter Maydell #include "qemu/osdep.h" 2483c9f4caSPaolo Bonzini #include "hw/pci/pci_ids.h" 2583c9f4caSPaolo Bonzini #include "hw/pci/msi.h" 2683c9f4caSPaolo Bonzini #include "hw/pci/pcie.h" 27cd1f0ca2SPhilippe Mathieu-Daudé #include "hw/pci/pcie_port.h" 28d6454270SMarkus Armbruster #include "migration/vmstate.h" 290b8fa32fSMarkus Armbruster #include "qemu/module.h" 308135aeedSIsaku Yamahata 318135aeedSIsaku Yamahata #define PCI_DEVICE_ID_IOH_EPORT 0x3420 /* D0:F0 express mode */ 328135aeedSIsaku Yamahata #define PCI_DEVICE_ID_IOH_REV 0x2 338135aeedSIsaku Yamahata #define IOH_EP_SSVID_OFFSET 0x40 348135aeedSIsaku Yamahata #define IOH_EP_SSVID_SVID PCI_VENDOR_ID_INTEL 358135aeedSIsaku Yamahata #define IOH_EP_SSVID_SSID 0 368135aeedSIsaku Yamahata #define IOH_EP_MSI_OFFSET 0x60 378135aeedSIsaku Yamahata #define IOH_EP_MSI_SUPPORTED_FLAGS PCI_MSI_FLAGS_MASKBIT 388135aeedSIsaku Yamahata #define IOH_EP_MSI_NR_VECTOR 2 398135aeedSIsaku Yamahata #define IOH_EP_EXP_OFFSET 0x90 408135aeedSIsaku Yamahata #define IOH_EP_AER_OFFSET 0x100 418135aeedSIsaku Yamahata 4261620c2fSIsaku Yamahata /* 4361620c2fSIsaku Yamahata * If two MSI vector are allocated, Advanced Error Interrupt Message Number 4461620c2fSIsaku Yamahata * is 1. otherwise 0. 4561620c2fSIsaku Yamahata * 17.12.5.10 RPERRSTS, 32:27 bit Advanced Error Interrupt Message Number. 4661620c2fSIsaku Yamahata */ 4761620c2fSIsaku Yamahata static uint8_t ioh3420_aer_vector(const PCIDevice *d) 4861620c2fSIsaku Yamahata { 4961620c2fSIsaku Yamahata switch (msi_nr_vectors_allocated(d)) { 5061620c2fSIsaku Yamahata case 1: 5161620c2fSIsaku Yamahata return 0; 5261620c2fSIsaku Yamahata case 2: 5361620c2fSIsaku Yamahata return 1; 5461620c2fSIsaku Yamahata case 4: 5561620c2fSIsaku Yamahata case 8: 5661620c2fSIsaku Yamahata case 16: 5761620c2fSIsaku Yamahata case 32: 5861620c2fSIsaku Yamahata default: 5961620c2fSIsaku Yamahata break; 6061620c2fSIsaku Yamahata } 6161620c2fSIsaku Yamahata abort(); 6261620c2fSIsaku Yamahata return 0; 6361620c2fSIsaku Yamahata } 6461620c2fSIsaku Yamahata 65fed23cb4SMarcel Apfelbaum static int ioh3420_interrupts_init(PCIDevice *d, Error **errp) 6661620c2fSIsaku Yamahata { 678135aeedSIsaku Yamahata int rc; 6852ea63deSCao jin 698135aeedSIsaku Yamahata rc = msi_init(d, IOH_EP_MSI_OFFSET, IOH_EP_MSI_NR_VECTOR, 708135aeedSIsaku Yamahata IOH_EP_MSI_SUPPORTED_FLAGS & PCI_MSI_FLAGS_64BIT, 71fed23cb4SMarcel Apfelbaum IOH_EP_MSI_SUPPORTED_FLAGS & PCI_MSI_FLAGS_MASKBIT, 7206592d7eSMao Zhongyi errp); 738135aeedSIsaku Yamahata if (rc < 0) { 741108b2f8SCao jin assert(rc == -ENOTSUP); 758135aeedSIsaku Yamahata } 7652ea63deSCao jin 7761620c2fSIsaku Yamahata return rc; 788135aeedSIsaku Yamahata } 798135aeedSIsaku Yamahata 80fed23cb4SMarcel Apfelbaum static void ioh3420_interrupts_uninit(PCIDevice *d) 818135aeedSIsaku Yamahata { 8261620c2fSIsaku Yamahata msi_uninit(d); 838135aeedSIsaku Yamahata } 848135aeedSIsaku Yamahata 858135aeedSIsaku Yamahata static const VMStateDescription vmstate_ioh3420 = { 868135aeedSIsaku Yamahata .name = "ioh-3240-express-root-port", 879d6b9db1SPeter Xu .priority = MIG_PRI_PCI_BUS, 888135aeedSIsaku Yamahata .version_id = 1, 898135aeedSIsaku Yamahata .minimum_version_id = 1, 906bde6aaaSMichael S. Tsirkin .post_load = pcie_cap_slot_post_load, 91*f026c578SRichard Henderson .fields = (const VMStateField[]) { 9220daa90aSDr. David Alan Gilbert VMSTATE_PCI_DEVICE(parent_obj.parent_obj.parent_obj, PCIESlot), 93bcb75750SAndreas Färber VMSTATE_STRUCT(parent_obj.parent_obj.parent_obj.exp.aer_log, 94bcb75750SAndreas Färber PCIESlot, 0, vmstate_pcie_aer_log, PCIEAERLog), 958135aeedSIsaku Yamahata VMSTATE_END_OF_LIST() 968135aeedSIsaku Yamahata } 978135aeedSIsaku Yamahata }; 988135aeedSIsaku Yamahata 9940021f08SAnthony Liguori static void ioh3420_class_init(ObjectClass *klass, void *data) 10040021f08SAnthony Liguori { 10139bffca2SAnthony Liguori DeviceClass *dc = DEVICE_CLASS(klass); 10240021f08SAnthony Liguori PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); 103fed23cb4SMarcel Apfelbaum PCIERootPortClass *rpc = PCIE_ROOT_PORT_CLASS(klass); 10440021f08SAnthony Liguori 10540021f08SAnthony Liguori k->vendor_id = PCI_VENDOR_ID_INTEL; 10640021f08SAnthony Liguori k->device_id = PCI_DEVICE_ID_IOH_EPORT; 10740021f08SAnthony Liguori k->revision = PCI_DEVICE_ID_IOH_REV; 10839bffca2SAnthony Liguori dc->desc = "Intel IOH device id 3420 PCIE Root Port"; 10939bffca2SAnthony Liguori dc->vmsd = &vmstate_ioh3420; 110fed23cb4SMarcel Apfelbaum rpc->aer_vector = ioh3420_aer_vector; 111fed23cb4SMarcel Apfelbaum rpc->interrupts_init = ioh3420_interrupts_init; 112fed23cb4SMarcel Apfelbaum rpc->interrupts_uninit = ioh3420_interrupts_uninit; 113fed23cb4SMarcel Apfelbaum rpc->exp_offset = IOH_EP_EXP_OFFSET; 114fed23cb4SMarcel Apfelbaum rpc->aer_offset = IOH_EP_AER_OFFSET; 115fed23cb4SMarcel Apfelbaum rpc->ssvid_offset = IOH_EP_SSVID_OFFSET; 116fed23cb4SMarcel Apfelbaum rpc->ssid = IOH_EP_SSVID_SSID; 1178135aeedSIsaku Yamahata } 11840021f08SAnthony Liguori 1198c43a6f0SAndreas Färber static const TypeInfo ioh3420_info = { 12040021f08SAnthony Liguori .name = "ioh3420", 121fed23cb4SMarcel Apfelbaum .parent = TYPE_PCIE_ROOT_PORT, 12240021f08SAnthony Liguori .class_init = ioh3420_class_init, 1238135aeedSIsaku Yamahata }; 1248135aeedSIsaku Yamahata 12583f7d43aSAndreas Färber static void ioh3420_register_types(void) 1268135aeedSIsaku Yamahata { 12739bffca2SAnthony Liguori type_register_static(&ioh3420_info); 1288135aeedSIsaku Yamahata } 1298135aeedSIsaku Yamahata 13083f7d43aSAndreas Färber type_init(ioh3420_register_types) 131