Add Cserve_Get_VM_Time
[qemu-palcode.git] / pci.c
blob87a101cc40304c22674596997eaf885f4fd85bb7
1 /* Simplistic PCI support.
3 Copyright (C) 2011 Richard Henderson
5 This file is part of QEMU PALcode.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the text
15 of the GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; see the file COPYING. If not see
19 <http://www.gnu.org/licenses/>. */
21 /* We don't bother supporting PCI bridges, because the device model we're
22 currently using for QEMU doesn't build any.
24 We don't bother to build real datastructures in memory, because it's
25 fairly quick under emulation simply to access configuration space again.
26 This helps when running kernels under the emulator that might have
27 re-organized the BARs out from under us. */
29 #include "protos.h"
30 #include "pci.h"
31 #include "pci_regs.h"
34 #define PCI_DEVFN(slot, func) ((((slot) & 0x1f) << 3) | ((func) & 0x07))
35 #define PCI_BUS(devfn) ((devfn) >> 8)
36 #define PCI_SLOT(devfn) (((devfn) >> 3) & 0x1f)
37 #define PCI_FUNC(devfn) ((devfn) & 0x07)
38 #define PCI_SLOT_MAX 32
39 #define PCI_FUNC_MAX 8
40 #define PCI_REGION_ROM 6
41 #define PCI_REGIONS_MAX 7
44 void
45 pci_config_maskw(int bdf, int addr, uint16_t off, uint16_t on)
47 uint16_t val = pci_config_readw(bdf, addr);
48 val = (val & ~off) | on;
49 pci_config_writew(bdf, addr, val);
52 int
53 pci_next(int bdf, int *pmax)
55 int max;
57 if (PCI_FUNC(bdf) == 1)
59 /* If the last device was not a multi-function device, skip to next. */
60 if ((pci_config_readb(bdf-1, PCI_HEADER_TYPE) & 0x80) == 0)
61 bdf += 7;
64 max = *pmax;
65 while (1)
67 uint16_t vendor;
69 /* ??? Support multiple PCI busses here at some point. */
70 if (bdf >= max)
71 return -1;
73 /* Check if there is a device present at the location. */
74 vendor = pci_config_readw(bdf, PCI_VENDOR_ID);
75 if (vendor != 0x0000 && vendor != 0xffff)
76 return bdf;
78 bdf += (PCI_FUNC(bdf) == 0 ? 8 : 1);
82 static void
83 pci_setup_device(int bdf, uint32_t *p_io_base, uint32_t *p_mem_base)
85 int vendor_id, device_id, class_id, region;
87 vendor_id = pci_config_readw(bdf, PCI_VENDOR_ID);
88 device_id = pci_config_readw(bdf, PCI_DEVICE_ID);
89 class_id = pci_config_readw(bdf, PCI_CLASS_DEVICE);
91 printf("PCI: %02x:%02x:%x class %04x id %04x:%04x\r\n",
92 PCI_BUS(bdf), PCI_SLOT(bdf), PCI_FUNC(bdf),
93 class_id, vendor_id, device_id);
95 for (region = 0; region < PCI_REGION_ROM; region++)
97 int ofs = PCI_BASE_ADDRESS_0 + region * 4;
98 uint32_t old, mask, val, size, align;
99 uint32_t *p_base;
101 old = pci_config_readl(bdf, ofs);
102 if (old & PCI_BASE_ADDRESS_SPACE_IO)
104 mask = PCI_BASE_ADDRESS_IO_MASK;
105 p_base = p_io_base;
107 else
109 mask = PCI_BASE_ADDRESS_MEM_MASK;
110 p_base = p_mem_base;
113 pci_config_writel(bdf, ofs, -1);
114 val = pci_config_readl(bdf, ofs);
115 pci_config_writel(bdf, ofs, old);
117 align = size = ~(val & mask) + 1;
118 if (val != 0)
120 uint32_t addr = *p_base;
121 addr = (addr + align - 1) & ~(align - 1);
122 *p_base = addr + size;
123 pci_config_writel(bdf, ofs, addr);
125 printf("PCI: region %d: %08x\r\n", region, addr);
127 if ((val & PCI_BASE_ADDRESS_MEM_TYPE_MASK)
128 == PCI_BASE_ADDRESS_MEM_TYPE_64)
130 pci_config_writel(bdf, ofs + 4, 0);
131 region++;
136 pci_config_maskw(bdf, PCI_COMMAND, 0, PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
138 /* Map the interrupt. */
141 void
142 pci_setup(void)
144 uint32_t io_base = 0xc000;
145 uint32_t mem_base = 256 * 1024 * 1024;
146 int bdf, max;
148 foreachpci (bdf, max)
149 pci_setup_device(bdf, &io_base, &mem_base);