fix missing type declarations (Joachim Henke)
[qemu] / hw / apb_pci.c
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