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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 40 - (show annotations)
Mon Oct 8 16:22:11 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 9944 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1539 2007/05/01 04:03:51 debug Exp $
20070415	Landisk PCLOCK should be 33.33 MHz, not 50 MHz. (This makes
		the clock run at correct speed.)
		FINALLY found and fixed the bug which caused OpenBSD/landisk
		to randomly bug out: an &-sign was missing in the special case
		handling of FPSCR in the 'LDS.L @Rm+,FPSCR' instruction.
		Adding similar special case handling for 'LDC.L @Rm+,SR'
		(calling sh_update_sr() instead of just loading).
		Implementing the 'FCNVSD FPUL,DRn' and 'FCNVDS DRm,FPUL'
		SuperH instructions.
		The 'LDC Rm,SR' instruction now immediately breaks out of the
		dyntrans loop if an interrupt is to be triggered.
20070416	In memory_rw.c, if mapping a page as writable, make sure to
		invalidate code translations even if the data access was a
		read.
		Minor SuperH updates.
20070418	Removing the dummy M68K emulation mode.
		Minor SH update (turning unnecessary sts_mach_rn, sts_macl_rn,
		and sts_pr_rn instruction handlers into mov_rm_rn).
20070419	Beginning to add a skeleton for an M88K mode: Adding a hack to
		allow OpenBSD/m88k a.out binaries to be loaded, and disassembly
		of a few simple 88K instructions.
		Commenting out the 'LDC Rm,SR' fix from a few days ago, because
		it made Linux/dreamcast bug out.
		Adding a hack to dev_sh4.c (an extra translation cache
		invalidation), which allows OpenBSD/landisk to boot ok after
		an install. Upgrading the Landisk machine mode to stable,
		updating documentation, etc.
20070420	Experimenting with adding a PCI controller (pcic) to dev_sh4.
		Adding a dummy Realtek 8139C+ skeleton device (dev_rtl8139c).
		Implementing the first M88K instructions (br, or[.u] imm), and
		adding disassembly of some more instructions.
20070421	Continuing a little on dev_rtl8139c.
20070422	Implementing the 9346 EEPROM "read" command for dev_rtl8139c.
		Finally found and fixed an old bug in the log n symbol search
		(it sometimes missed symbols). Debug trace (-i, -t etc) should
		now show more symbols. :-)
20070423	Continuing a little on M88K disassembly.
20070428	Fixing a memset arg order bug in src/net/net.c (thanks to
		Nigel Horne for noticing the bug).
		Applying parts of a patch from Carl van Schaik to clear out
		bottom bits of MIPS addresses more correctly, when using large
		page sizes, and doing some other minor cleanup/refactoring.
		Fixing a couple of warnings given by gcc with the -W option (a
		few more warnings than just plain -Wall).
		Reducing SuperH dyntrans physical address space from 64-bit to
		32-bit (since SH5/SH64 isn't imlemented yet anyway).
		Adding address-to-symbol annotation to a few more instructions
		in the SuperH instruction trace output.
		Beginning regression testing for the next release.
		Reverting the value of SCIF_DELAYED_TX_VALUE from 1 to 2,
		because OpenBSD/landisk may otherwise hang randomly.
20070429	The ugly hack/workaround to get OpenBSD/landisk booting without
		crashing does NOT work anymore (with the April 21 snapshot
		of OpenBSD/landisk). Strangely enough, removing the hack
		completely causes OpenBSD/landisk to work (!).
		More regression testing (re-testing everything SuperH-related,
		and some other things).
		Cobalt interrupts were actually broken; fixing by commenting
		out the DEC21143s in the Cobalt machine.
20070430	More regression testing.
20070501	Updating the OpenBSD/landisk install instructions to use
		4.1 instead of the current snapshot.
		GAAAH! OpenBSD/landisk 4.1 _needs_ the ugly hack/workaround;
		reintroducing it again. (The 4.1 kernel is actually from
		2007-03-11.)
		Simplifying the NetBSD/evbarm install instructions a bit.
		More regression testing.

==============  RELEASE 0.4.5.1  ==============


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.9 2007/04/28 09:19:52 debug Exp $
29 *
30 * 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 = malloc(sizeof(struct lca_data));
333 if (d == NULL) {
334 fprintf(stderr, "out of memory\n");
335 exit(1);
336 }
337 memset(d, 0, sizeof(struct lca_data));
338
339 /* Register a PCI bus: */
340 d->pci_data = bus_pci_init(
341 devinit->machine,
342 "TODO: irq" /* pciirq: TODO */,
343 LCA_PCI_SIO, /* pci device io offset */
344 0x00000000, /* pci device mem offset: TODO */
345 0x00000000, /* PCI portbase: TODO */
346 0x00000000, /* PCI membase: TODO */
347 "TODO: pci irq base", /* PCI irqbase: TODO */
348 LCA_ISA_BASE, /* ISA portbase */
349 LCA_ISA_MEMBASE, /* ISA membase */
350 "TODO: irqbase isa"); /* ISA irqbase: TODO */
351
352 /* Add the "sio0" controller (as seen by NetBSD): */
353 bus_pci_add(devinit->machine, d->pci_data, devinit->machine->memory,
354 0, 7, 0, "i82378zb");
355
356 memory_device_register(devinit->machine->memory, "lca_pci_conf",
357 LCA_PCI_CONF, 0x20000000, dev_lca_pci_conf_access, (void *)d,
358 DM_DEFAULT, NULL);
359
360 memory_device_register(devinit->machine->memory, "lca_isa",
361 LCA_PCI_SIO, 0x10000 << 5, dev_lca_isa_access, (void *)d,
362 DM_DEFAULT, NULL);
363
364 memory_device_register(devinit->machine->memory, "lca_ioc",
365 LCA_IOC_BASE, 0x20000000, dev_lca_ioc_access, (void *)d,
366 DM_DEFAULT, NULL);
367
368 interrupt_path = malloc(strlen(devinit->machine->path) + 10);
369 snprintf(interrupt_path, strlen(devinit->machine->path) + 10,
370 "%s.lca", devinit->machine->path);
371
372 memset(&interrupt_template, 0, sizeof(interrupt_template));
373 interrupt_template.line = 0;
374 interrupt_template.name = interrupt_path;
375 interrupt_template.extra = d;
376 interrupt_template.interrupt_assert = lca_interrupt_assert;
377 interrupt_template.interrupt_deassert = lca_interrupt_deassert;
378 interrupt_handler_register(&interrupt_template);
379
380 bus_isa_init(devinit->machine, interrupt_path,
381 BUS_ISA_IDE0 | BUS_ISA_IDE1, LCA_ISA_BASE, LCA_ISA_MEMBASE);
382
383 return 1;
384 }
385

  ViewVC Help
Powered by ViewVC 1.1.26