]> git.proxmox.com Git - qemu.git/blame - hw/apb_pci.c
fix savevm command without id or tag
[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
72f44c8c 29#include "sysbus.h"
87ecb68b 30#include "pci.h"
4f5e19e6 31#include "pci_host.h"
18e08a55 32#include "apb_pci.h"
a94fd955
BS
33
34/* debug APB */
35//#define DEBUG_APB
36
37#ifdef DEBUG_APB
001faf32
BS
38#define APB_DPRINTF(fmt, ...) \
39do { printf("APB: " fmt , ## __VA_ARGS__); } while (0)
a94fd955 40#else
001faf32 41#define APB_DPRINTF(fmt, ...)
a94fd955
BS
42#endif
43
930f3fe1
BS
44/*
45 * Chipset docs:
46 * PBM: "UltraSPARC IIi User's Manual",
47 * http://www.sun.com/processors/manuals/805-0087.pdf
48 *
49 * APB: "Advanced PCI Bridge (APB) User's Manual",
50 * http://www.sun.com/processors/manuals/805-1251.pdf
51 */
52
72f44c8c
BS
53typedef struct APBState {
54 SysBusDevice busdev;
55 PCIHostState host_state;
56} APBState;
502a5395 57
c227f099 58static void apb_config_writel (void *opaque, target_phys_addr_t addr,
f930d07e 59 uint32_t val)
502a5395
PB
60{
61 //PCIBus *s = opaque;
62
63 switch (addr & 0x3f) {
64 case 0x00: // Control/Status
65 case 0x10: // AFSR
66 case 0x18: // AFAR
67 case 0x20: // Diagnostic
68 case 0x28: // Target address space
f930d07e 69 // XXX
502a5395 70 default:
f930d07e 71 break;
502a5395
PB
72 }
73}
74
75static uint32_t apb_config_readl (void *opaque,
c227f099 76 target_phys_addr_t addr)
502a5395
PB
77{
78 //PCIBus *s = opaque;
79 uint32_t val;
80
81 switch (addr & 0x3f) {
82 case 0x00: // Control/Status
83 case 0x10: // AFSR
84 case 0x18: // AFAR
85 case 0x20: // Diagnostic
86 case 0x28: // Target address space
f930d07e 87 // XXX
502a5395 88 default:
f930d07e
BS
89 val = 0;
90 break;
502a5395
PB
91 }
92 return val;
93}
94
d60efc6b 95static CPUWriteMemoryFunc * const apb_config_write[] = {
502a5395
PB
96 &apb_config_writel,
97 &apb_config_writel,
98 &apb_config_writel,
99};
100
d60efc6b 101static CPUReadMemoryFunc * const apb_config_read[] = {
502a5395
PB
102 &apb_config_readl,
103 &apb_config_readl,
104 &apb_config_readl,
105};
106
5a5d4a76
BS
107static void apb_pci_config_write(APBState *s, target_phys_addr_t addr,
108 uint32_t val, int size)
109{
110 APB_DPRINTF("%s: addr " TARGET_FMT_lx " val %x\n", __func__, addr, val);
111 pci_data_write(s->host_state.bus, (addr & 0x00ffffff) | (1u << 31), val,
112 size);
113}
114
115static uint32_t apb_pci_config_read(APBState *s, target_phys_addr_t addr,
116 int size)
117{
118 uint32_t ret;
119
120 ret = pci_data_read(s->host_state.bus, (addr & 0x00ffffff) | (1u << 31),
121 size);
122 APB_DPRINTF("%s: addr " TARGET_FMT_lx " -> %x\n", __func__, addr, ret);
123 return ret;
124}
125
126static void apb_pci_config_writel(void *opaque, target_phys_addr_t addr,
127 uint32_t val)
128{
129 APBState *s = opaque;
130
204c7a39 131 apb_pci_config_write(s, addr, bswap32(val), 4);
5a5d4a76
BS
132}
133
134static void apb_pci_config_writew(void *opaque, target_phys_addr_t addr,
135 uint32_t val)
136{
137 APBState *s = opaque;
138
204c7a39 139 apb_pci_config_write(s, addr, bswap16(val), 2);
5a5d4a76
BS
140}
141
142static void apb_pci_config_writeb(void *opaque, target_phys_addr_t addr,
143 uint32_t val)
144{
145 APBState *s = opaque;
146
147 apb_pci_config_write(s, addr, val, 1);
148}
149
150static uint32_t apb_pci_config_readl(void *opaque, target_phys_addr_t addr)
151{
152 APBState *s = opaque;
153
204c7a39 154 return bswap32(apb_pci_config_read(s, addr, 4));
5a5d4a76
BS
155}
156
157static uint32_t apb_pci_config_readw(void *opaque, target_phys_addr_t addr)
158{
159 APBState *s = opaque;
160
204c7a39 161 return bswap16(apb_pci_config_read(s, addr, 2));
5a5d4a76
BS
162}
163
164static uint32_t apb_pci_config_readb(void *opaque, target_phys_addr_t addr)
165{
166 APBState *s = opaque;
167
168 return apb_pci_config_read(s, addr, 1);
169}
170
171static CPUWriteMemoryFunc * const apb_pci_config_writes[] = {
5a5d4a76 172 &apb_pci_config_writeb,
3eb26cc2
BS
173 &apb_pci_config_writew,
174 &apb_pci_config_writel,
5a5d4a76
BS
175};
176
177static CPUReadMemoryFunc * const apb_pci_config_reads[] = {
5a5d4a76 178 &apb_pci_config_readb,
3eb26cc2
BS
179 &apb_pci_config_readw,
180 &apb_pci_config_readl,
5a5d4a76
BS
181};
182
c227f099 183static void pci_apb_iowriteb (void *opaque, target_phys_addr_t addr,
502a5395
PB
184 uint32_t val)
185{
afcea8cb 186 cpu_outb(addr & IOPORTS_MASK, val);
502a5395
PB
187}
188
c227f099 189static void pci_apb_iowritew (void *opaque, target_phys_addr_t addr,
502a5395
PB
190 uint32_t val)
191{
afcea8cb 192 cpu_outw(addr & IOPORTS_MASK, val);
502a5395
PB
193}
194
c227f099 195static void pci_apb_iowritel (void *opaque, target_phys_addr_t addr,
502a5395
PB
196 uint32_t val)
197{
afcea8cb 198 cpu_outl(addr & IOPORTS_MASK, val);
502a5395
PB
199}
200
c227f099 201static uint32_t pci_apb_ioreadb (void *opaque, target_phys_addr_t addr)
502a5395
PB
202{
203 uint32_t val;
204
afcea8cb 205 val = cpu_inb(addr & IOPORTS_MASK);
502a5395
PB
206 return val;
207}
208
c227f099 209static uint32_t pci_apb_ioreadw (void *opaque, target_phys_addr_t addr)
502a5395
PB
210{
211 uint32_t val;
212
afcea8cb 213 val = cpu_inw(addr & IOPORTS_MASK);
502a5395
PB
214 return val;
215}
216
c227f099 217static uint32_t pci_apb_ioreadl (void *opaque, target_phys_addr_t addr)
502a5395
PB
218{
219 uint32_t val;
220
afcea8cb 221 val = cpu_inl(addr & IOPORTS_MASK);
502a5395
PB
222 return val;
223}
224
d60efc6b 225static CPUWriteMemoryFunc * const pci_apb_iowrite[] = {
502a5395
PB
226 &pci_apb_iowriteb,
227 &pci_apb_iowritew,
228 &pci_apb_iowritel,
229};
230
d60efc6b 231static CPUReadMemoryFunc * const pci_apb_ioread[] = {
502a5395
PB
232 &pci_apb_ioreadb,
233 &pci_apb_ioreadw,
234 &pci_apb_ioreadl,
235};
236
80b3ada7 237/* The APB host has an IRQ line for each IRQ line of each slot. */
d2b59317 238static int pci_apb_map_irq(PCIDevice *pci_dev, int irq_num)
502a5395 239{
80b3ada7
PB
240 return ((pci_dev->devfn & 0x18) >> 1) + irq_num;
241}
242
243static int pci_pbm_map_irq(PCIDevice *pci_dev, int irq_num)
244{
245 int bus_offset;
246 if (pci_dev->devfn & 1)
247 bus_offset = 16;
248 else
249 bus_offset = 0;
250 return bus_offset + irq_num;
d2b59317
PB
251}
252
5d4e84c8 253static void pci_apb_set_irq(void *opaque, int irq_num, int level)
d2b59317 254{
5d4e84c8
JQ
255 qemu_irq *pic = opaque;
256
80b3ada7 257 /* PCI IRQ map onto the first 32 INO. */
d537cf6c 258 qemu_set_irq(pic[irq_num], level);
502a5395
PB
259}
260
d6318738
MT
261static void apb_pci_bridge_init(PCIBus *b)
262{
263 PCIDevice *dev = pci_bridge_get_device(b);
264
265 /*
266 * command register:
267 * According to PCI bridge spec, after reset
268 * bus master bit is off
269 * memory space enable bit is off
270 * According to manual (805-1251.pdf).
271 * the reset value should be zero unless the boot pin is tied high
272 * (which is true) and thus it should be PCI_COMMAND_MEMORY.
273 */
274 pci_set_word(dev->config + PCI_COMMAND,
275 PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
276 dev->config[PCI_LATENCY_TIMER] = 0x10;
277 dev->config[PCI_HEADER_TYPE] |= PCI_HEADER_TYPE_MULTI_FUNCTION;
278}
279
c227f099
AL
280PCIBus *pci_apb_init(target_phys_addr_t special_base,
281 target_phys_addr_t mem_base,
c190ea07 282 qemu_irq *pic, PCIBus **bus2, PCIBus **bus3)
502a5395 283{
72f44c8c
BS
284 DeviceState *dev;
285 SysBusDevice *s;
286 APBState *d;
502a5395 287
80b3ada7 288 /* Ultrasparc PBM main bus */
72f44c8c 289 dev = qdev_create(NULL, "pbm");
e23a1b33 290 qdev_init_nofail(dev);
72f44c8c
BS
291 s = sysbus_from_qdev(dev);
292 /* apb_config */
bae7b517 293 sysbus_mmio_map(s, 0, special_base);
72f44c8c
BS
294 /* pci_ioport */
295 sysbus_mmio_map(s, 1, special_base + 0x2000000ULL);
204c7a39 296 /* pci_config */
72f44c8c
BS
297 sysbus_mmio_map(s, 2, special_base + 0x1000000ULL);
298 /* mem_data */
204c7a39 299 sysbus_mmio_map(s, 3, mem_base);
72f44c8c 300 d = FROM_SYSBUS(APBState, s);
c5ff6d54 301 d->host_state.bus = pci_register_bus(&d->busdev.qdev, "pci",
72f44c8c
BS
302 pci_apb_set_irq, pci_pbm_map_irq, pic,
303 0, 32);
f6b6f1bc
BS
304 pci_bus_set_mem_base(d->host_state.bus, mem_base);
305
72f44c8c
BS
306 pci_create_simple(d->host_state.bus, 0, "pbm");
307 /* APB secondary busses */
2217dcff
IY
308 *bus2 = pci_bridge_init(d->host_state.bus, PCI_DEVFN(1, 0),
309 PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_SIMBA,
310 pci_apb_map_irq,
72f44c8c 311 "Advanced PCI Bus secondary bridge 1");
d6318738
MT
312 apb_pci_bridge_init(*bus2);
313
2217dcff
IY
314 *bus3 = pci_bridge_init(d->host_state.bus, PCI_DEVFN(1, 1),
315 PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_SIMBA,
316 pci_apb_map_irq,
72f44c8c 317 "Advanced PCI Bus secondary bridge 2");
d6318738 318 apb_pci_bridge_init(*bus3);
502a5395 319
72f44c8c
BS
320 return d->host_state.bus;
321}
322
81a322d4 323static int pci_pbm_init_device(SysBusDevice *dev)
72f44c8c
BS
324{
325
326 APBState *s;
204c7a39 327 int pci_mem_data, apb_config, pci_ioport, pci_config;
72f44c8c
BS
328
329 s = FROM_SYSBUS(APBState, dev);
330 /* apb_config */
1eed09cb 331 apb_config = cpu_register_io_memory(apb_config_read,
f930d07e 332 apb_config_write, s);
bae7b517 333 sysbus_init_mmio(dev, 0x10000ULL, apb_config);
72f44c8c 334 /* pci_ioport */
1eed09cb 335 pci_ioport = cpu_register_io_memory(pci_apb_ioread,
502a5395 336 pci_apb_iowrite, s);
72f44c8c 337 sysbus_init_mmio(dev, 0x10000ULL, pci_ioport);
5a5d4a76
BS
338 /* pci_config */
339 pci_config = cpu_register_io_memory(apb_pci_config_reads,
340 apb_pci_config_writes, s);
341 sysbus_init_mmio(dev, 0x1000000ULL, pci_config);
72f44c8c 342 /* mem_data */
f08b32fe 343 pci_mem_data = pci_host_data_register_mmio(&s->host_state);
72f44c8c 344 sysbus_init_mmio(dev, 0x10000000ULL, pci_mem_data);
81a322d4 345 return 0;
72f44c8c 346}
502a5395 347
81a322d4 348static int pbm_pci_host_init(PCIDevice *d)
72f44c8c 349{
deb54399
AL
350 pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_SUN);
351 pci_config_set_device_id(d->config, PCI_DEVICE_ID_SUN_SABRE);
502a5395
PB
352 d->config[0x04] = 0x06; // command = bus master, pci mem
353 d->config[0x05] = 0x00;
354 d->config[0x06] = 0xa0; // status = fast back-to-back, 66MHz, no error
355 d->config[0x07] = 0x03; // status = medium devsel
356 d->config[0x08] = 0x00; // revision
357 d->config[0x09] = 0x00; // programming i/f
173a543b 358 pci_config_set_class(d->config, PCI_CLASS_BRIDGE_HOST);
502a5395 359 d->config[0x0D] = 0x10; // latency_timer
110c50fd 360 d->config[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type
81a322d4 361 return 0;
72f44c8c 362}
80b3ada7 363
72f44c8c
BS
364static PCIDeviceInfo pbm_pci_host_info = {
365 .qdev.name = "pbm",
366 .qdev.size = sizeof(PCIDevice),
367 .init = pbm_pci_host_init,
368};
369
370static void pbm_register_devices(void)
371{
372 sysbus_register_dev("pbm", sizeof(APBState), pci_pbm_init_device);
373 pci_qdev_register(&pbm_pci_host_info);
502a5395 374}
72f44c8c
BS
375
376device_init(pbm_register_devices)