/[gxemul]/trunk/src/devices/dev_mpc10x.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Annotation of /trunk/src/devices/dev_mpc10x.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 58 - (hide annotations)
Thu Oct 11 20:56:28 2007 UTC (16 years, 7 months ago) by dpavlin
File MIME type: text/plain
File size: 10191 byte(s)
more cleanup still doesn't work...
1 dpavlin 20 /*
2 dpavlin 34 * Copyright (C) 2005-2007 Anders Gavare. All rights reserved.
3 dpavlin 20 *
4     * Redistribution and use in source and binary forms, with or without
5     * modification, are permitted provided that the following conditions are met:
6     *
7     * 1. Redistributions of source code must retain the above copyright
8     * notice, this list of conditions and the following disclaimer.
9     * 2. Redistributions in binary form must reproduce the above copyright
10     * notice, this list of conditions and the following disclaimer in the
11     * documentation and/or other materials provided with the distribution.
12     * 3. The name of the author may not be used to endorse or promote products
13     * derived from this software without specific prior written permission.
14     *
15     * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16     * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17     * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18     * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19     * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20     * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21     * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24     * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25     * SUCH DAMAGE.
26     *
27     *
28 dpavlin 53 * $Id: dev_mpc10x.c,v 1.12 2007/06/15 18:13:04 debug Exp $
29 dpavlin 42 *
30 dpavlin 53 * COMMENT: IBM mpc10x bridge (PCI and interrupt controller)
31 dpavlin 20 */
32    
33     #include <stdio.h>
34     #include <stdlib.h>
35     #include <string.h>
36    
37     #include "bus_pci.h"
38     #include "cpu.h"
39     #include "device.h"
40 dpavlin 42 #include "interrupt.h"
41 dpavlin 20 #include "machine.h"
42     #include "memory.h"
43     #include "misc.h"
44    
45 dpavlin 53 #include "mpc10xreg.h"
46 dpavlin 20
47    
48 dpavlin 53 struct mpc10x_data {
49 dpavlin 34 struct interrupt ppc_irq; /* Connected to the CPU */
50    
51     uint32_t sr; /* Interrupt Status register */
52     uint32_t er; /* Interrupt Enable register */
53    
54     struct pci_data *pci_data; /* PCI bus */
55     };
56    
57    
58 dpavlin 53 void mpc10x_interrupt_assert(struct interrupt *interrupt)
59 dpavlin 34 {
60 dpavlin 53 struct mpc10x_data *d = interrupt->extra;
61 dpavlin 42 d->sr |= interrupt->line;
62 dpavlin 34 if (d->sr & d->er)
63     INTERRUPT_ASSERT(d->ppc_irq);
64     }
65 dpavlin 53 void mpc10x_interrupt_deassert(struct interrupt *interrupt)
66 dpavlin 34 {
67 dpavlin 53 struct mpc10x_data *d = interrupt->extra;
68 dpavlin 42 d->sr &= ~interrupt->line;
69 dpavlin 34 if (!(d->sr & d->er))
70     INTERRUPT_DEASSERT(d->ppc_irq);
71     }
72    
73    
74 dpavlin 20 /*
75 dpavlin 53 * dev_mpc10x_pci_access():
76 dpavlin 20 *
77 dpavlin 22 * Passes PCI indirect addr and data accesses onto bus_pci.
78 dpavlin 20 */
79 dpavlin 53 DEVICE_ACCESS(mpc10x_pci)
80 dpavlin 20 {
81     uint64_t idata = 0, odata = 0;
82 dpavlin 22 int bus, dev, func, reg;
83 dpavlin 53 struct mpc10x_data *d = extra;
84 dpavlin 20
85 dpavlin 57 if (writeflag == MEM_WRITE) {
86 dpavlin 22 idata = memory_readmax64(cpu, data, len|MEM_PCI_LITTLE_ENDIAN);
87 dpavlin 57 debug("mpc10x_pci WRITE offset 0x%x: 0x%x\n", relative_addr, odata);
88     }
89 dpavlin 20
90 dpavlin 57 debug("relative: %d i: 0x%x o: 0x%x data: %s len: %d\n", relative_addr,idata, odata, data, len );
91    
92 dpavlin 22 switch (relative_addr) {
93     case 0: /* Address: */
94     bus_pci_decompose_1(idata, &bus, &dev, &func, &reg);
95     bus_pci_setaddr(cpu, d->pci_data, bus, dev, func, reg);
96     break;
97 dpavlin 20
98 dpavlin 22 case 4: /* Data: */
99     bus_pci_data_access(cpu, d->pci_data, writeflag == MEM_READ?
100     &odata : &idata, len, writeflag);
101     break;
102     }
103 dpavlin 20
104 dpavlin 57 #define PCI_VENDOR_ID_MOTOROLA 0x1057
105     #define MPC10X_BRIDGE_106 ((PCI_DEVICE_ID_MOTOROLA_MPC106 << 16) | \
106     PCI_VENDOR_ID_MOTOROLA)
107     #define MPC10X_BRIDGE_8240 ((0x0003 << 16) | PCI_VENDOR_ID_MOTOROLA)
108     #define MPC10X_BRIDGE_107 ((0x0004 << 16) | PCI_VENDOR_ID_MOTOROLA)
109     #define MPC10X_BRIDGE_8245 ((0x0006 << 16) | PCI_VENDOR_ID_MOTOROLA)
110    
111     debug("i: 0x%x o: 0x%x\n", idata, odata );
112     if (writeflag == MEM_READ) {
113 dpavlin 22 memory_writemax64(cpu, data, len|MEM_PCI_LITTLE_ENDIAN, odata);
114 dpavlin 57 odata = MPC10X_BRIDGE_8245;
115     debug("mpc10x_pci READ offset 0x%x: 0x%x\n", relative_addr, odata);
116     }
117 dpavlin 20
118     return 1;
119     }
120    
121    
122     /*
123 dpavlin 53 * dev_mpc10x_int_access():
124 dpavlin 20 *
125     * The interrupt controller.
126     */
127 dpavlin 53 DEVICE_ACCESS(mpc10x_int)
128 dpavlin 20 {
129 dpavlin 53 struct mpc10x_data *d = extra;
130 dpavlin 20 uint64_t idata = 0, odata = 0;
131    
132     if (writeflag == MEM_WRITE)
133     idata = memory_readmax64(cpu, data, len);
134    
135     switch (relative_addr) {
136    
137 dpavlin 49 case MPC_UIC_SR:
138 dpavlin 20 /* Status register (cleared by writing ones): */
139 dpavlin 34 if (writeflag == MEM_READ) {
140 dpavlin 20 odata = d->sr;
141 dpavlin 34 } else {
142 dpavlin 20 d->sr &= ~idata;
143 dpavlin 34 if (!(d->sr & d->er))
144     INTERRUPT_DEASSERT(d->ppc_irq);
145     }
146 dpavlin 20 break;
147    
148 dpavlin 49 case MPC_UIC_SRS:
149 dpavlin 20 /* Status register set: */
150     if (writeflag == MEM_READ) {
151 dpavlin 53 fatal("[ mpc10x_int: read from MPC_UIC_SRS? ]\n");
152 dpavlin 20 odata = d->sr;
153 dpavlin 34 } else {
154 dpavlin 20 d->sr = idata;
155 dpavlin 34 if (d->sr & d->er)
156     INTERRUPT_ASSERT(d->ppc_irq);
157     else
158     INTERRUPT_DEASSERT(d->ppc_irq);
159     }
160 dpavlin 20 break;
161    
162 dpavlin 49 case MPC_UIC_ER:
163 dpavlin 20 /* Enable register: */
164 dpavlin 34 if (writeflag == MEM_READ) {
165 dpavlin 20 odata = d->er;
166 dpavlin 34 } else {
167 dpavlin 20 d->er = idata;
168 dpavlin 34 if (d->sr & d->er)
169     INTERRUPT_ASSERT(d->ppc_irq);
170     else
171     INTERRUPT_DEASSERT(d->ppc_irq);
172     }
173 dpavlin 20 break;
174    
175 dpavlin 49 case MPC_UIC_MSR:
176 dpavlin 20 /* Masked status: */
177 dpavlin 34 if (writeflag == MEM_READ) {
178 dpavlin 20 odata = d->sr & d->er;
179 dpavlin 34 } else {
180 dpavlin 53 fatal("[ mpc10x_int: write to MPC_UIC_MSR? ]\n");
181 dpavlin 34 }
182 dpavlin 20 break;
183    
184     default:if (writeflag == MEM_WRITE) {
185 dpavlin 53 fatal("[ mpc10x_int: unimplemented write to "
186 dpavlin 20 "offset 0x%x: data=0x%x ]\n", (int)
187     relative_addr, (int)idata);
188     } else {
189 dpavlin 53 fatal("[ mpc10x_int: unimplemented read from "
190 dpavlin 20 "offset 0x%x ]\n", (int)relative_addr);
191     }
192     }
193    
194     if (writeflag == MEM_READ)
195     memory_writemax64(cpu, data, len, odata);
196    
197     return 1;
198     }
199    
200 dpavlin 57 /*
201     * dev_mpc10x_config_access():
202     *
203     * Configuration
204     */
205 dpavlin 58
206 dpavlin 57 DEVICE_ACCESS(mpc10x_config)
207     {
208     uint64_t idata = 0, odata = 0;
209 dpavlin 20
210 dpavlin 58 debug("mpc10x_config relative: %d i: 0x%x o: 0x%x data: %s len: %d write: %d\n", relative_addr,idata, odata, data, len, writeflag );
211 dpavlin 57 if (writeflag == MEM_WRITE) {
212     idata = memory_readmax64(cpu, data, len);
213 dpavlin 58 debug("[ mpc10x_config WRITE offset 0x%x: 0x%x odata: 0x%x data: 0x%x len: %d ]\n", relative_addr, idata, odata, data, len);
214     } else {
215     fatal("[ mpc10x_config: read! ]\n");
216 dpavlin 57 }
217    
218 dpavlin 58 return 1;
219     }
220 dpavlin 57
221     #define PCI_VENDOR_ID_MOTOROLA 0x1057
222     #define MPC10X_BRIDGE_106 ((PCI_DEVICE_ID_MOTOROLA_MPC106 << 16) | \
223     PCI_VENDOR_ID_MOTOROLA)
224     #define MPC10X_BRIDGE_8240 ((0x0003 << 16) | PCI_VENDOR_ID_MOTOROLA)
225     #define MPC10X_BRIDGE_107 ((0x0004 << 16) | PCI_VENDOR_ID_MOTOROLA)
226     #define MPC10X_BRIDGE_8245 ((0x0006 << 16) | PCI_VENDOR_ID_MOTOROLA)
227    
228 dpavlin 58 DEVICE_ACCESS(mpc10x_data)
229     {
230     uint64_t idata = 0, odata = 0;
231 dpavlin 57
232 dpavlin 58 debug("mpc10x_data: relative: %d i: 0x%x o: 0x%x data: %s len: %d write: %d\n", relative_addr,idata, odata, data, len, writeflag );
233     if (writeflag == MEM_WRITE) {
234     idata = memory_readmax64(cpu, data, len);
235     fatal("[ mpc10x_data: write -> %x ]\n", idata);
236     } else {
237 dpavlin 57 odata = MPC10X_BRIDGE_8245;
238 dpavlin 58 debug("[ mpc10x_data: READ offset 0x%x: 0x%x odata: 0x%x data: 0x%x len: %d ]\n", relative_addr, idata, odata, data, len);
239 dpavlin 57 memory_writemax64(cpu, data, len, odata);
240     }
241    
242     return 1;
243     }
244    
245 dpavlin 58
246 dpavlin 53 DEVINIT(mpc10x)
247 dpavlin 20 {
248 dpavlin 53 struct mpc10x_data *d;
249 dpavlin 20 char tmp[300];
250 dpavlin 34 int i;
251 dpavlin 20
252 dpavlin 53 CHECK_ALLOCATION(d = malloc(sizeof(struct mpc10x_data)));
253     memset(d, 0, sizeof(struct mpc10x_data));
254 dpavlin 20
255 dpavlin 34 /* Connect to the CPU's interrupt pin: */
256     INTERRUPT_CONNECT(devinit->interrupt_path, d->ppc_irq);
257    
258 dpavlin 53 /* Register 32 mpc10x interrupts: */
259 dpavlin 34 for (i=0; i<32; i++) {
260     struct interrupt template;
261     char n[300];
262 dpavlin 53 snprintf(n, sizeof(n), "%s.mpc10x.%i",
263 dpavlin 34 devinit->interrupt_path, i);
264     memset(&template, 0, sizeof(template));
265 dpavlin 42 template.line = 1 << i;
266 dpavlin 34 template.name = n;
267     template.extra = d;
268 dpavlin 53 template.interrupt_assert = mpc10x_interrupt_assert;
269     template.interrupt_deassert = mpc10x_interrupt_deassert;
270 dpavlin 34 interrupt_handler_register(&template);
271     }
272    
273 dpavlin 58 #define MPC10X_MAPB_CNFG_ADDR 0xfec00000
274     #define MPC10X_MAPB_CNFG_DATA 0xfee00000
275    
276     #define MPC10X_MAPB_ISA_IO_BASE 0xfe000000
277     #define MPC10X_MAPB_ISA_MEM_BASE 0x80000000
278     #define MPC10X_MAPB_DRAM_OFFSET 0x00000000
279    
280     #define MPC10X_MAPB_PCI_IO_START 0x00000000
281     #define MPC10X_MAPB_PCI_IO_END (0x00c00000 - 1)
282     #define MPC10X_MAPB_PCI_MEM_START 0x80000000
283     #define MPC10X_MAPB_PCI_MEM_END (0xc0000000 - 1)
284    
285     #define MPC10X_MAPB_PCI_MEM_OFFSET (MPC10X_MAPB_ISA_MEM_BASE - \
286     MPC10X_MAPB_PCI_MEM_START)
287    
288    
289    
290 dpavlin 20 /* Register a PCI bus: */
291 dpavlin 53 snprintf(tmp, sizeof(tmp), "%s.mpc10x", devinit->interrupt_path);
292 dpavlin 20 d->pci_data = bus_pci_init(
293 dpavlin 34 devinit->machine,
294     tmp, /* pciirq path */
295 dpavlin 58 0x00000000, /* pci device io offset */
296     0x00000000, /* pci device mem offset */
297     0xfe000000, /* PCI portbase */
298 dpavlin 57 0x80000000, /* PCI membase: TODO */
299 dpavlin 34 tmp, /* PCI irqbase */
300 dpavlin 58 0xfe000000, /* ISA portbase: TODO */
301     0x80000000, /* ISA membase: TODO */
302 dpavlin 34 tmp); /* ISA irqbase */
303 dpavlin 20
304 dpavlin 57 /* PCI host bridge */
305     bus_pci_add(devinit->machine, d->pci_data,
306     devinit->machine->memory, 0, 0, 0, "mpc10x_host_bridge");
307 dpavlin 34
308 dpavlin 57 /* MPC10x configuration */
309     memory_device_register(devinit->machine->memory, "mpc10x_config",
310 dpavlin 58 0xfec00000, 1, dev_mpc10x_config_access, d, DM_DEFAULT, NULL);
311     memory_device_register(devinit->machine->memory, "mpc10x_data",
312     0xfee00000, 8, dev_mpc10x_data_access, d, DM_DEFAULT, NULL);
313 dpavlin 34
314 dpavlin 58 #if 0
315 dpavlin 20 /* PCI configuration registers: */
316 dpavlin 53 memory_device_register(devinit->machine->memory, "mpc10x_pci",
317 dpavlin 57 0xfee00000, 8, dev_mpc10x_pci_access, d, DM_DEFAULT, NULL);
318 dpavlin 20
319     /* Interrupt controller: */
320 dpavlin 53 memory_device_register(devinit->machine->memory, "mpc10x_int",
321     MPC_UIC_BASE, MPC_UIC_SIZE, dev_mpc10x_int_access, d,
322 dpavlin 34 DM_DEFAULT, NULL);
323 dpavlin 58 #endif
324 dpavlin 20
325     /* Two serial ports: */
326 dpavlin 53 snprintf(tmp, sizeof(tmp), "ns16550 irq=%s.mpc10x.%i addr=0x%llx "
327 dpavlin 49 "name2=tty0", devinit->interrupt_path, 31 - MPC_IB_UART_0,
328     (long long)MPC_COM0);
329 dpavlin 34 devinit->machine->main_console_handle = (size_t)
330     device_add(devinit->machine, tmp);
331 dpavlin 49 #if 0
332 dpavlin 53 snprintf(tmp, sizeof(tmp), "ns16550 irq=%s.mpc10x.%i addr=0x%llx "
333 dpavlin 49 "name2=tty1", devinit->interrupt_path, 31 - MPC_IB_UART_1,
334     (long long)MPC_COM1);
335     device_add(devinit->machine, tmp);
336     #endif
337 dpavlin 20
338 dpavlin 34 devinit->return_ptr = d->pci_data;
339    
340     return 1;
341 dpavlin 20 }
342    

  ViewVC Help
Powered by ViewVC 1.1.26