/[gxemul]/upstream/0.4.5.1/src/devices/dev_cpc700.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 /upstream/0.4.5.1/src/devices/dev_cpc700.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 41 - (hide annotations)
Mon Oct 8 16:22:20 2007 UTC (16 years, 8 months ago) by dpavlin
File MIME type: text/plain
File size: 7214 byte(s)
0.4.5.1
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 34 * $Id: dev_cpc700.c,v 1.10 2007/01/29 19:03:16 debug Exp $
29 dpavlin 20 *
30     * IBM CPC700 bridge; PCI and interrupt controller.
31     */
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     #include "machine.h"
41     #include "memory.h"
42     #include "misc.h"
43    
44     #include "cpc700reg.h"
45    
46    
47 dpavlin 34 struct cpc700_data {
48     struct interrupt ppc_irq; /* Connected to the CPU */
49    
50     uint32_t sr; /* Interrupt Status register */
51     uint32_t er; /* Interrupt Enable register */
52    
53     struct pci_data *pci_data; /* PCI bus */
54     };
55    
56    
57     void cpc700_interrupt_assert(struct interrupt *interrupt)
58     {
59     struct cpc700_data *d = interrupt->extra;
60     d->sr |= (1 << interrupt->line);
61     if (d->sr & d->er)
62     INTERRUPT_ASSERT(d->ppc_irq);
63     }
64     void cpc700_interrupt_deassert(struct interrupt *interrupt)
65     {
66     struct cpc700_data *d = interrupt->extra;
67     d->sr &= ~(1 << interrupt->line);
68     if (!(d->sr & d->er))
69     INTERRUPT_DEASSERT(d->ppc_irq);
70     }
71    
72    
73 dpavlin 20 /*
74     * dev_cpc700_pci_access():
75     *
76 dpavlin 22 * Passes PCI indirect addr and data accesses onto bus_pci.
77 dpavlin 20 */
78 dpavlin 22 DEVICE_ACCESS(cpc700_pci)
79 dpavlin 20 {
80     uint64_t idata = 0, odata = 0;
81 dpavlin 22 int bus, dev, func, reg;
82 dpavlin 20 struct cpc700_data *d = extra;
83    
84     if (writeflag == MEM_WRITE)
85 dpavlin 22 idata = memory_readmax64(cpu, data, len|MEM_PCI_LITTLE_ENDIAN);
86 dpavlin 20
87 dpavlin 22 switch (relative_addr) {
88     case 0: /* Address: */
89     bus_pci_decompose_1(idata, &bus, &dev, &func, &reg);
90     bus_pci_setaddr(cpu, d->pci_data, bus, dev, func, reg);
91     break;
92 dpavlin 20
93 dpavlin 22 case 4: /* Data: */
94     bus_pci_data_access(cpu, d->pci_data, writeflag == MEM_READ?
95     &odata : &idata, len, writeflag);
96     break;
97     }
98 dpavlin 20
99     if (writeflag == MEM_READ)
100 dpavlin 22 memory_writemax64(cpu, data, len|MEM_PCI_LITTLE_ENDIAN, odata);
101 dpavlin 20
102     return 1;
103     }
104    
105    
106     /*
107     * dev_cpc700_int_access():
108     *
109     * The interrupt controller.
110     */
111 dpavlin 22 DEVICE_ACCESS(cpc700_int)
112 dpavlin 20 {
113     struct cpc700_data *d = extra;
114     uint64_t idata = 0, odata = 0;
115    
116     if (writeflag == MEM_WRITE)
117     idata = memory_readmax64(cpu, data, len);
118    
119     switch (relative_addr) {
120    
121     case CPC_UIC_SR:
122     /* Status register (cleared by writing ones): */
123 dpavlin 34 if (writeflag == MEM_READ) {
124 dpavlin 20 odata = d->sr;
125 dpavlin 34 } else {
126 dpavlin 20 d->sr &= ~idata;
127 dpavlin 34 if (!(d->sr & d->er))
128     INTERRUPT_DEASSERT(d->ppc_irq);
129     }
130 dpavlin 20 break;
131    
132     case CPC_UIC_SRS:
133     /* Status register set: */
134     if (writeflag == MEM_READ) {
135     fatal("[ cpc700_int: read from CPC_UIC_SRS? ]\n");
136     odata = d->sr;
137 dpavlin 34 } else {
138 dpavlin 20 d->sr = idata;
139 dpavlin 34 if (d->sr & d->er)
140     INTERRUPT_ASSERT(d->ppc_irq);
141     else
142     INTERRUPT_DEASSERT(d->ppc_irq);
143     }
144 dpavlin 20 break;
145    
146     case CPC_UIC_ER:
147     /* Enable register: */
148 dpavlin 34 if (writeflag == MEM_READ) {
149 dpavlin 20 odata = d->er;
150 dpavlin 34 } else {
151 dpavlin 20 d->er = idata;
152 dpavlin 34 if (d->sr & d->er)
153     INTERRUPT_ASSERT(d->ppc_irq);
154     else
155     INTERRUPT_DEASSERT(d->ppc_irq);
156     }
157 dpavlin 20 break;
158    
159     case CPC_UIC_MSR:
160     /* Masked status: */
161 dpavlin 34 if (writeflag == MEM_READ) {
162 dpavlin 20 odata = d->sr & d->er;
163 dpavlin 34 } else {
164 dpavlin 20 fatal("[ cpc700_int: write to CPC_UIC_MSR? ]\n");
165 dpavlin 34 }
166 dpavlin 20 break;
167    
168     default:if (writeflag == MEM_WRITE) {
169     fatal("[ cpc700_int: unimplemented write to "
170     "offset 0x%x: data=0x%x ]\n", (int)
171     relative_addr, (int)idata);
172     } else {
173     fatal("[ cpc700_int: unimplemented read from "
174     "offset 0x%x ]\n", (int)relative_addr);
175     }
176     }
177    
178     if (writeflag == MEM_READ)
179     memory_writemax64(cpu, data, len, odata);
180    
181     return 1;
182     }
183    
184    
185 dpavlin 34 DEVINIT(cpc700)
186 dpavlin 20 {
187     struct cpc700_data *d;
188     char tmp[300];
189 dpavlin 34 int i;
190 dpavlin 20
191     d = malloc(sizeof(struct cpc700_data));
192     if (d == NULL) {
193     fprintf(stderr, "out of memory\n");
194     exit(1);
195     }
196     memset(d, 0, sizeof(struct cpc700_data));
197    
198 dpavlin 34 /* Connect to the CPU's interrupt pin: */
199     INTERRUPT_CONNECT(devinit->interrupt_path, d->ppc_irq);
200    
201     /* Register 32 CPC700 interrupts: */
202     for (i=0; i<32; i++) {
203     struct interrupt template;
204     char n[300];
205     snprintf(n, sizeof(n), "%s.cpc700.%i",
206     devinit->interrupt_path, i);
207     memset(&template, 0, sizeof(template));
208     template.line = i;
209     template.name = n;
210     template.extra = d;
211     template.interrupt_assert = cpc700_interrupt_assert;
212     template.interrupt_deassert = cpc700_interrupt_deassert;
213     interrupt_handler_register(&template);
214     }
215    
216 dpavlin 20 /* Register a PCI bus: */
217 dpavlin 34 snprintf(tmp, sizeof(tmp), "%s.cpc700", devinit->interrupt_path);
218 dpavlin 20 d->pci_data = bus_pci_init(
219 dpavlin 34 devinit->machine,
220     tmp, /* pciirq path */
221 dpavlin 20 0, /* pci device io offset */
222     0, /* pci device mem offset */
223     CPC_PCI_IO_BASE, /* PCI portbase */
224     CPC_PCI_MEM_BASE, /* PCI membase: TODO */
225 dpavlin 34 tmp, /* PCI irqbase */
226 dpavlin 20 0, /* ISA portbase: TODO */
227     0, /* ISA membase: TODO */
228 dpavlin 34 tmp); /* ISA irqbase */
229 dpavlin 20
230 dpavlin 34 switch (devinit->machine->machine_type) {
231    
232 dpavlin 20 case MACHINE_PMPPC:
233 dpavlin 34 bus_pci_add(devinit->machine, d->pci_data,
234     devinit->machine->memory, 0, 0, 0, "heuricon_pmppc");
235 dpavlin 20 break;
236 dpavlin 34
237 dpavlin 20 default:fatal("!\n! WARNING: cpc700 for non-implemented machine"
238     " type\n!\n");
239     exit(1);
240     }
241    
242     /* PCI configuration registers: */
243 dpavlin 34 memory_device_register(devinit->machine->memory, "cpc700_pci",
244     CPC_PCICFGADR, 8, dev_cpc700_pci_access, d, DM_DEFAULT, NULL);
245 dpavlin 20
246     /* Interrupt controller: */
247 dpavlin 34 memory_device_register(devinit->machine->memory, "cpc700_int",
248     CPC_UIC_BASE, CPC_UIC_SIZE, dev_cpc700_int_access, d,
249     DM_DEFAULT, NULL);
250 dpavlin 20
251     /* Two serial ports: */
252 dpavlin 34 snprintf(tmp, sizeof(tmp), "ns16550 irq=%s.cpc700.%i addr=0x%llx "
253     "name2=tty0", devinit->interrupt_path, 31 - CPC_IB_UART_0,
254     (long long)CPC_COM0);
255     devinit->machine->main_console_handle = (size_t)
256     device_add(devinit->machine, tmp);
257     snprintf(tmp, sizeof(tmp), "ns16550 irq=%s.cpc700.%i addr=0x%llx "
258     "name2=tty1", devinit->interrupt_path, 31 - CPC_IB_UART_1,
259     (long long)CPC_COM1);
260     device_add(devinit->machine, tmp);
261 dpavlin 20
262 dpavlin 34 devinit->return_ptr = d->pci_data;
263    
264     return 1;
265 dpavlin 20 }
266    

  ViewVC Help
Powered by ViewVC 1.1.26