Statistics
| Branch: | Revision:

root / hw / apb_pci.c @ 0986ac3b

History | View | Annotate | Download (6.5 kB)

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
#include "vl.h"
25
typedef target_phys_addr_t pci_addr_t;
26
#include "pci_host.h"
27

    
28
typedef PCIHostState APBState;
29

    
30
static void pci_apb_config_writel (void *opaque, target_phys_addr_t addr,
31
                                         uint32_t val)
32
{
33
    APBState *s = opaque;
34
    int i;
35

    
36
    for (i = 11; i < 32; i++) {
37
        if ((val & (1 << i)) != 0)
38
            break;
39
    }
40
    s->config_reg = (1 << 16) | (val & 0x7FC) | (i << 11);
41
}
42

    
43
static uint32_t pci_apb_config_readl (void *opaque,
44
                                            target_phys_addr_t addr)
45
{
46
    APBState *s = opaque;
47
    uint32_t val;
48
    int devfn;
49

    
50
    devfn = (s->config_reg >> 8) & 0xFF;
51
    val = (1 << (devfn >> 3)) | ((devfn & 0x07) << 8) | (s->config_reg & 0xFC);
52
    return val;
53
}
54

    
55
static CPUWriteMemoryFunc *pci_apb_config_write[] = {
56
    &pci_apb_config_writel,
57
    &pci_apb_config_writel,
58
    &pci_apb_config_writel,
59
};
60

    
61
static CPUReadMemoryFunc *pci_apb_config_read[] = {
62
    &pci_apb_config_readl,
63
    &pci_apb_config_readl,
64
    &pci_apb_config_readl,
65
};
66

    
67
static void apb_config_writel (void *opaque, target_phys_addr_t addr,
68
                               uint32_t val)
69
{
70
    //PCIBus *s = opaque;
71

    
72
    switch (addr & 0x3f) {
73
    case 0x00: // Control/Status
74
    case 0x10: // AFSR
75
    case 0x18: // AFAR
76
    case 0x20: // Diagnostic
77
    case 0x28: // Target address space
78
        // XXX
79
    default:
80
        break;
81
    }
82
}
83

    
84
static uint32_t apb_config_readl (void *opaque,
85
                                  target_phys_addr_t addr)
86
{
87
    //PCIBus *s = opaque;
88
    uint32_t val;
89

    
90
    switch (addr & 0x3f) {
91
    case 0x00: // Control/Status
92
    case 0x10: // AFSR
93
    case 0x18: // AFAR
94
    case 0x20: // Diagnostic
95
    case 0x28: // Target address space
96
        // XXX
97
    default:
98
        val = 0;
99
        break;
100
    }
101
    return val;
102
}
103

    
104
static CPUWriteMemoryFunc *apb_config_write[] = {
105
    &apb_config_writel,
106
    &apb_config_writel,
107
    &apb_config_writel,
108
};
109

    
110
static CPUReadMemoryFunc *apb_config_read[] = {
111
    &apb_config_readl,
112
    &apb_config_readl,
113
    &apb_config_readl,
114
};
115

    
116
static CPUWriteMemoryFunc *pci_apb_write[] = {
117
    &pci_host_data_writeb,
118
    &pci_host_data_writew,
119
    &pci_host_data_writel,
120
};
121

    
122
static CPUReadMemoryFunc *pci_apb_read[] = {
123
    &pci_host_data_readb,
124
    &pci_host_data_readw,
125
    &pci_host_data_readl,
126
};
127

    
128
static void pci_apb_iowriteb (void *opaque, target_phys_addr_t addr,
129
                                  uint32_t val)
130
{
131
    cpu_outb(NULL, addr & 0xffff, val);
132
}
133

    
134
static void pci_apb_iowritew (void *opaque, target_phys_addr_t addr,
135
                                  uint32_t val)
136
{
137
    cpu_outw(NULL, addr & 0xffff, val);
138
}
139

    
140
static void pci_apb_iowritel (void *opaque, target_phys_addr_t addr,
141
                                uint32_t val)
