]> git.proxmox.com Git - mirror_qemu.git/blob - hw/apb_pci.c
tcg: increase TCG_MAX_OP_SIZE to 192
[mirror_qemu.git] / hw / apb_pci.c
1 /*
2 * QEMU Ultrasparc APB PCI host
3 *
4 * Copyright (c) 2006 Fabrice Bellard
5 *
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 */
24
25 /* XXX This file and most of its contents are somewhat misnamed. The
26 Ultrasparc PCI host is called the PCI Bus Module (PBM). The APB is
27 the secondary PCI bridge. */
28
29 #include "sysbus.h"
30 #include "pci.h"
31 #include "pci_host.h"
32
33 /* debug APB */
34 //#define DEBUG_APB
35
36 #ifdef DEBUG_APB
37 #define APB_DPRINTF(fmt, ...) \
38 do { printf("APB: " fmt , ## __VA_ARGS__); } while (0)
39 #else
40 #define APB_DPRINTF(fmt, ...)
41 #endif
42
43 /*
44 * Chipset docs:
45 * PBM: "UltraSPARC IIi User's Manual",
46 * http://www.sun.com/processors/manuals/805-0087.pdf
47 *
48 * APB: "Advanced PCI Bridge (APB) User's Manual",
49 * http://www.sun.com/processors/manuals/805-1251.pdf
50 */
51
52 typedef struct APBState {
53 SysBusDevice busdev;
54 PCIHostState host_state;
55 } APBState;
56
57 static void apb_config_writel (void *opaque, target_phys_addr_t addr,
58 uint32_t val)
59 {
60 //PCIBus *s = opaque;
61
62 switch (addr & 0x3f) {
63 case 0x00: // Control/Status
64 case 0x10: // AFSR
65 case 0x18: // AFAR
66 case 0x20: // Diagnostic
67 case 0x28: // Target address space
68 // XXX
69 default:
70 break;
71 }
72 }
73
74 static uint32_t apb_config_readl (void *opaque,
75 target_phys_addr_t addr)
76 {
77 //PCIBus *s = opaque;
78 uint32_t val;
79
80 switch (addr & 0x3f) {
81 case 0x00: // Control/Status
82 case 0x10: // AFSR
83 case 0x18: // AFAR
84 case 0x20: // Diagnostic
85 case 0x28: // Target address space
86 // XXX
87 default:
88 val = 0;
89 break;
90 }
91 return val;
92 }
93
94 static CPUWriteMemoryFunc * const apb_config_write[] = {
95 &apb_config_writel,
96 &apb_config_writel,
97 &apb_config_writel,
98 };
99
100 static CPUReadMemoryFunc * const apb_config_read[] = {
101 &apb_config_readl,
102 &apb_config_readl,
103 &apb_config_readl,
104 };
105
106 static void pci_apb_iowriteb (void *opaque, target_phys_addr_t addr,
107 uint32_t val)
108 {
109 cpu_outb(addr & IOPORTS_MASK, val);
110 }
111
112 static void pci_apb_iowritew (void *opaque, target_phys_addr_t addr,
113 uint32_t val)
114 {
115 cpu_outw(addr & IOPORTS_MASK, val);
116 }
117
118 static void pci_apb_iowritel (void *opaque, target_phys_addr_t addr,
119 uint32_t val)
120 {
121 cpu_outl(addr & IOPORTS_MASK, val);
122 }
123
124 static uint32_t pci_apb_ioreadb (void *opaque, target_phys_addr_t addr)
125 {
126 uint32_t val;
127
128 val = cpu_inb(addr & IOPORTS_MASK);
129 return val;
130 }
131
132 static uint32_t pci_apb_ioreadw (void *opaque, target_phys_addr_t addr)
133 {
134 uint32_t val;
135
136 val = cpu_inw(addr & IOPORTS_MASK);
137 return val;
138 }
139
140 static uint32_t pci_apb_ioreadl (void *opaque, target_phys_addr_t addr)
141 {
142 uint32_t val;
143
144 val = cpu_inl(addr & IOPORTS_MASK);
145 return val;
146 }
147
148 static CPUWriteMemoryFunc * const pci_apb_iowrite[] = {
149 &pci_apb_iowriteb,
150 &pci_apb_iowritew,
151 &pci_apb_iowritel,
152 };
153
154 static CPUReadMemoryFunc * const pci_apb_ioread[] = {
155 &pci_apb_ioreadb,
156 &pci_apb_ioreadw,
157 &pci_apb_ioreadl,
158 };
159
160 /* The APB host has an IRQ line for each IRQ line of each slot. */
161 static int pci_apb_map_irq(PCIDevice *pci_dev, int irq_num)
162 {
163 return ((pci_dev->devfn & 0x18) >> 1) + irq_num;
164 }
165
166 static int pci_pbm_map_irq(PCIDevice *pci_dev, int irq_num)
167 {
168 int bus_offset;
169 if (pci_dev->devfn & 1)
170 bus_offset = 16;
171 else
172 bus_offset = 0;
173 return bus_offset + irq_num;
174 }
175
176 static void pci_apb_set_irq(void *opaque, int irq_num, int level)
177 {
178 qemu_irq *pic = opaque;
179
180 /* PCI IRQ map onto the first 32 INO. */
181 qemu_set_irq(pic[irq_num], level);
182 }
183
184 PCIBus *pci_apb_init(target_phys_addr_t special_base,
185 target_phys_addr_t mem_base,
186 qemu_irq *pic, PCIBus **bus2, PCIBus **bus3)
187 {
188 DeviceState *dev;
189 SysBusDevice *s;
190 APBState *d;
191
192 /* Ultrasparc PBM main bus */
193 dev = qdev_create(NULL, "pbm");
194 qdev_init_nofail(dev);
195 s = sysbus_from_qdev(dev);
196 /* apb_config */
197 sysbus_mmio_map(s, 0, special_base + 0x2000ULL);
198 /* pci_ioport */
199 sysbus_mmio_map(s, 1, special_base + 0x2000000ULL);
200 /* mem_config: XXX size should be 4G-prom */
201 sysbus_mmio_map(s, 2, special_base + 0x1000000ULL);
202 /* mem_data */
203 sysbus_mmio_map(s, 3, mem_base);
204 d = FROM_SYSBUS(APBState, s);
205 d->host_state.bus = pci_register_bus(&d->busdev.qdev, "pci",
206 pci_apb_set_irq, pci_pbm_map_irq, pic,
207 0, 32);
208 pci_create_simple(d->host_state.bus, 0, "pbm");
209 /* APB secondary busses */
210 *bus2 = pci_bridge_init(d->host_state.bus, PCI_DEVFN(1, 0),
211 PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_SIMBA,
212 pci_apb_map_irq,
213 "Advanced PCI Bus secondary bridge 1");
214 *bus3 = pci_bridge_init(d->host_state.bus, PCI_DEVFN(1, 1),
215 PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_SIMBA,
216 pci_apb_map_irq,
217 "Advanced PCI Bus secondary bridge 2");
218
219 return d->host_state.bus;
220 }
221
222 static int pci_pbm_init_device(SysBusDevice *dev)
223 {
224
225 APBState *s;
226 int pci_mem_config, pci_mem_data, apb_config, pci_ioport;
227
228 s = FROM_SYSBUS(APBState, dev);
229 /* apb_config */
230 apb_config = cpu_register_io_memory(apb_config_read,
231 apb_config_write, s);
232 sysbus_init_mmio(dev, 0x40ULL, apb_config);
233 /* pci_ioport */
234 pci_ioport = cpu_register_io_memory(pci_apb_ioread,
235 pci_apb_iowrite, s);
236 sysbus_init_mmio(dev, 0x10000ULL, pci_ioport);
237 /* mem_config */
238 pci_mem_config = pci_host_config_register_io_memory(&s->host_state);
239 sysbus_init_mmio(dev, 0x10ULL, pci_mem_config);
240 /* mem_data */
241 pci_mem_data = pci_host_data_register_io_memory(&s->host_state);
242 sysbus_init_mmio(dev, 0x10000000ULL, pci_mem_data);
243 return 0;
244 }
245
246 static int pbm_pci_host_init(PCIDevice *d)
247 {
248 pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_SUN);
249 pci_config_set_device_id(d->config, PCI_DEVICE_ID_SUN_SABRE);
250 d->config[0x04] = 0x06; // command = bus master, pci mem
251 d->config[0x05] = 0x00;
252 d->config[0x06] = 0xa0; // status = fast back-to-back, 66MHz, no error
253 d->config[0x07] = 0x03; // status = medium devsel
254 d->config[0x08] = 0x00; // revision
255 d->config[0x09] = 0x00; // programming i/f
256 pci_config_set_class(d->config, PCI_CLASS_BRIDGE_HOST);
257 d->config[0x0D] = 0x10; // latency_timer
258 d->config[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type
259 return 0;
260 }
261
262 static PCIDeviceInfo pbm_pci_host_info = {
263 .qdev.name = "pbm",
264 .qdev.size = sizeof(PCIDevice),
265 .init = pbm_pci_host_init,
266 };
267
268 static void pbm_register_devices(void)
269 {
270 sysbus_register_dev("pbm", sizeof(APBState), pci_pbm_init_device);
271 pci_qdev_register(&pbm_pci_host_info);
272 }
273
274 device_init(pbm_register_devices)