/[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 57 - (hide annotations)
Thu Oct 11 18:57:32 2007 UTC (16 years, 7 months ago) by dpavlin
File MIME type: text/plain
File size: 9082 byte(s)
more cleanups, debugging and first try to implement mpc401 config register
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     DEVICE_ACCESS(mpc10x_config)
206     {
207     uint64_t idata = 0, odata = 0;
208     // struct mpc10x_data *d = extra;
209 dpavlin 20
210 dpavlin 57 if (writeflag == MEM_WRITE) {
211     idata = memory_readmax64(cpu, data, len);
212     debug("mpc10x_config WRITE offset 0x%x: 0x%x [old: 0x%x]\n", relative_addr, odata, idata);
213     }
214    
215     debug("relative: %d i: 0x%x o: 0x%x data: %s len: %d\n", relative_addr,idata, odata, data, len );
216    
217     switch (relative_addr) {
218     case 0:
219    
220     #define PCI_VENDOR_ID_MOTOROLA 0x1057
221     #define MPC10X_BRIDGE_106 ((PCI_DEVICE_ID_MOTOROLA_MPC106 << 16) | \
222     PCI_VENDOR_ID_MOTOROLA)
223     #define MPC10X_BRIDGE_8240 ((0x0003 << 16) | PCI_VENDOR_ID_MOTOROLA)
224     #define MPC10X_BRIDGE_107 ((0x0004 << 16) | PCI_VENDOR_ID_MOTOROLA)
225     #define MPC10X_BRIDGE_8245 ((0x0006 << 16) | PCI_VENDOR_ID_MOTOROLA)
226    
227     return MPC10X_BRIDGE_8245;
228     }
229    
230     debug("i: 0x%x o: 0x%x\n", idata, odata );
231     if (writeflag == MEM_READ) {
232     odata = MPC10X_BRIDGE_8245;
233     memory_writemax64(cpu, data, len, odata);
234     debug("mpc10x_config READ offset 0x%x: 0x%x\n", relative_addr, odata);
235     }
236    
237     return 1;
238     }
239    
240 dpavlin 53 DEVINIT(mpc10x)
241 dpavlin 20 {
242 dpavlin 53 struct mpc10x_data *d;
243 dpavlin 20 char tmp[300];
244 dpavlin 34 int i;
245 dpavlin 20
246 dpavlin 53 CHECK_ALLOCATION(d = malloc(sizeof(struct mpc10x_data)));
247     memset(d, 0, sizeof(struct mpc10x_data));
248 dpavlin 20
249 dpavlin 34 /* Connect to the CPU's interrupt pin: */
250     INTERRUPT_CONNECT(devinit->interrupt_path, d->ppc_irq);
251    
252 dpavlin 53 /* Register 32 mpc10x interrupts: */
253 dpavlin 34 for (i=0; i<32; i++) {
254     struct interrupt template;
255     char n[300];
256 dpavlin 53 snprintf(n, sizeof(n), "%s.mpc10x.%i",
257 dpavlin 34 devinit->interrupt_path, i);
258     memset(&template, 0, sizeof(template));
259 dpavlin 42 template.line = 1 << i;
260 dpavlin 34 template.name = n;
261     template.extra = d;
262 dpavlin 53 template.interrupt_assert = mpc10x_interrupt_assert;
263     template.interrupt_deassert = mpc10x_interrupt_deassert;
264 dpavlin 34 interrupt_handler_register(&template);
265     }
266    
267 dpavlin 20 /* Register a PCI bus: */
268 dpavlin 53 snprintf(tmp, sizeof(tmp), "%s.mpc10x", devinit->interrupt_path);
269 dpavlin 20 d->pci_data = bus_pci_init(
270 dpavlin 34 devinit->machine,
271     tmp, /* pciirq path */
272 dpavlin 57 0xfc000000, /* pci device io offset */
273     0xfcc00000, /* pci device mem offset */
274     0xfec00000, /* PCI portbase */
275     0x80000000, /* PCI membase: TODO */
276 dpavlin 34 tmp, /* PCI irqbase */
277 dpavlin 20 0, /* ISA portbase: TODO */
278     0, /* ISA membase: TODO */
279 dpavlin 34 tmp); /* ISA irqbase */
280 dpavlin 20
281 dpavlin 57 /* PCI host bridge */
282     bus_pci_add(devinit->machine, d->pci_data,
283     devinit->machine->memory, 0, 0, 0, "mpc10x_host_bridge");
284 dpavlin 34
285 dpavlin 57 /* MPC10x configuration */
286     memory_device_register(devinit->machine->memory, "mpc10x_config",
287     0xfec00000, 8, dev_mpc10x_config_access, d, DM_DEFAULT, NULL);
288 dpavlin 34
289 dpavlin 20 /* PCI configuration registers: */
290 dpavlin 53 memory_device_register(devinit->machine->memory, "mpc10x_pci",
291 dpavlin 57 0xfee00000, 8, dev_mpc10x_pci_access, d, DM_DEFAULT, NULL);
292 dpavlin 20
293     /* Interrupt controller: */
294 dpavlin 53 memory_device_register(devinit->machine->memory, "mpc10x_int",
295     MPC_UIC_BASE, MPC_UIC_SIZE, dev_mpc10x_int_access, d,
296 dpavlin 34 DM_DEFAULT, NULL);
297 dpavlin 20
298     /* Two serial ports: */
299 dpavlin 53 snprintf(tmp, sizeof(tmp), "ns16550 irq=%s.mpc10x.%i addr=0x%llx "
300 dpavlin 49 "name2=tty0", devinit->interrupt_path, 31 - MPC_IB_UART_0,
301     (long long)MPC_COM0);
302 dpavlin 34 devinit->machine->main_console_handle = (size_t)
303     device_add(devinit->machine, tmp);
304 dpavlin 49 #if 0
305 dpavlin 53 snprintf(tmp, sizeof(tmp), "ns16550 irq=%s.mpc10x.%i addr=0x%llx "
306 dpavlin 49 "name2=tty1", devinit->interrupt_path, 31 - MPC_IB_UART_1,
307     (long long)MPC_COM1);
308     device_add(devinit->machine, tmp);
309     #endif
310 dpavlin 20
311 dpavlin 34 devinit->return_ptr = d->pci_data;
312    
313     return 1;
314 dpavlin 20 }
315    

  ViewVC Help
Powered by ViewVC 1.1.26