1bc20ba98SIsaku Yamahata /* 2bc20ba98SIsaku Yamahata * pcie_port.c 3bc20ba98SIsaku Yamahata * 4bc20ba98SIsaku Yamahata * Copyright (c) 2010 Isaku Yamahata <yamahata at valinux co jp> 5bc20ba98SIsaku Yamahata * VA Linux Systems Japan K.K. 6bc20ba98SIsaku Yamahata * 7bc20ba98SIsaku Yamahata * This program is free software; you can redistribute it and/or modify 8bc20ba98SIsaku Yamahata * it under the terms of the GNU General Public License as published by 9bc20ba98SIsaku Yamahata * the Free Software Foundation; either version 2 of the License, or 10bc20ba98SIsaku Yamahata * (at your option) any later version. 11bc20ba98SIsaku Yamahata * 12bc20ba98SIsaku Yamahata * This program is distributed in the hope that it will be useful, 13bc20ba98SIsaku Yamahata * but WITHOUT ANY WARRANTY; without even the implied warranty of 14bc20ba98SIsaku Yamahata * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15bc20ba98SIsaku Yamahata * GNU General Public License for more details. 16bc20ba98SIsaku Yamahata * 17bc20ba98SIsaku Yamahata * You should have received a copy of the GNU General Public License along 18bc20ba98SIsaku Yamahata * with this program; if not, see <http://www.gnu.org/licenses/>. 19bc20ba98SIsaku Yamahata */ 20bc20ba98SIsaku Yamahata 21*c759b24fSMichael S. Tsirkin #include "hw/pci/pcie_port.h" 22bc20ba98SIsaku Yamahata 23bc20ba98SIsaku Yamahata void pcie_port_init_reg(PCIDevice *d) 24bc20ba98SIsaku Yamahata { 25bc20ba98SIsaku Yamahata /* Unlike pci bridge, 26bc20ba98SIsaku Yamahata 66MHz and fast back to back don't apply to pci express port. */ 27bc20ba98SIsaku Yamahata pci_set_word(d->config + PCI_STATUS, 0); 28bc20ba98SIsaku Yamahata pci_set_word(d->config + PCI_SEC_STATUS, 0); 29bc20ba98SIsaku Yamahata 30633442ffSMichael S. Tsirkin /* Unlike conventional pci bridge, some bits are hardwired to 0. */ 31bba5ed77SIsaku Yamahata pci_set_word(d->wmask + PCI_BRIDGE_CONTROL, 32bba5ed77SIsaku Yamahata PCI_BRIDGE_CTL_PARITY | 33bba5ed77SIsaku Yamahata PCI_BRIDGE_CTL_ISA | 34bba5ed77SIsaku Yamahata PCI_BRIDGE_CTL_VGA | 35bba5ed77SIsaku Yamahata PCI_BRIDGE_CTL_SERR | 36bba5ed77SIsaku Yamahata PCI_BRIDGE_CTL_BUS_RESET); 37bc20ba98SIsaku Yamahata } 38bc20ba98SIsaku Yamahata 39bc20ba98SIsaku Yamahata /************************************************************************** 40bc20ba98SIsaku Yamahata * (chassis number, pcie physical slot number) -> pcie slot conversion 41bc20ba98SIsaku Yamahata */ 42bc20ba98SIsaku Yamahata struct PCIEChassis { 43bc20ba98SIsaku Yamahata uint8_t number; 44bc20ba98SIsaku Yamahata 45bc20ba98SIsaku Yamahata QLIST_HEAD(, PCIESlot) slots; 46bc20ba98SIsaku Yamahata QLIST_ENTRY(PCIEChassis) next; 47bc20ba98SIsaku Yamahata }; 48bc20ba98SIsaku Yamahata 49bc20ba98SIsaku Yamahata static QLIST_HEAD(, PCIEChassis) chassis = QLIST_HEAD_INITIALIZER(chassis); 50bc20ba98SIsaku Yamahata 51bc20ba98SIsaku Yamahata static struct PCIEChassis *pcie_chassis_find(uint8_t chassis_number) 52bc20ba98SIsaku Yamahata { 53bc20ba98SIsaku Yamahata struct PCIEChassis *c; 54bc20ba98SIsaku Yamahata QLIST_FOREACH(c, &chassis, next) { 55bc20ba98SIsaku Yamahata if (c->number == chassis_number) { 56bc20ba98SIsaku Yamahata break; 57bc20ba98SIsaku Yamahata } 58bc20ba98SIsaku Yamahata } 59bc20ba98SIsaku Yamahata return c; 60bc20ba98SIsaku Yamahata } 61bc20ba98SIsaku Yamahata 62bc20ba98SIsaku Yamahata void pcie_chassis_create(uint8_t chassis_number) 63bc20ba98SIsaku Yamahata { 64bc20ba98SIsaku Yamahata struct PCIEChassis *c; 65bc20ba98SIsaku Yamahata c = pcie_chassis_find(chassis_number); 66bc20ba98SIsaku Yamahata if (c) { 67bc20ba98SIsaku Yamahata return; 68bc20ba98SIsaku Yamahata } 697267c094SAnthony Liguori c = g_malloc0(sizeof(*c)); 70bc20ba98SIsaku Yamahata c->number = chassis_number; 71bc20ba98SIsaku Yamahata QLIST_INIT(&c->slots); 72bc20ba98SIsaku Yamahata QLIST_INSERT_HEAD(&chassis, c, next); 73bc20ba98SIsaku Yamahata } 74bc20ba98SIsaku Yamahata 75bc20ba98SIsaku Yamahata static PCIESlot *pcie_chassis_find_slot_with_chassis(struct PCIEChassis *c, 76bc20ba98SIsaku Yamahata uint8_t slot) 77bc20ba98SIsaku Yamahata { 78bc20ba98SIsaku Yamahata PCIESlot *s; 79bc20ba98SIsaku Yamahata QLIST_FOREACH(s, &c->slots, next) { 80bc20ba98SIsaku Yamahata if (s->slot == slot) { 81bc20ba98SIsaku Yamahata break; 82bc20ba98SIsaku Yamahata } 83bc20ba98SIsaku Yamahata } 84bc20ba98SIsaku Yamahata return s; 85bc20ba98SIsaku Yamahata } 86bc20ba98SIsaku Yamahata 87bc20ba98SIsaku Yamahata PCIESlot *pcie_chassis_find_slot(uint8_t chassis_number, uint16_t slot) 88bc20ba98SIsaku Yamahata { 89bc20ba98SIsaku Yamahata struct PCIEChassis *c; 90bc20ba98SIsaku Yamahata c = pcie_chassis_find(chassis_number); 91bc20ba98SIsaku Yamahata if (!c) { 92bc20ba98SIsaku Yamahata return NULL; 93bc20ba98SIsaku Yamahata } 94bc20ba98SIsaku Yamahata return pcie_chassis_find_slot_with_chassis(c, slot); 95bc20ba98SIsaku Yamahata } 96bc20ba98SIsaku Yamahata 97bc20ba98SIsaku Yamahata int pcie_chassis_add_slot(struct PCIESlot *slot) 98bc20ba98SIsaku Yamahata { 99bc20ba98SIsaku Yamahata struct PCIEChassis *c; 100bc20ba98SIsaku Yamahata c = pcie_chassis_find(slot->chassis); 101bc20ba98SIsaku Yamahata if (!c) { 102bc20ba98SIsaku Yamahata return -ENODEV; 103bc20ba98SIsaku Yamahata } 104bc20ba98SIsaku Yamahata if (pcie_chassis_find_slot_with_chassis(c, slot->slot)) { 105bc20ba98SIsaku Yamahata return -EBUSY; 106bc20ba98SIsaku Yamahata } 107bc20ba98SIsaku Yamahata QLIST_INSERT_HEAD(&c->slots, slot, next); 108bc20ba98SIsaku Yamahata return 0; 109bc20ba98SIsaku Yamahata } 110bc20ba98SIsaku Yamahata 111bc20ba98SIsaku Yamahata void pcie_chassis_del_slot(PCIESlot *s) 112bc20ba98SIsaku Yamahata { 113bc20ba98SIsaku Yamahata QLIST_REMOVE(s, next); 114bc20ba98SIsaku Yamahata } 115