]> git.proxmox.com Git - qemu.git/blame - hw/apb_pci.c
kvm: Restrict configure check to Linux
[qemu.git] / hw / apb_pci.c
CommitLineData
502a5395
PB
1/*
2 * QEMU Ultrasparc APB PCI host
3 *
4 * Copyright (c) 2006 Fabrice Bellard
5fafdf24 5 *
502a5395
PB
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
80b3ada7 24
a94fd955 25/* XXX This file and most of its contents are somewhat misnamed. The
80b3ada7
PB
26 Ultrasparc PCI host is called the PCI Bus Module (PBM). The APB is
27 the secondary PCI bridge. */
28
87ecb68b
PB
29#include "hw.h"
30#include "pci.h"
a94fd955
BS
31
32/* debug APB */
33//#define DEBUG_APB
34
35#ifdef DEBUG_APB
001faf32
BS
36#define APB_DPRINTF(fmt, ...) \
37do { printf("APB: " fmt , ## __VA_ARGS__); } while (0)
a94fd955 38#else
001faf32 39#define APB_DPRINTF(fmt, ...)
a94fd955
BS
40#endif
41
502a5395
PB
42typedef target_phys_addr_t pci_addr_t;
43#include "pci_host.h"
44
45typedef PCIHostState APBState;
46
47static void pci_apb_config_writel (void *opaque, target_phys_addr_t addr,
48 uint32_t val)
49{
50 APBState *s = opaque;
502a5395 51
a94fd955
BS
52#ifdef TARGET_WORDS_BIGENDIAN
53 val = bswap32(val);
54#endif
55 APB_DPRINTF("config_writel addr " TARGET_FMT_plx " val %x\n", addr,
56 val);
57 s->config_reg = val;
502a5395
PB
58}
59
60static uint32_t pci_apb_config_readl (void *opaque,
61 target_phys_addr_t addr)
62{
63 APBState *s = opaque;
64 uint32_t val;
502a5395 65
a94fd955
BS
66 val = s->config_reg;
67#ifdef TARGET_WORDS_BIGENDIAN
68 val = bswap32(val);
69#endif
70 APB_DPRINTF("config_readl addr " TARGET_FMT_plx " val %x\n", addr,
71 val);
502a5395
PB
72 return val;
73}
74
75static CPUWriteMemoryFunc *pci_apb_config_write[] = {
76 &pci_apb_config_writel,
77 &pci_apb_config_writel,
78 &pci_apb_config_writel,
79};
80
81static CPUReadMemoryFunc *pci_apb_config_read[] = {
82 &pci_apb_config_readl,
83 &pci_apb_config_readl,
84 &pci_apb_config_readl,
85};
86
87static void apb_config_writel (void *opaque, target_phys_addr_t addr,
f930d07e 88 uint32_t val)
502a5395
PB
89{
90 //PCIBus *s = opaque;
91
92 switch (addr & 0x3f) {
93 case 0x00: // Control/Status
94 case 0x10: // AFSR
95 case 0x18: // AFAR
96 case 0x20: // Diagnostic
97 case 0x28: // Target address space
f930d07e 98 // XXX
502a5395 99 default:
f930d07e 100 break;
502a5395
PB
101 }
102}
103
104static uint32_t apb_config_readl (void *opaque,
f930d07e 105 target_phys_addr_t addr)
502a5395
PB
106{
107 //PCIBus *s = opaque;
108 uint32_t val;
109
110 switch (addr & 0x3f) {
111 case 0x00: // Control/Status
112 case 0x10: // AFSR
113 case 0x18: // AFAR
114 case 0x20: // Diagnostic
115 case 0x28: // Target address space
f930d07e 116 // XXX
502a5395 117 default:
f930d07e
BS
118 val = 0;
119 break;
502a5395
PB
120 }
121 return val;
122}
123
124static CPUWriteMemoryFunc *apb_config_write[] = {
125 &apb_config_writel,
126 &apb_config_writel,
127 &apb_config_writel,
128};
129
130static CPUReadMemoryFunc *apb_config_read[] = {
131 &apb_config_readl,
132 &apb_config_readl,
133 &apb_config_readl,
134};
135
136static CPUWriteMemoryFunc *pci_apb_write[] = {
137 &pci_host_data_writeb,
138 &pci_host_data_writew,
139 &pci_host_data_writel,
140};
141
142static CPUReadMemoryFunc *pci_apb_read[] = {
143 &pci_host_data_readb,
144 &pci_host_data_readw,
145 &pci_host_data_readl,
146};
147
148static void pci_apb_iowriteb (void *opaque, target_phys_addr_t addr,
149 uint32_t val)
150{
151 cpu_outb(NULL, addr & 0xffff, val);
152}
153
154static void pci_apb_iowritew (void *opaque, target_phys_addr_t addr,
155 uint32_t val)
156{
157 cpu_outw(NULL, addr & 0xffff, val);
158}
159
160static void pci_apb_iowritel (void *opaque, target_phys_addr_t addr,
161 uint32_t val)
162{
163 cpu_outl(NULL, addr & 0xffff, val);
164}
165
166static uint32_t pci_apb_ioreadb (void *opaque, target_phys_addr_t addr)
167{
168 uint32_t val;
169
170 val = cpu_inb(NULL, addr & 0xffff);
171 return val;
172}
173
174static uint32_t pci_apb_ioreadw (void *opaque, target_phys_addr_t addr)
175{
176 uint32_t val;
177
178 val = cpu_inw(NULL, addr & 0xffff);
179 return val;
180}
181
182static uint32_t pci_apb_ioreadl (void *opaque, target_phys_addr_t addr)
183{
184 uint32_t val;
185
186 val = cpu_inl(NULL, addr & 0xffff);
187 return val;
188}
189
190static CPUWriteMemoryFunc *pci_apb_iowrite[] = {
191 &pci_apb_iowriteb,
192 &pci_apb_iowritew,
193 &pci_apb_iowritel,
194};
195
196static CPUReadMemoryFunc *pci_apb_ioread[] = {
197 &pci_apb_ioreadb,
198 &pci_apb_ioreadw,
199 &pci_apb_ioreadl,
200};
201
80b3ada7 202/* The APB host has an IRQ line for each IRQ line of each slot. */
d2b59317 203static int pci_apb_map_irq(PCIDevice *pci_dev, int irq_num)
502a5395 204{
80b3ada7
PB
205 return ((pci_dev->devfn & 0x18) >> 1) + irq_num;
206}
207
208static int pci_pbm_map_irq(PCIDevice *pci_dev, int irq_num)
209{
210 int bus_offset;
211 if (pci_dev->devfn & 1)
212 bus_offset = 16;
213 else
214 bus_offset = 0;
215 return bus_offset + irq_num;
d2b59317
PB
216}
217
d537cf6c 218static void pci_apb_set_irq(qemu_irq *pic, int irq_num, int level)
d2b59317 219{
80b3ada7 220 /* PCI IRQ map onto the first 32 INO. */
d537cf6c 221 qemu_set_irq(pic[irq_num], level);
502a5395
PB
222}
223
fdf41d22
BS
224PCIBus *pci_apb_init(target_phys_addr_t special_base,
225 target_phys_addr_t mem_base,
c190ea07 226 qemu_irq *pic, PCIBus **bus2, PCIBus **bus3)
502a5395
PB
227{
228 APBState *s;
229 PCIDevice *d;
230 int pci_mem_config, pci_mem_data, apb_config, pci_ioport;
231
232 s = qemu_mallocz(sizeof(APBState));
80b3ada7 233 /* Ultrasparc PBM main bus */
02e2da45
PB
234 s->bus = pci_register_bus(NULL, "pci",
235 pci_apb_set_irq, pci_pbm_map_irq, pic, 0, 32);
502a5395
PB
236
237 pci_mem_config = cpu_register_io_memory(0, pci_apb_config_read,
238 pci_apb_config_write, s);
239 apb_config = cpu_register_io_memory(0, apb_config_read,
f930d07e 240 apb_config_write, s);
502a5395
PB
241 pci_mem_data = cpu_register_io_memory(0, pci_apb_read,
242 pci_apb_write, s);
243 pci_ioport = cpu_register_io_memory(0, pci_apb_ioread,
244 pci_apb_iowrite, s);
245
246 cpu_register_physical_memory(special_base + 0x2000ULL, 0x40, apb_config);
77f193da
BS
247 cpu_register_physical_memory(special_base + 0x1000000ULL, 0x10,
248 pci_mem_config);
249 cpu_register_physical_memory(special_base + 0x2000000ULL, 0x10000,
250 pci_ioport);
251 cpu_register_physical_memory(mem_base, 0x10000000,
252 pci_mem_data); // XXX size should be 4G-prom
502a5395 253
5fafdf24 254 d = pci_register_device(s->bus, "Advanced PCI Bus", sizeof(PCIDevice),
80b3ada7 255 0, NULL, NULL);
deb54399
AL
256 pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_SUN);
257 pci_config_set_device_id(d->config, PCI_DEVICE_ID_SUN_SABRE);
502a5395
PB
258 d->config[0x04] = 0x06; // command = bus master, pci mem
259 d->config[0x05] = 0x00;
260 d->config[0x06] = 0xa0; // status = fast back-to-back, 66MHz, no error
261 d->config[0x07] = 0x03; // status = medium devsel
262 d->config[0x08] = 0x00; // revision
263 d->config[0x09] = 0x00; // programming i/f
173a543b 264 pci_config_set_class(d->config, PCI_CLASS_BRIDGE_HOST);
502a5395 265 d->config[0x0D] = 0x10; // latency_timer
6407f373 266 d->config[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type
80b3ada7
PB
267
268 /* APB secondary busses */
480b9f24
BS
269 *bus2 = pci_bridge_init(s->bus, 8, PCI_VENDOR_ID_SUN,
270 PCI_DEVICE_ID_SUN_SIMBA, pci_apb_map_irq,
c190ea07 271 "Advanced PCI Bus secondary bridge 1");
480b9f24
BS
272 *bus3 = pci_bridge_init(s->bus, 9, PCI_VENDOR_ID_SUN,
273 PCI_DEVICE_ID_SUN_SIMBA, pci_apb_map_irq,
c190ea07 274 "Advanced PCI Bus secondary bridge 2");
a94fd955 275 return s->bus;
502a5395 276}