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" 28*0b8fa32fSMarkus Armbruster #include "qemu/module.h" 298135aeedSIsaku Yamahata 308135aeedSIsaku Yamahata #define PCI_DEVICE_ID_IOH_EPORT 0x3420 /* D0:F0 express mode */ 318135aeedSIsaku Yamahata #define PCI_DEVICE_ID_IOH_REV 0x2 328135aeedSIsaku Yamahata #define IOH_EP_SSVID_OFFSET 0x40 338135aeedSIsaku Yamahata #define IOH_EP_SSVID_SVID PCI_VENDOR_ID_INTEL 348135aeedSIsaku Yamahata #define IOH_EP_SSVID_SSID 0 358135aeedSIsaku Yamahata #define IOH_EP_MSI_OFFSET 0x60 368135aeedSIsaku Yamahata #define IOH_EP_MSI_SUPPORTED_FLAGS PCI_MSI_FLAGS_MASKBIT 378135aeedSIsaku Yamahata #define IOH_EP_MSI_NR_VECTOR 2 388135aeedSIsaku Yamahata #define IOH_EP_EXP_OFFSET 0x90 398135aeedSIsaku Yamahata #define IOH_EP_AER_OFFSET 0x100 408135aeedSIsaku Yamahata 4161620c2fSIsaku Yamahata /* 4261620c2fSIsaku Yamahata * If two MSI vector are allocated, Advanced Error Interrupt Message Number 4361620c2fSIsaku Yamahata * is 1. otherwise 0. 4461620c2fSIsaku Yamahata * 17.12.5.10 RPERRSTS, 32:27 bit Advanced Error Interrupt Message Number. 4561620c2fSIsaku Yamahata */ 4661620c2fSIsaku Yamahata static uint8_t ioh3420_aer_vector(const PCIDevice *d) 4761620c2fSIsaku Yamahata { 4861620c2fSIsaku Yamahata switch (msi_nr_vectors_allocated(d)) { 4961620c2fSIsaku Yamahata case 1: 5061620c2fSIsaku Yamahata return 0; 5161620c2fSIsaku Yamahata case 2: 5261620c2fSIsaku Yamahata return 1; 5361620c2fSIsaku Yamahata case 4: 5461620c2fSIsaku Yamahata case 8: 5561620c2fSIsaku Yamahata case 16: 5661620c2fSIsaku Yamahata case 32: 5761620c2fSIsaku Yamahata default: 5861620c2fSIsaku Yamahata break; 5961620c2fSIsaku Yamahata } 6061620c2fSIsaku Yamahata abort(); 6161620c2fSIsaku Yamahata return 0; 6261620c2fSIsaku Yamahata } 6361620c2fSIsaku Yamahata 64fed23cb4SMarcel Apfelbaum static int ioh3420_interrupts_init(PCIDevice *d, Error **errp) 6561620c2fSIsaku Yamahata { 668135aeedSIsaku Yamahata int rc; 6752ea63deSCao jin 688135aeedSIsaku Yamahata rc = msi_init(d, IOH_EP_MSI_OFFSET, IOH_EP_MSI_NR_VECTOR, 698135aeedSIsaku Yamahata IOH_EP_MSI_SUPPORTED_FLAGS & PCI_MSI_FLAGS_64BIT, 70fed23cb4SMarcel Apfelbaum IOH_EP_MSI_SUPPORTED_FLAGS & PCI_MSI_FLAGS_MASKBIT, 7106592d7eSMao Zhongyi errp); 728135aeedSIsaku Yamahata if (rc < 0) { 731108b2f8SCao jin assert(rc == -ENOTSUP); 748135aeedSIsaku Yamahata } 7552ea63deSCao jin 7661620c2fSIsaku Yamahata return rc; 778135aeedSIsaku Yamahata } 788135aeedSIsaku Yamahata 79fed23cb4SMarcel Apfelbaum static void ioh3420_interrupts_uninit(PCIDevice *d) 808135aeedSIsaku Yamahata { 8161620c2fSIsaku Yamahata msi_uninit(d); 828135aeedSIsaku Yamahata } 838135aeedSIsaku Yamahata 848135aeedSIsaku Yamahata static const VMStateDescription vmstate_ioh3420 = { 858135aeedSIsaku Yamahata .name = "ioh-3240-express-root-port", 869d6b9db1SPeter Xu .priority = MIG_PRI_PCI_BUS, 878135aeedSIsaku Yamahata .version_id = 1, 888135aeedSIsaku Yamahata .minimum_version_id = 1, 896bde6aaaSMichael S. Tsirkin .post_load = pcie_cap_slot_post_load, 908135aeedSIsaku Yamahata .fields = (VMStateField[]) { 9120daa90aSDr. David Alan Gilbert VMSTATE_PCI_DEVICE(parent_obj.parent_obj.parent_obj, PCIESlot), 92bcb75750SAndreas Färber VMSTATE_STRUCT(parent_obj.parent_obj.parent_obj.exp.aer_log, 93bcb75750SAndreas Färber PCIESlot, 0, vmstate_pcie_aer_log, PCIEAERLog), 948135aeedSIsaku Yamahata VMSTATE_END_OF_LIST() 958135aeedSIsaku Yamahata } 968135aeedSIsaku Yamahata }; 978135aeedSIsaku Yamahata 9840021f08SAnthony Liguori static void ioh3420_class_init(ObjectClass *klass, void *data) 9940021f08SAnthony Liguori { 10039bffca2SAnthony Liguori DeviceClass *dc = DEVICE_CLASS(klass); 10140021f08SAnthony Liguori PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); 102fed23cb4SMarcel Apfelbaum PCIERootPortClass *rpc = PCIE_ROOT_PORT_CLASS(klass); 10340021f08SAnthony Liguori 10440021f08SAnthony Liguori k->vendor_id = PCI_VENDOR_ID_INTEL; 10540021f08SAnthony Liguori k->device_id = PCI_DEVICE_ID_IOH_EPORT; 10640021f08SAnthony Liguori k->revision = PCI_DEVICE_ID_IOH_REV; 10739bffca2SAnthony Liguori dc->desc = "Intel IOH device id 3420 PCIE Root Port"; 10839bffca2SAnthony Liguori dc->vmsd = &vmstate_ioh3420; 109fed23cb4SMarcel Apfelbaum rpc->aer_vector = ioh3420_aer_vector; 110fed23cb4SMarcel Apfelbaum rpc->interrupts_init = ioh3420_interrupts_init; 111fed23cb4SMarcel Apfelbaum rpc->interrupts_uninit = ioh3420_interrupts_uninit; 112fed23cb4SMarcel Apfelbaum rpc->exp_offset = IOH_EP_EXP_OFFSET; 113fed23cb4SMarcel Apfelbaum rpc->aer_offset = IOH_EP_AER_OFFSET; 114fed23cb4SMarcel Apfelbaum rpc->ssvid_offset = IOH_EP_SSVID_OFFSET; 115fed23cb4SMarcel Apfelbaum rpc->ssid = IOH_EP_SSVID_SSID; 1168135aeedSIsaku Yamahata } 11740021f08SAnthony Liguori 1188c43a6f0SAndreas Färber static const TypeInfo ioh3420_info = { 11940021f08SAnthony Liguori .name = "ioh3420", 120fed23cb4SMarcel Apfelbaum .parent = TYPE_PCIE_ROOT_PORT, 12140021f08SAnthony Liguori .class_init = ioh3420_class_init, 1228135aeedSIsaku Yamahata }; 1238135aeedSIsaku Yamahata 12483f7d43aSAndreas Färber static void ioh3420_register_types(void) 1258135aeedSIsaku Yamahata { 12639bffca2SAnthony Liguori type_register_static(&ioh3420_info); 1278135aeedSIsaku Yamahata } 1288135aeedSIsaku Yamahata 12983f7d43aSAndreas Färber type_init(ioh3420_register_types) 130