/[gxemul]/upstream/0.4.6/src/devices/dev_lca.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

Contents of /upstream/0.4.6/src/devices/dev_lca.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 43 - (show annotations)
Mon Oct 8 16:22:43 2007 UTC (16 years, 8 months ago) by dpavlin
File MIME type: text/plain
File size: 9928 byte(s)
0.4.6
1 /*
2 * Copyright (C) 2006-2007 Anders Gavare. All rights reserved.
3 *
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 * $Id: dev_lca.c,v 1.10 2007/06/15 19:11:15 debug Exp $
29 *
30 * COMMENT: LCA PCI bus, for Alpha machines
31 */
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36
37 #include "bus_isa.h"
38 #include "bus_pci.h"
39 #include "cpu.h"
40 #include "device.h"
41 #include "emul.h"
42 #include "interrupt.h"
43 #include "machine.h"
44 #include "memory.h"
45 #include "misc.h"
46
47
48 #include "alpha_lcareg.h"
49
50 #define LCA_ISA_BASE (LCA_PCI_SIO + 0x10000000)
51 #define LCA_ISA_MEMBASE (LCA_PCI_SIO + 0x18000000)
52
53
54 struct lca_data {
55 struct pci_data *pci_data;
56
57 uint64_t ioc_conf;
58 uint64_t tlb_enable;
59 uint64_t window_base_0;
60 uint64_t window_mask_0;
61 uint64_t window_t_base_0;
62 uint64_t window_base_1;
63 uint64_t window_mask_1;
64 uint64_t window_t_base_1;
65 };
66
67
68 /*
69 * lca_interrupt_assert():
70 *
71 * Line 0 = ISA interrupt.
72 */
73 void lca_interrupt_assert(struct interrupt *interrupt)
74 {
75 fatal("lca_interrupt_assert: TODO\n");
76 exit(1);
77 }
78
79
80 /*
81 * lca_interrupt_deassert():
82 *
83 * Line 0 = ISA interrupt.
84 */
85 void lca_interrupt_deassert(struct interrupt *interrupt)
86 {
87 fatal("lca_interrupt_deassert: TODO\n");
88 exit(1);
89 }
90
91
92 DEVICE_ACCESS(lca_pci_conf)
93 {
94 uint64_t idata = 0, odata = 0;
95 int tag, bus, dev, func, reg;
96 struct lca_data *d = extra;
97
98 if (writeflag == MEM_WRITE)
99 idata = memory_readmax64(cpu, data, len);
100
101 /*
102 * 1. Decompose the address into a tag.
103 *
104 * According to NetBSD's lca_pci.c, the address is composed like this:
105 *
106 * addr = tag << 5 | (regoffset & ~0x03) << 5 | 0x3 << 3
107 */
108 reg = (relative_addr >> 5) & 0xfc;
109 tag = (relative_addr >> 5) & ~0xff;
110
111 /*
112 * 2. Decompose the tag into bus, dev, and func.
113 *
114 * The tag can be constructed in one of two ways. On the primary
115 * bus (nr 0):
116 *
117 * tag = (1 << (device + 11)) | (function << 8);
118 *
119 * and on other busses, the tag is a normal:
120 *
121 * tag = (bus << 16) | (device << 11) | (function << 8)
122 */
123 /* printf("tag = 0x%x\n", (int)tag); */
124 bus = d->ioc_conf & 1;
125
126 if (bus == 0) {
127 for (dev=0; dev<21; dev++)
128 if (tag & (0x800 << dev))
129 break;
130 if (dev >= 21) {
131 /* fatal("[ LCA: No bus 0 device? TODO ]\n");
132 exit(1); */
133 dev = 0;
134 }
135 } else {
136 fatal("TODO. Non-zero bus.\n");
137 exit(1);
138 }
139
140 func = (tag >> 8) & 7;
141 /* printf("bus=%i dev=%i func=%i reg=%i\n", bus,dev,func,reg); */
142
143 /* Pass PCI accesses onto bus_pci: */
144 bus_pci_setaddr(cpu, d->pci_data, bus, dev, func, reg);
145 bus_pci_data_access(cpu, d->pci_data, writeflag == MEM_READ?
146 &odata : &idata, len, writeflag);
147
148 if (writeflag == MEM_READ)
149 memory_writemax64(cpu, data, len, odata);
150
151 return 1;
152 }
153
154
155 DEVICE_ACCESS(lca_isa)
156 {
157 unsigned int ofs, i;
158 uint8_t byte;
159
160 relative_addr >>= 5;
161
162 ofs = relative_addr & 3;
163 if (ofs > len) {
164 fatal("[ ofs=%i len=%i in lca_isa access function. "
165 "aborting ]\n", ofs, len);
166 exit(1);
167 }
168
169 if (writeflag == MEM_WRITE) {
170 byte = data[ofs % len];
171 return cpu->memory_rw(cpu, cpu->mem, LCA_ISA_BASE +
172 relative_addr, &byte, 1, writeflag, CACHE_NONE);
173 }
174
175 cpu->memory_rw(cpu, cpu->mem, LCA_ISA_BASE + relative_addr,
176 &byte, 1, MEM_READ, CACHE_NONE);
177
178 for (i=0; i<len; i++)
179 data[i] = i == ofs? byte : 0x00;
180
181 return 1;
182 }
183
184
185 DEVICE_ACCESS(lca_ioc)
186 {
187 uint64_t idata = 0, odata = 0;
188 struct lca_data *d = extra;
189
190 if (writeflag == MEM_WRITE)
191 idata = memory_readmax64(cpu, data, len);
192
193 switch (relative_addr + LCA_IOC_BASE) {
194
195 case LCA_IOC_BASE:
196 /* Ignore? Linux reads from the base at startup. */
197 break;
198
199 case LCA_IOC_CONF:
200 if (writeflag == MEM_READ) {
201 odata = d->ioc_conf;
202 } else {
203 d->ioc_conf = idata;
204 /* Only bit 0 is implemented so far, the PCI bus 0 vs
205 bus non-0 selection bit. */
206 if (idata & ~1) {
207 fatal("TODO: Write to unimplemented bit of"
208 " IOC_CONF: 0x%x\n", (int)idata);
209 exit(1);
210 }
211 }
212 break;
213
214 case LCA_IOC_TBIA:
215 /* TLB Invalidate All. */
216 /* TODO: For now, let's just ignore it. */
217 break;
218
219 case LCA_IOC_TB_ENA:
220 if (writeflag == MEM_READ) {
221 odata = d->tlb_enable;
222 } else {
223 d->tlb_enable = idata;
224 /* TODO: Actually implement this. */
225 if (idata & ~IOC_TB_ENA_TEN) {
226 fatal("TODO: LCA_IOC_TB_ENA value "
227 " (0x%"PRIx64") has unimplemented "
228 "bits.\n", (uint64_t)idata);
229 exit(1);
230 }
231 }
232 break;
233
234 case LCA_IOC_W_BASE0:
235 if (writeflag == MEM_READ) {
236 odata = d->window_base_0;
237 } else {
238 d->window_base_0 = idata;
239 /* TODO: Actually implement this. */
240 if (idata != 0ULL && idata != 0x300800000ULL) {
241 fatal("TODO: LCA_IOC_W_BASE0 value differs"
242 " (0x%"PRIx64") from the only implemented"
243 " values\n", (uint64_t)idata);
244 exit(1);
245 }
246 }
247 break;
248
249 case LCA_IOC_W_MASK0:
250 if (writeflag == MEM_READ) {
251 odata = d->window_mask_0;
252 } else {
253 d->window_mask_0 = idata;
254 /* TODO: Actually implement this. */
255 if (idata != 0x700000ULL) {
256 fatal("TODO: LCA_IOC_W_MASK0 value differs"
257 " (0x%"PRIx64") from the only implemented"
258 " value\n", (uint64_t)idata);
259 exit(1);
260 }
261 }
262 break;
263
264 case LCA_IOC_W_T_BASE0:
265 if (writeflag == MEM_READ) {
266 odata = d->window_t_base_0;
267 } else {
268 d->window_t_base_0 = idata;
269 /* TODO: Actually implement this. */
270 }
271 break;
272
273 case LCA_IOC_W_BASE1:
274 if (writeflag == MEM_READ) {
275 odata = d->window_base_1;
276 } else {
277 d->window_base_1 = idata;
278 /* TODO: Actually implement this. */
279 if (idata != 0x240000000ULL) {
280 fatal("TODO: LCA_IOC_W_BASE1 value differs"
281 " (0x%"PRIx64") from the only implemented"
282 " value\n", (uint64_t)idata);
283 exit(1);
284 }
285 }
286 break;
287
288 case LCA_IOC_W_MASK1:
289 if (writeflag == MEM_READ) {
290 odata = d->window_mask_1;
291 } else {
292 d->window_mask_1 = idata;
293 /* TODO: Actually implement this. */
294 if (idata != 0x3ff00000ULL) {
295 fatal("TODO: LCA_IOC_W_MASK1 value differs"
296 " (0x%"PRIx64") from the only implemented"
297 " value\n", (uint64_t)idata);
298 exit(1);
299 }
300 }
301 break;
302
303 case LCA_IOC_W_T_BASE1:
304 if (writeflag == MEM_READ) {
305 odata = d->window_t_base_1;
306 } else {
307 d->window_t_base_1 = idata;
308 /* TODO: Actually implement this. */
309 }
310 break;
311
312 default:fatal("[ lca_ioc: unimplemented %s to offset 0x%x",
313 writeflag == MEM_WRITE? "write" : "read", (int)
314 relative_addr);
315 if (writeflag == MEM_WRITE)
316 fatal(": 0x%x", (int)idata);
317 fatal(" ]\n");
318 exit(1);
319 }
320
321 if (writeflag == MEM_READ)
322 memory_writemax64(cpu, data, len, odata);
323
324 return 1;
325 }
326
327
328 DEVINIT(lca)
329 {
330 char *interrupt_path;
331 struct interrupt interrupt_template;
332 struct lca_data *d;
333
334 CHECK_ALLOCATION(d = malloc(sizeof(struct lca_data)));
335 memset(d, 0, sizeof(struct lca_data));
336
337 /* Register a PCI bus: */
338 d->pci_data = bus_pci_init(
339 devinit->machine,
340 "TODO: irq" /* pciirq: TODO */,
341 LCA_PCI_SIO, /* pci device io offset */
342 0x00000000, /* pci device mem offset: TODO */
343 0x00000000, /* PCI portbase: TODO */
344 0x00000000, /* PCI membase: TODO */
345 "TODO: pci irq base", /* PCI irqbase: TODO */
346 LCA_ISA_BASE, /* ISA portbase */
347 LCA_ISA_MEMBASE, /* ISA membase */
348 "TODO: irqbase isa"); /* ISA irqbase: TODO */
349
350 /* Add the "sio0" controller (as seen by NetBSD): */
351 bus_pci_add(devinit->machine, d->pci_data, devinit->machine->memory,
352 0, 7, 0, "i82378zb");
353
354 memory_device_register(devinit->machine->memory, "lca_pci_conf",
355 LCA_PCI_CONF, 0x20000000, dev_lca_pci_conf_access, (void *)d,
356 DM_DEFAULT, NULL);
357
358 memory_device_register(devinit->machine->memory, "lca_isa",
359 LCA_PCI_SIO, 0x10000 << 5, dev_lca_isa_access, (void *)d,
360 DM_DEFAULT, NULL);
361
362 memory_device_register(devinit->machine->memory, "lca_ioc",
363 LCA_IOC_BASE, 0x20000000, dev_lca_ioc_access, (void *)d,
364 DM_DEFAULT, NULL);
365
366 CHECK_ALLOCATION(interrupt_path =
367 malloc(strlen(devinit->machine->path) + 10));
368 snprintf(interrupt_path, strlen(devinit->machine->path) + 10,
369 "%s.lca", devinit->machine->path);
370
371 memset(&interrupt_template, 0, sizeof(interrupt_template));
372 interrupt_template.line = 0;
373 interrupt_template.name = interrupt_path;
374 interrupt_template.extra = d;
375 interrupt_template.interrupt_assert = lca_interrupt_assert;
376 interrupt_template.interrupt_deassert = lca_interrupt_deassert;
377 interrupt_handler_register(&interrupt_template);
378
379 bus_isa_init(devinit->machine, interrupt_path,
380 BUS_ISA_IDE0 | BUS_ISA_IDE1, LCA_ISA_BASE, LCA_ISA_MEMBASE);
381
382 return 1;
383 }
384

  ViewVC Help
Powered by ViewVC 1.1.26