Statistics
| Branch: | Revision:

root / hw / apb_pci.c @ 9b595395

History | View | Annotate | Download (7.5 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 80b3ada7 pbrook
/* XXX This file and most of its contests 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 502a5395 pbrook
typedef target_phys_addr_t pci_addr_t;
32 502a5395 pbrook
#include "pci_host.h"
33 502a5395 pbrook
34 502a5395 pbrook
typedef PCIHostState APBState;
35 502a5395 pbrook
36 502a5395 pbrook
static void pci_apb_config_writel (void *opaque, target_phys_addr_t addr,
37 502a5395 pbrook
                                         uint32_t val)
38 502a5395 pbrook
{
39 502a5395 pbrook
    APBState *s = opaque;
40 502a5395 pbrook
    int i;
41 502a5395 pbrook
42 502a5395 pbrook
    for (i = 11; i < 32; i++) {
43 502a5395 pbrook
        if ((val & (1 << i)) != 0)
44 502a5395 pbrook
            break;
45 502a5395 pbrook
    }
46 502a5395 pbrook
    s->config_reg = (1 << 16) | (val & 0x7FC) | (i << 11);
47 502a5395 pbrook
}
48 502a5395 pbrook
49 502a5395 pbrook
static uint32_t pci_apb_config_readl (void *opaque,
50 502a5395 pbrook
                                            target_phys_addr_t addr)
51 502a5395 pbrook
{
52 502a5395 pbrook
    APBState *s = opaque;
53 502a5395 pbrook
    uint32_t val;
54 502a5395 pbrook
    int devfn;
55 502a5395 pbrook
56 502a5395 pbrook
    devfn = (s->config_reg >> 8) & 0xFF;
57 502a5395 pbrook
    val = (1 << (devfn >> 3)) | ((devfn & 0x07) << 8) | (s->config_reg & 0xFC);
58 502a5395 pbrook
    return val;
59 502a5395 pbrook
}
60 502a5395 pbrook
61 502a5395 pbrook
static CPUWriteMemoryFunc *pci_apb_config_write[] = {
62 502a5395 pbrook
    &pci_apb_config_writel,
63 502a5395 pbrook
    &pci_apb_config_writel,
64 502a5395 pbrook
    &pci_apb_config_writel,
65 502a5395 pbrook
};
66 502a5395 pbrook
67 502a5395 pbrook
static CPUReadMemoryFunc *pci_apb_config_read[] = {
68 502a5395 pbrook
    &pci_apb_config_readl,
69 502a5395 pbrook
    &pci_apb_config_readl,
70 502a5395 pbrook
    &pci_apb_config_readl,
71 502a5395 pbrook
};
72 502a5395 pbrook
73 502a5395 pbrook
static void apb_config_writel (void *opaque, target_phys_addr_t addr,
74 f930d07e blueswir1
                               uint32_t val)
75 502a5395 pbrook
{
76 502a5395 pbrook
    //PCIBus *s = opaque;
77 502a5395 pbrook
78 502a5395 pbrook
    switch (addr & 0x3f) {
79 502a5395 pbrook
    case 0x00: // Control/Status
80 502a5395 pbrook
    case 0x10: // AFSR
81 502a5395 pbrook
    case 0x18: // AFAR
82 502a5395 pbrook
    case 0x20: // Diagnostic
83 502a5395 pbrook
    case 0x28: // Target address space
84 f930d07e blueswir1
        // XXX
85 502a5395 pbrook
    default:
86 f930d07e blueswir1
        break;
87 502a5395 pbrook
    }
88 502a5395 pbrook
}
89 502a5395 pbrook
90 502a5395 pbrook
static uint32_t apb_config_readl (void *opaque,
91 f930d07e blueswir1
                                  target_phys_addr_t addr)
92 502a5395 pbrook
{
93 502a5395 pbrook
    //PCIBus *s = opaque;
94 502a5395 pbrook
    uint32_t val;
95 502a5395 pbrook
96 502a5395 pbrook
    switch (addr & 0x3f) {
97 502a5395 pbrook
    case 0x00: // Control/Status
98 502a5395 pbrook
    case 0x10: // AFSR
99 502a5395 pbrook
    case 0x18: // AFAR
100 502a5395 pbrook
    case 0x20: // Diagnostic
101 502a5395 pbrook
    case 0x28: // Target address space
102 f930d07e blueswir1
        // XXX
103 502a5395 pbrook
    default:
104 f930d07e blueswir1
        val = 0;
105 f930d07e blueswir1
        break;
106 502a5395 pbrook
    }
107 502a5395 pbrook
    return val;
108 502a5395 pbrook
}
109 502a5395 pbrook
110 502a5395 pbrook
static CPUWriteMemoryFunc *apb_config_write[] = {
111 502a5395 pbrook
    &apb_config_writel,
112 502a5395 pbrook
    &apb_config_writel,
113 502a5395 pbrook
    &apb_config_writel,
114 502a5395 pbrook
};
115 502a5395 pbrook
116 502a5395 pbrook
static CPUReadMemoryFunc *apb_config_read[] = {
117 502a5395 pbrook
    &apb_config_readl,
118 502a5395 pbrook
    &apb_config_readl,
119 502a5395 pbrook
    &apb_config_readl,
120 502a5395 pbrook
};
121 502a5395 pbrook
122 502a5395 pbrook
static CPUWriteMemoryFunc *pci_apb_write[] = {
123 502a5395 pbrook
    &pci_host_data_writeb,
124 502a5395 pbrook
    &pci_host_data_writew,
125 502a5395 pbrook
    &pci_host_data_writel,
126 502a5395 pbrook
};
127 502a5395 pbrook
128 502a5395 pbrook
static CPUReadMemoryFunc *pci_apb_read[] = {
129 502a5395 pbrook
    &pci_host_data_readb,
130 502a5395 pbrook
    &pci_host_data_readw,
131 502a5395 pbrook
    &pci_host_data_readl,
132 502a5395 pbrook
};
133 502a5395 pbrook
134 502a5395 pbrook
static void pci_apb_iowriteb (void *opaque, target_phys_addr_t addr,
135 502a5395 pbrook
                                  uint32_t val)
136 502a5395 pbrook
{
137 502a5395 pbrook
    cpu_outb(NULL, addr & 0xffff, val);
138 502a5395 pbrook
}
139 502a5395 pbrook
140 502a5395 pbrook
static void pci_apb_iowritew (void *opaque, target_phys_addr_t addr,
141 502a5395 pbrook
                                  uint32_t val)
142 502a5395 pbrook
{
143 502a5395 pbrook
    cpu_outw(NULL, addr & 0xffff, val);
144 502a5395 pbrook
}
145 502a5395 pbrook
146 502a5395 pbrook
static void pci_apb_iowritel (void *opaque, target_phys_addr_t addr,
147 502a5395 pbrook
                                uint32_t val)
148 502a5395 pbrook
{
149 502a5395 pbrook
    cpu_outl(NULL, addr & 0xffff, val);
150 502a5395 pbrook
}
151 502a5395 pbrook
152 502a5395 pbrook
static uint32_t pci_apb_ioreadb (void *opaque, target_phys_addr_t addr)
153 502a5395 pbrook
{
154 502a5395 pbrook
    uint32_t val;
155 502a5395 pbrook
156 502a5395 pbrook
    val = cpu_inb(NULL, addr & 0xffff);
157 502a5395 pbrook
    return val;
158 502a5395 pbrook
}
159 502a5395 pbrook
160 502a5395 pbrook
static uint32_t pci_apb_ioreadw (void *opaque, target_phys_addr_t addr)
161 502a5395 pbrook
{
162 502a5395 pbrook
    uint32_t val;
163 502a5395 pbrook
164 502a5395 pbrook
    val = cpu_inw(NULL, addr & 0xffff);
165 502a5395 pbrook
    return val;
166 502a5395 pbrook
}
167 502a5395 pbrook
168 502a5395 pbrook
static uint32_t pci_apb_ioreadl (void *opaque, target_phys_addr_t addr)
169 502a5395 pbrook
{
170 502a5395 pbrook
    uint32_t val;
171 502a5395 pbrook
172 502a5395 pbrook
    val = cpu_inl(NULL, addr & 0xffff);
173 502a5395 pbrook
    return val;
174 502a5395 pbrook
}
175 502a5395 pbrook
176 502a5395 pbrook
static CPUWriteMemoryFunc *pci_apb_iowrite[] = {
177 502a5395 pbrook
    &pci_apb_iowriteb,
178 502a5395 pbrook
    &pci_apb_iowritew,
179 502a5395 pbrook
    &pci_apb_iowritel,
180 502a5395 pbrook
};
181 502a5395 pbrook
182 502a5395 pbrook
static CPUReadMemoryFunc *pci_apb_ioread[] = {
183 502a5395 pbrook
    &pci_apb_ioreadb,
184 502a5395 pbrook
    &pci_apb_ioreadw,
185 502a5395 pbrook
    &pci_apb_ioreadl,
186 502a5395 pbrook
};
187 502a5395 pbrook
188 80b3ada7 pbrook
/* The APB host has an IRQ line for each IRQ line of each slot.  */
189 d2b59317 pbrook
static int pci_apb_map_irq(PCIDevice *pci_dev, int irq_num)
190 502a5395 pbrook
{
191 80b3ada7 pbrook
    return ((pci_dev->devfn & 0x18) >> 1) + irq_num;
192 80b3ada7 pbrook
}
193 80b3ada7 pbrook
194 80b3ada7 pbrook
static int pci_pbm_map_irq(PCIDevice *pci_dev, int irq_num)
195 80b3ada7 pbrook
{
196 80b3ada7 pbrook
    int bus_offset;
197 80b3ada7 pbrook
    if (pci_dev->devfn & 1)
198 80b3ada7 pbrook
        bus_offset = 16;
199 80b3ada7 pbrook
    else
200 80b3ada7 pbrook
        bus_offset = 0;
201 80b3ada7 pbrook
    return bus_offset + irq_num;
202 d2b59317 pbrook
}
203 d2b59317 pbrook
204 d537cf6c pbrook
static void pci_apb_set_irq(qemu_irq *pic, int irq_num, int level)
205 d2b59317 pbrook
{
206 80b3ada7 pbrook
    /* PCI IRQ map onto the first 32 INO.  */
207 d537cf6c pbrook
    qemu_set_irq(pic[irq_num], level);
208 502a5395 pbrook
}
209 502a5395 pbrook
210 fdf41d22 blueswir1
PCIBus *pci_apb_init(target_phys_addr_t special_base,
211 fdf41d22 blueswir1
                     target_phys_addr_t mem_base,
212 d537cf6c pbrook
                     qemu_irq *pic)
213 502a5395 pbrook
{
214 502a5395 pbrook
    APBState *s;
215 502a5395 pbrook
    PCIDevice *d;
216 502a5395 pbrook
    int pci_mem_config, pci_mem_data, apb_config, pci_ioport;
217 80b3ada7 pbrook
    PCIBus *secondary;
218 502a5395 pbrook
219 502a5395 pbrook
    s = qemu_mallocz(sizeof(APBState));
220 80b3ada7 pbrook
    /* Ultrasparc PBM main bus */
221 80b3ada7 pbrook
    s->bus = pci_register_bus(pci_apb_set_irq, pci_pbm_map_irq, pic, 0, 32);
222 502a5395 pbrook
223 502a5395 pbrook
    pci_mem_config = cpu_register_io_memory(0, pci_apb_config_read,
224 502a5395 pbrook
                                            pci_apb_config_write, s);
225 502a5395 pbrook
    apb_config = cpu_register_io_memory(0, apb_config_read,
226 f930d07e blueswir1
                                        apb_config_write, s);
227 502a5395 pbrook
    pci_mem_data = cpu_register_io_memory(0, pci_apb_read,
228 502a5395 pbrook
                                          pci_apb_write, s);
229 502a5395 pbrook
    pci_ioport = cpu_register_io_memory(0, pci_apb_ioread,
230 502a5395 pbrook
                                          pci_apb_iowrite, s);
231 502a5395 pbrook
232 502a5395 pbrook
    cpu_register_physical_memory(special_base + 0x2000ULL, 0x40, apb_config);
233 502a5395 pbrook
    cpu_register_physical_memory(special_base + 0x1000000ULL, 0x10, pci_mem_config);
234 502a5395 pbrook
    cpu_register_physical_memory(special_base + 0x2000000ULL, 0x10000, pci_ioport);
235 502a5395 pbrook
    cpu_register_physical_memory(mem_base, 0x10000000, pci_mem_data); // XXX size should be 4G-prom
236 502a5395 pbrook
237 5fafdf24 ths
    d = pci_register_device(s->bus, "Advanced PCI Bus", sizeof(PCIDevice),
238 80b3ada7 pbrook
                            0, NULL, NULL);
239 502a5395 pbrook
    d->config[0x00] = 0x8e; // vendor_id : Sun
240 502a5395 pbrook
    d->config[0x01] = 0x10;
241 502a5395 pbrook
    d->config[0x02] = 0x00; // device_id
242 502a5395 pbrook
    d->config[0x03] = 0xa0;
243 502a5395 pbrook
    d->config[0x04] = 0x06; // command = bus master, pci mem
244 502a5395 pbrook
    d->config[0x05] = 0x00;
245 502a5395 pbrook
    d->config[0x06] = 0xa0; // status = fast back-to-back, 66MHz, no error
246 502a5395 pbrook
    d->config[0x07] = 0x03; // status = medium devsel
247 502a5395 pbrook
    d->config[0x08] = 0x00; // revision
248 502a5395 pbrook
    d->config[0x09] = 0x00; // programming i/f
249 502a5395 pbrook
    d->config[0x0A] = 0x00; // class_sub = pci host
250 502a5395 pbrook
    d->config[0x0B] = 0x06; // class_base = PCI_bridge
251 502a5395 pbrook
    d->config[0x0D] = 0x10; // latency_timer
252 502a5395 pbrook
    d->config[0x0E] = 0x00; // header_type
253 80b3ada7 pbrook
254 80b3ada7 pbrook
    /* APB secondary busses */
255 4258b780 pbrook
    secondary = pci_bridge_init(s->bus, 8, 0x108e5000, pci_apb_map_irq, "Advanced PCI Bus secondary bridge 1");
256 4258b780 pbrook
    pci_bridge_init(s->bus, 9, 0x108e5000, pci_apb_map_irq, "Advanced PCI Bus secondary bridge 2");
257 80b3ada7 pbrook
    return secondary;
258 502a5395 pbrook
}
259 502a5395 pbrook