Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / qemu-palcode / pci.c
1 /* Simplistic PCI support.
2
3    Copyright (C) 2011 Richard Henderson
4
5    This file is part of QEMU PALcode.
6
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.
11
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.
16
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/>.  */
20
21 /* We don't bother supporting PCI bridges, because the device model we're
22    currently using for QEMU doesn't build any.
23
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.  */
28
29 #include "protos.h"
30 #include "pci.h"
31 #include "pci_regs.h"
32
33
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
42
43
44 void
45 pci_config_maskw(int bdf, int addr, uint16_t off, uint16_t on)
46 {
47   uint16_t val = pci_config_readw(bdf, addr);
48   val = (val & ~off) | on;
49   pci_config_writew(bdf, addr, val);
50 }
51
52 int
53 pci_next(int bdf, int *pmax)
54 {
55   int max;
56
57   if (PCI_FUNC(bdf) == 1)
58     {
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;
62     }
63
64   max = *pmax;
65   while (1)
66     {
67       uint16_t vendor;
68
69       /* ??? Support multiple PCI busses here at some point.  */
70       if (bdf >= max)
71         return -1;
72
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;
77
78       bdf += (PCI_FUNC(bdf) == 0 ? 8 : 1);
79     }
80 }
81
82 static void
83 pci_setup_device(int bdf, uint32_t *p_io_base, uint32_t *p_mem_base)
84 {
85   int vendor_id, device_id, class_id, region;
86
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);
90
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);
94
95   for (region = 0; region < PCI_REGION_ROM; region++)
96     {
97       int ofs = PCI_BASE_ADDRESS_0 + region * 4;
98       uint32_t old, mask, val, size, align;
99       uint32_t *p_base;
100
101       old = pci_config_readl(bdf, ofs);
102       if (old & PCI_BASE_ADDRESS_SPACE_IO)
103         {
104           mask = PCI_BASE_ADDRESS_IO_MASK;
105           p_base = p_io_base;
106         }
107       else
108         {
109           mask = PCI_BASE_ADDRESS_MEM_MASK;
110           p_base = p_mem_base;
111         }
112
113       pci_config_writel(bdf, ofs, -1);
114       val = pci_config_readl(bdf, ofs);
115       pci_config_writel(bdf, ofs, old);
116
117       align = size = ~(val & mask) + 1;
118       if (val != 0)
119         {
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);
124
125           printf("PCI:   region %d: %08x\r\n", region, addr);
126
127           if ((val & PCI_BASE_ADDRESS_MEM_TYPE_MASK)
128               == PCI_BASE_ADDRESS_MEM_TYPE_64)
129             {
130               pci_config_writel(bdf, ofs + 4, 0);
131               region++;
132             }
133         }
134     }
135
136   pci_config_maskw(bdf, PCI_COMMAND, 0, PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
137
138   /* Map the interrupt.  */
139 }
140
141 void
142 pci_setup(void)
143 {
144   uint32_t io_base = 0xc000;
145   uint32_t mem_base = 256 * 1024 * 1024;
146   int bdf, max;
147
148   foreachpci (bdf, max)
149     pci_setup_device(bdf, &io_base, &mem_base);
150 }