142
{
143
    cpu_outl(NULL, addr & 0xffff, val);
144
}
145

    
146
static uint32_t pci_apb_ioreadb (void *opaque, target_phys_addr_t addr)
147
{
148
    uint32_t val;
149

    
150
    val = cpu_inb(NULL, addr & 0xffff);
151
    return val;
152
}
153

    
154
static uint32_t pci_apb_ioreadw (void *opaque, target_phys_addr_t addr)
155
{
156
    uint32_t val;
157

    
158
    val = cpu_inw(NULL, addr & 0xffff);
159
    return val;
160
}
161

    
162
static uint32_t pci_apb_ioreadl (void *opaque, target_phys_addr_t addr)
163
{
164
    uint32_t val;
165

    
166
    val = cpu_inl(NULL, addr & 0xffff);
167
    return val;
168
}
169

    
170
static CPUWriteMemoryFunc *pci_apb_iowrite[] = {
171
    &pci_apb_iowriteb,
172
    &pci_apb_iowritew,
173
    &pci_apb_iowritel,
174
};
175

    
176
static CPUReadMemoryFunc *pci_apb_ioread[] = {
177
    &pci_apb_ioreadb,
178
    &pci_apb_ioreadw,
179
    &pci_apb_ioreadl,
180
};
181

    
182
/* ??? This is probably wrong.  */
183
static void pci_apb_set_irq(PCIDevice *d, void *pic, int irq_num, int level)
184
{
185
    pic_set_irq_new(pic, d->config[PCI_INTERRUPT_LINE], level);
186
}
187

    
188
PCIBus *pci_apb_init(target_ulong special_base, target_ulong mem_base,
189
                     void *pic)
190
{
191
    APBState *s;
192
    PCIDevice *d;
193
    int pci_mem_config, pci_mem_data, apb_config, pci_ioport;
194

    
195
    s = qemu_mallocz(sizeof(APBState));
196
    /* Ultrasparc APB main bus */
197
    s->bus = pci_register_bus(pci_apb_set_irq, pic, 0);
198

    
199
    pci_mem_config = cpu_register_io_memory(0, pci_apb_config_read,
200
                                            pci_apb_config_write, s);
201
    apb_config = cpu_register_io_memory(0, apb_config_read,
202
                                        apb_config_write, s);
203
    pci_mem_data = cpu_register_io_memory(0, pci_apb_read,
204
                                          pci_apb_write, s);
205
    pci_ioport = cpu_register_io_memory(0, pci_apb_ioread,
206
                                          pci_apb_iowrite, s);
207

    
208
    cpu_register_physical_memory(special_base + 0x2000ULL, 0x40, apb_config);
209
    cpu_register_physical_memory(special_base + 0x1000000ULL, 0x10, pci_mem_config);
210
    cpu_register_physical_memory(special_base + 0x2000000ULL, 0x10000, pci_ioport);
211
    cpu_register_physical_memory(mem_base, 0x10000000, pci_mem_data); // XXX size should be 4G-prom
212

    
213
    d = pci_register_device(s->bus, "Advanced PCI Bus", sizeof(PCIDevice), 
214
                            -1, NULL, NULL);
215
    d->config[0x00] = 0x8e; // vendor_id : Sun
216
    d->config[0x01] = 0x10;
217
    d->config[0x02] = 0x00; // device_id
218
    d->config[0x03] = 0xa0;
219
    d->config[0x04] = 0x06; // command = bus master, pci mem
220
    d->config[0x05] = 0x00;
221
    d->config[0x06] = 0xa0; // status = fast back-to-back, 66MHz, no error
222
    d->config[0x07] = 0x03; // status = medium devsel
223
    d->config[0x08] = 0x00; // revision
224
    d->config[0x09] = 0x00; // programming i/f
225
    d->config[0x0A] = 0x00; // class_sub = pci host
226
    d->config[0x0B] = 0x06; // class_base = PCI_bridge
227
    d->config[0x0D] = 0x10; // latency_timer
228
    d->config[0x0E] = 0x00; // header_type
229
    return s->bus;
230
}
231

    
232