Statistics
| Branch: | Revision:

root / hw / apb_pci.c @ d56dd6cf

History | View | Annotate | Download (8.1 kB)

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