Statistics
| Branch: | Revision:

root / hw / apb_pci.c @ a01d8cad

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