unin_pci.c 8.9 KB
Newer Older
P
pbrook 已提交
1 2 3 4
/*
 * QEMU Uninorth PCI host (for all Mac99 and newer machines)
 *
 * Copyright (c) 2006 Fabrice Bellard
5
 *
P
pbrook 已提交
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
P
pbrook 已提交
24 25 26 27
#include "hw.h"
#include "ppc_mac.h"
#include "pci.h"

28 29 30 31 32 33 34 35 36 37
/* debug UniNorth */
//#define DEBUG_UNIN

#ifdef DEBUG_UNIN
#define UNIN_DPRINTF(fmt, args...) \
do { printf("UNIN: " fmt , ##args); } while (0)
#else
#define UNIN_DPRINTF(fmt, args...)
#endif

P
pbrook 已提交
38 39 40 41 42 43 44 45 46 47
typedef target_phys_addr_t pci_addr_t;
#include "pci_host.h"

typedef PCIHostState UNINState;

static void pci_unin_main_config_writel (void *opaque, target_phys_addr_t addr,
                                         uint32_t val)
{
    UNINState *s = opaque;

48
    UNIN_DPRINTF("config_writel addr " TARGET_FMT_plx " val %x\n", addr, val);
P
pbrook 已提交
49 50 51 52
#ifdef TARGET_WORDS_BIGENDIAN
    val = bswap32(val);
#endif

B
blueswir1 已提交
53
    s->config_reg = val;
P
pbrook 已提交
54 55 56 57 58 59 60 61
}

static uint32_t pci_unin_main_config_readl (void *opaque,
                                            target_phys_addr_t addr)
{
    UNINState *s = opaque;
    uint32_t val;

B
blueswir1 已提交
62
    val = s->config_reg;
P
pbrook 已提交
63 64 65
#ifdef TARGET_WORDS_BIGENDIAN
    val = bswap32(val);
#endif
66
    UNIN_DPRINTF("config_readl addr " TARGET_FMT_plx " val %x\n", addr, val);
P
pbrook 已提交
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99

    return val;
}

static CPUWriteMemoryFunc *pci_unin_main_config_write[] = {
    &pci_unin_main_config_writel,
    &pci_unin_main_config_writel,
    &pci_unin_main_config_writel,
};

static CPUReadMemoryFunc *pci_unin_main_config_read[] = {
    &pci_unin_main_config_readl,
    &pci_unin_main_config_readl,
    &pci_unin_main_config_readl,
};

static CPUWriteMemoryFunc *pci_unin_main_write[] = {
    &pci_host_data_writeb,
    &pci_host_data_writew,
    &pci_host_data_writel,
};

static CPUReadMemoryFunc *pci_unin_main_read[] = {
    &pci_host_data_readb,
    &pci_host_data_readw,
    &pci_host_data_readl,
};

static void pci_unin_config_writel (void *opaque, target_phys_addr_t addr,
                                    uint32_t val)
{
    UNINState *s = opaque;

B
blueswir1 已提交
100
    s->config_reg = val;
P
pbrook 已提交
101 102 103 104 105 106 107
}

static uint32_t pci_unin_config_readl (void *opaque,
                                       target_phys_addr_t addr)
{
    UNINState *s = opaque;

B
blueswir1 已提交
108
    return s->config_reg;
P
pbrook 已提交
109 110 111 112 113 114 115 116 117 118 119 120 121 122
}

static CPUWriteMemoryFunc *pci_unin_config_write[] = {
    &pci_unin_config_writel,
    &pci_unin_config_writel,
    &pci_unin_config_writel,
};

static CPUReadMemoryFunc *pci_unin_config_read[] = {
    &pci_unin_config_readl,
    &pci_unin_config_readl,
    &pci_unin_config_readl,
};

B
blueswir1 已提交
123
#if 0
P
pbrook 已提交
124 125 126 127 128 129 130 131 132 133 134 135 136
static CPUWriteMemoryFunc *pci_unin_write[] = {
    &pci_host_pci_writeb,
    &pci_host_pci_writew,
    &pci_host_pci_writel,
};

static CPUReadMemoryFunc *pci_unin_read[] = {
    &pci_host_pci_readb,
    &pci_host_pci_readw,
    &pci_host_pci_readl,
};
#endif

137 138
/* Don't know if this matches real hardware, but it agrees with OHW.  */
static int pci_unin_map_irq(PCIDevice *pci_dev, int irq_num)
P
pbrook 已提交
139
{
140 141 142
    return (irq_num + (pci_dev->devfn >> 3)) & 3;
}

P
pbrook 已提交
143
static void pci_unin_set_irq(qemu_irq *pic, int irq_num, int level)
144
{
P
pbrook 已提交
145
    qemu_set_irq(pic[irq_num + 8], level);
P
pbrook 已提交
146 147
}

148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
static void pci_unin_save(QEMUFile* f, void *opaque)
{
    PCIDevice *d = opaque;

    pci_device_save(d, f);
}

static int pci_unin_load(QEMUFile* f, void *opaque, int version_id)
{
    PCIDevice *d = opaque;

    if (version_id != 1)
        return -EINVAL;

    return pci_device_load(d, f);
}

static void pci_unin_reset(void *opaque)
{
}

P
pbrook 已提交
169
PCIBus *pci_pmac_init(qemu_irq *pic)
P
pbrook 已提交
170 171 172 173 174 175 176 177
{
    UNINState *s;
    PCIDevice *d;
    int pci_mem_config, pci_mem_data;

    /* Use values found on a real PowerMac */
    /* Uninorth main bus */
    s = qemu_mallocz(sizeof(UNINState));
178
    s->bus = pci_register_bus(pci_unin_set_irq, pci_unin_map_irq,
P
pbrook 已提交
179
                              pic, 11 << 3, 4);
P
pbrook 已提交
180

181
    pci_mem_config = cpu_register_io_memory(0, pci_unin_main_config_read,
P
pbrook 已提交
182 183 184 185 186
                                            pci_unin_main_config_write, s);
    pci_mem_data = cpu_register_io_memory(0, pci_unin_main_read,
                                          pci_unin_main_write, s);
    cpu_register_physical_memory(0xf2800000, 0x1000, pci_mem_config);
    cpu_register_physical_memory(0xf2c00000, 0x1000, pci_mem_data);
187
    d = pci_register_device(s->bus, "Uni-north main", sizeof(PCIDevice),
P
pbrook 已提交
188
                            11 << 3, NULL, NULL);
189
    pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_APPLE);
190
    pci_config_set_device_id(d->config, PCI_DEVICE_ID_APPLE_UNI_N_PCI);
P
pbrook 已提交
191
    d->config[0x08] = 0x00; // revision
192
    pci_config_set_class(d->config, PCI_CLASS_BRIDGE_HOST);
P
pbrook 已提交
193 194 195 196 197
    d->config[0x0C] = 0x08; // cache_line_size
    d->config[0x0D] = 0x10; // latency_timer
    d->config[0x0E] = 0x00; // header_type
    d->config[0x34] = 0x00; // capabilities_pointer

T
ths 已提交
198
#if 0 // XXX: not activated as PPC BIOS doesn't handle multiple buses properly
P
pbrook 已提交
199 200 201
    /* pci-to-pci bridge */
    d = pci_register_device("Uni-north bridge", sizeof(PCIDevice), 0, 13 << 3,
                            NULL, NULL);
202 203
    pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_DEC);
    pci_config_set_device_id(d->config, PCI_DEVICE_ID_DEC_21154);
P
pbrook 已提交
204
    d->config[0x08] = 0x05; // revision
205
    pci_config_set_class(d->config, PCI_CLASS_BRIDGE_PCI);
P
pbrook 已提交
206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225
    d->config[0x0C] = 0x08; // cache_line_size
    d->config[0x0D] = 0x20; // latency_timer
    d->config[0x0E] = 0x01; // header_type

    d->config[0x18] = 0x01; // primary_bus
    d->config[0x19] = 0x02; // secondary_bus
    d->config[0x1A] = 0x02; // subordinate_bus
    d->config[0x1B] = 0x20; // secondary_latency_timer
    d->config[0x1C] = 0x11; // io_base
    d->config[0x1D] = 0x01; // io_limit
    d->config[0x20] = 0x00; // memory_base
    d->config[0x21] = 0x80;
    d->config[0x22] = 0x00; // memory_limit
    d->config[0x23] = 0x80;
    d->config[0x24] = 0x01; // prefetchable_memory_base
    d->config[0x25] = 0x80;
    d->config[0x26] = 0xF1; // prefectchable_memory_limit
    d->config[0x27] = 0x7F;
    // d->config[0x34] = 0xdc // capabilities_pointer
#endif
B
blueswir1 已提交
226

P
pbrook 已提交
227
    /* Uninorth AGP bus */
228
    pci_mem_config = cpu_register_io_memory(0, pci_unin_config_read,
P
pbrook 已提交
229
                                            pci_unin_config_write, s);
B
blueswir1 已提交
230 231
    pci_mem_data = cpu_register_io_memory(0, pci_unin_main_read,
                                          pci_unin_main_write, s);
P
pbrook 已提交
232 233 234
    cpu_register_physical_memory(0xf0800000, 0x1000, pci_mem_config);
    cpu_register_physical_memory(0xf0c00000, 0x1000, pci_mem_data);

B
blueswir1 已提交
235 236
    d = pci_register_device(s->bus, "Uni-north AGP", sizeof(PCIDevice),
                            11 << 3, NULL, NULL);
237 238
    pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_APPLE);
    pci_config_set_device_id(d->config, PCI_DEVICE_ID_APPLE_UNI_N_AGP);
