/[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 60 - (hide annotations)
Fri Oct 12 19:40:03 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 10356 byte(s)
undertand that I *really* have to use len|MEM_PCI_LITTLE_ENDIAN when dealing
with PCI data
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 60 debug("mpc10x_config relative: %d i: 0x%x o: 0x%x data: %x len: %x write: %x w: %x r: %x\n", relative_addr,idata, odata, data, len, writeflag, MEM_WRITE, MEM_READ );
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 dpavlin 60 }
215     if (writeflag == MEM_READ) {
216 dpavlin 58 fatal("[ mpc10x_config: read! ]\n");
217 dpavlin 57 }
218    
219 dpavlin 58 return 1;
220     }
221 dpavlin 57
222     #define PCI_VENDOR_ID_MOTOROLA 0x1057
223     #define MPC10X_BRIDGE_106 ((PCI_DEVICE_ID_MOTOROLA_MPC106 << 16) | \
224     PCI_VENDOR_ID_MOTOROLA)
225     #define MPC10X_BRIDGE_8240 ((0x0003 << 16) | PCI_VENDOR_ID_MOTOROLA)
226     #define MPC10X_BRIDGE_107 ((0x0004 << 16) | PCI_VENDOR_ID_MOTOROLA)
227     #define MPC10X_BRIDGE_8245 ((0x0006 << 16) | PCI_VENDOR_ID_MOTOROLA)
228    
229 dpavlin 58 DEVICE_ACCESS(mpc10x_data)
230     {
231     uint64_t idata = 0, odata = 0;
232 dpavlin 57
233 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 );
234     if (writeflag == MEM_WRITE) {
235 dpavlin 60 idata = memory_readmax64(cpu, data, len|MEM_PCI_LITTLE_ENDIAN);
236     fatal("[ mpc10x_data: write -> %x ]\n", (int)idata);
237     }
238     if (writeflag == MEM_READ) {
239 dpavlin 57 odata = MPC10X_BRIDGE_8245;
240 dpavlin 60 memory_writemax64(cpu, data, len|MEM_PCI_LITTLE_ENDIAN, odata);
241     debug("odata = %x\n", (int)odata);
242 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);
243 dpavlin 57 }
244    
245     return 1;
246     }
247    
248 dpavlin 58
249 dpavlin 53 DEVINIT(mpc10x)
250 dpavlin 20 {
251 dpavlin 53 struct mpc10x_data *d;
252 dpavlin 20 char tmp[300];
253 dpavlin 34 int i;
254 dpavlin 20
255 dpavlin 53 CHECK_ALLOCATION(d = malloc(sizeof(struct mpc10x_data)));
256     memset(d, 0, sizeof(struct mpc10x_data));
257 dpavlin 20
258 dpavlin 34 /* Connect to the CPU's interrupt pin: */
259     INTERRUPT_CONNECT(devinit->interrupt_path, d->ppc_irq);
260    
261 dpavlin 53 /* Register 32 mpc10x interrupts: */
262 dpavlin 34 for (i=0; i<32; i++) {
263     struct interrupt template;
264     char n[300];
265 dpavlin 53 snprintf(n, sizeof(n), "%s.mpc10x.%i",
266 dpavlin 34 devinit->interrupt_path, i);
267     memset(&template, 0, sizeof(template));
268 dpavlin 42 template.line = 1 << i;
269 dpavlin 34 template.name = n;
270     template.extra = d;
271 dpavlin 53 template.interrupt_assert = mpc10x_interrupt_assert;
272     template.interrupt_deassert = mpc10x_interrupt_deassert;
273 dpavlin 34 interrupt_handler_register(&template);
274     }
275    
276 dpavlin 58 #define MPC10X_MAPB_CNFG_ADDR 0xfec00000
277     #define MPC10X_MAPB_CNFG_DATA 0xfee00000
278    
279     #define MPC10X_MAPB_ISA_IO_BASE 0xfe000000
280     #define MPC10X_MAPB_ISA_MEM_BASE 0x80000000
281     #define MPC10X_MAPB_DRAM_OFFSET 0x00000000
282    
283     #define MPC10X_MAPB_PCI_IO_START 0x00000000
284     #define MPC10X_MAPB_PCI_IO_END (0x00c00000 - 1)
285     #define MPC10X_MAPB_PCI_MEM_START 0x80000000
286     #define MPC10X_MAPB_PCI_MEM_END (0xc0000000 - 1)
287    
288     #define MPC10X_MAPB_PCI_MEM_OFFSET (MPC10X_MAPB_ISA_MEM_BASE - \
289     MPC10X_MAPB_PCI_MEM_START)
290    
291    
292    
293 dpavlin 20 /* Register a PCI bus: */
294 dpavlin 53 snprintf(tmp, sizeof(tmp), "%s.mpc10x", devinit->interrupt_path);
295 dpavlin 20 d->pci_data = bus_pci_init(
296 dpavlin 34 devinit->machine,
297     tmp, /* pciirq path */
298 dpavlin 58 0x00000000, /* pci device io offset */
299     0x00000000, /* pci device mem offset */
300     0xfe000000, /* PCI portbase */
301 dpavlin 57 0x80000000, /* PCI membase: TODO */
302 dpavlin 34 tmp, /* PCI irqbase */
303 dpavlin 58 0xfe000000, /* ISA portbase: TODO */
304     0x80000000, /* ISA membase: TODO */
305 dpavlin 34 tmp); /* ISA irqbase */
306 dpavlin 20
307 dpavlin 57 /* PCI host bridge */
308     bus_pci_add(devinit->machine, d->pci_data,
309     devinit->machine->memory, 0, 0, 0, "mpc10x_host_bridge");
310 dpavlin 34
311 dpavlin 57 /* MPC10x configuration */
312     memory_device_register(devinit->machine->memory, "mpc10x_config",
313 dpavlin 58 0xfec00000, 1, dev_mpc10x_config_access, d, DM_DEFAULT, NULL);
314     memory_device_register(devinit->machine->memory, "mpc10x_data",
315     0xfee00000, 8, dev_mpc10x_data_access, d, DM_DEFAULT, NULL);
316 dpavlin 34
317 dpavlin 58 #if 0
318 dpavlin 20 /* PCI configuration registers: */
319 dpavlin 53 memory_device_register(devinit->machine->memory, "mpc10x_pci",
320 dpavlin 57 0xfee00000, 8, dev_mpc10x_pci_access, d, DM_DEFAULT, NULL);
321 dpavlin 20
322     /* Interrupt controller: */
323 dpavlin 53 memory_device_register(devinit->machine->memory, "mpc10x_int",
324     MPC_UIC_BASE, MPC_UIC_SIZE, dev_mpc10x_int_access, d,
325 dpavlin 34 DM_DEFAULT, NULL);
326 dpavlin 58 #endif
327 dpavlin 20
328     /* Two serial ports: */
329 dpavlin 53 snprintf(tmp, sizeof(tmp), "ns16550 irq=%s.mpc10x.%i addr=0x%llx "
330 dpavlin 49 "name2=tty0", devinit->interrupt_path, 31 - MPC_IB_UART_0,
331     (long long)MPC_COM0);
332 dpavlin 34 devinit->machine->main_console_handle = (size_t)
333     device_add(devinit->machine, tmp);
334 dpavlin 49 #if 0
335 dpavlin 53 snprintf(tmp, sizeof(tmp), "ns16550 irq=%s.mpc10x.%i addr=0x%llx "
336 dpavlin 49 "name2=tty1", devinit->interrupt_path, 31 - MPC_IB_UART_1,
337     (long long)MPC_COM1);
338     device_add(devinit->machine, tmp);
339     #endif
340 dpavlin 20
341 dpavlin 34 devinit->return_ptr = d->pci_data;
342    
343     return 1;
344 dpavlin 20 }
345    

  ViewVC Help
Powered by ViewVC 1.1.26