P
pbrook 已提交
239
    d->config[0x08] = 0x00; // revision
240
    pci_config_set_class(d->config, PCI_CLASS_BRIDGE_HOST);
P
pbrook 已提交
241 242 243 244 245 246 247 248
    d->config[0x0C] = 0x08; // cache_line_size
    d->config[0x0D] = 0x10; // latency_timer
    d->config[0x0E] = 0x00; // header_type
    //    d->config[0x34] = 0x80; // capabilities_pointer

#if 0 // XXX: not needed for now
    /* Uninorth internal bus */
    s = &pci_bridge[2];
249
    pci_mem_config = cpu_register_io_memory(0, pci_unin_config_read,
P
pbrook 已提交
250 251 252 253 254 255 256 257
                                            pci_unin_config_write, s);
    pci_mem_data = cpu_register_io_memory(0, pci_unin_read,
                                          pci_unin_write, s);
    cpu_register_physical_memory(0xf4800000, 0x1000, pci_mem_config);
    cpu_register_physical_memory(0xf4c00000, 0x1000, pci_mem_data);

    d = pci_register_device("Uni-north internal", sizeof(PCIDevice),
                            3, 11 << 3, NULL, NULL);
258
    pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_APPLE);
259
    pci_config_set_device_id(d->config, PCI_DEVICE_ID_APPLE_UNI_N_I_PCI);
P
pbrook 已提交
260
    d->config[0x08] = 0x00; // revision
261
    pci_config_set_class(d->config, PCI_CLASS_BRIDGE_HOST);
P
pbrook 已提交
262 263 264 265 266
    d->config[0x0C] = 0x08; // cache_line_size
    d->config[0x0D] = 0x10; // latency_timer
    d->config[0x0E] = 0x00; // header_type
    d->config[0x34] = 0x00; // capabilities_pointer
#endif
267 268 269 270
    register_savevm("uninorth", 0, 1, pci_unin_save, pci_unin_load, d);
    qemu_register_reset(pci_unin_reset, d);
    pci_unin_reset(d);

P
pbrook 已提交
271 272
    return s->bus;
}