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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 41 - (show annotations)
Mon Oct 8 16:22:20 2007 UTC (16 years, 8 months ago) by dpavlin
File MIME type: text/plain
File size: 13051 byte(s)
0.4.5.1
1 /*
2 * Copyright (C) 2003-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_dec5800.c,v 1.21 2007/01/28 00:41:16 debug Exp $
29 *
30 * Emulation of devices found in a DECsystem 58x0, where x is the number
31 * of CPUs in the system. (The CPU board is called KN5800 by Ultrix.)
32 *
33 * o) timers and misc stuff
34 * o) BI (Backplane Interconnect)
35 * o) CCA (Console Communication Area)
36 * o) XMI (Extended Memory Interconnect)
37 *
38 * TODO: This hardware is not very easy to find docs about.
39 * Perhaps VAX 6000/300 docs?
40 */
41
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <string.h>
45
46 #include "console.h"
47 #include "cpu.h"
48 #include "device.h"
49 #include "devices.h"
50 #include "interrupt.h"
51 #include "machine.h"
52 #include "memory.h"
53 #include "misc.h"
54
55
56 #define DEV_DEC5800_LENGTH 0x1000 /* TODO */
57
58 struct dec5800_data {
59 uint32_t csr;
60 struct interrupt cpu_irq;
61
62 uint32_t vector_0x50;
63
64 struct interrupt timer_irq;
65 };
66
67
68 void dec5800_interrupt_assert(struct interrupt *interrupt)
69 {
70 struct dec5800_data *d = interrupt->extra;
71 d->csr |= (1 << interrupt->line);
72 if (d->csr & 0x10000000)
73 INTERRUPT_ASSERT(d->cpu_irq);
74 }
75 void dec5800_interrupt_deassert(struct interrupt *interrupt)
76 {
77 struct dec5800_data *d = interrupt->extra;
78 d->csr &= ~(1 << interrupt->line);
79 if (!(d->csr & 0x10000000))
80 INTERRUPT_DEASSERT(d->cpu_irq);
81 }
82
83
84 DEVICE_TICK(dec5800)
85 {
86 struct dec5800_data *d = extra;
87
88 /* Timer interrupts? */
89 if (d->csr & 0x8000) {
90 debug("[ dec5800: timer interrupt! ]\n");
91
92 /* Set timer interrupt pending bit: */
93 d->csr |= 0x20000000;
94
95 INTERRUPT_ASSERT(d->timer_irq);
96 }
97 }
98
99
100 DEVICE_ACCESS(dec5800_vectors)
101 {
102 uint64_t idata = 0, odata = 0;
103 struct dec5800_data *d = extra;
104
105 if (writeflag == MEM_WRITE)
106 idata = memory_readmax64(cpu, data, len);
107
108 if (writeflag == MEM_READ) {
109 /* TODO */
110 /* 0xfc = transmit interrupt, 0xf8 = receive interrupt,
111 0x80 = IPI */
112 odata = d->vector_0x50;
113 /* odata = 0xfc; */
114 debug("[ dec5800_vectors: read from 0x%02x: 0x%02x ]\n",
115 (int)relative_addr, (int)odata);
116 } else {
117 d->vector_0x50 = idata;
118 debug("[ dec5800_vectors: write to 0x%02x: 0x%02x ]\n",
119 (int)relative_addr, (int)idata);
120 }
121
122 if (writeflag == MEM_READ)
123 memory_writemax64(cpu, data, len, odata);
124
125 return 1;
126 }
127
128
129 DEVICE_ACCESS(dec5800)
130 {
131 uint64_t idata = 0, odata = 0;
132 struct dec5800_data *d = extra;
133
134 if (writeflag == MEM_WRITE)
135 idata = memory_readmax64(cpu, data, len);
136
137 /* Lowest 4 bits of csr contain cpu id: */
138 d->csr = (d->csr & ~0xf) | (cpu->cpu_id & 0xf);
139
140 switch (relative_addr) {
141 case 0x0000: /* csr */
142 if (writeflag == MEM_READ) {
143 odata = d->csr;
144 odata ^= random() & 0x10000;
145 debug("[ dec5800: read from csr: 0x%08x ]\n",
146 (int)odata);
147 } else {
148 d->csr = idata;
149
150 /* Ack. timer interrupts: */
151 d->csr &= ~0x20000000;
152 INTERRUPT_DEASSERT(d->timer_irq);
153
154 debug("[ dec5800: write to csr: 0x%08x ]\n",
155 (int)idata);
156 }
157 break;
158 default:
159 if (writeflag==MEM_READ) {
160 debug("[ dec5800: read from 0x%08lx ]\n",
161 (long)relative_addr);
162 } else {
163 debug("[ dec5800: write to 0x%08lx: 0x%08x ]\n",
164 (long)relative_addr, (int)idata);
165 }
166 }
167
168 if (writeflag == MEM_READ)
169 memory_writemax64(cpu, data, len, odata);
170
171 return 1;
172 }
173
174
175 DEVINIT(dec5800)
176 {
177 struct dec5800_data *d;
178 char tmpstr[200];
179 int i;
180
181 d = malloc(sizeof(struct dec5800_data));
182 if (d == NULL) {
183 fprintf(stderr, "out of memory\n");
184 exit(1);
185 }
186 memset(d, 0, sizeof(struct dec5800_data));
187
188 snprintf(tmpstr, sizeof(tmpstr), "%s.2", devinit->interrupt_path);
189 INTERRUPT_CONNECT(tmpstr, d->cpu_irq);
190
191 snprintf(tmpstr, sizeof(tmpstr), "%s.3", devinit->interrupt_path);
192 INTERRUPT_CONNECT(tmpstr, d->timer_irq);
193
194 /* Register 32 CSR interrupts, corresponding to bits in the CSR: */
195 for (i=0; i<32; i++) {
196 char n[200];
197 struct interrupt template;
198 snprintf(n, sizeof(n), "%s.dec5800.%i",
199 devinit->interrupt_path, i);
200 memset(&template, 0, sizeof(template));
201 template.line = i;
202 template.name = n;
203 template.extra = d;
204 template.interrupt_assert = dec5800_interrupt_assert;
205 template.interrupt_deassert = dec5800_interrupt_deassert;
206 interrupt_handler_register(&template);
207 }
208
209 memory_device_register(devinit->machine->memory, "dec5800",
210 devinit->addr, DEV_DEC5800_LENGTH, dev_dec5800_access,
211 d, DM_DEFAULT, NULL);
212 memory_device_register(devinit->machine->memory, "dec5800_vectors",
213 devinit->addr + 0x30000000, 0x100, dev_dec5800_vectors_access,
214 d, DM_DEFAULT, NULL);
215 machine_add_tickfunction(devinit->machine, dev_dec5800_tick,
216 d, 14, 0.0);
217
218 return 1;
219 }
220
221
222 /*****************************************************************************/
223
224
225 #include "bireg.h"
226
227 /* 16 slots, 0x2000 bytes each */
228 #define DEV_DECBI_LENGTH 0x20000
229
230 struct decbi_data {
231 int csr[NNODEBI];
232 };
233
234
235 DEVICE_ACCESS(decbi)
236 {
237 uint64_t idata = 0, odata = 0;
238 int node_nr;
239 struct decbi_data *d = extra;
240
241 if (writeflag == MEM_WRITE)
242 idata = memory_readmax64(cpu, data, len);
243
244 relative_addr += BI_NODESIZE; /* HACK */
245
246 node_nr = relative_addr / BI_NODESIZE;
247 relative_addr &= (BI_NODESIZE - 1);
248
249 /* TODO: This "1" here is the max node number in actual use. */
250 if (node_nr > 1 || node_nr >= NNODEBI)
251 return 0;
252
253 switch (relative_addr) {
254 case BIREG_DTYPE:
255 if (writeflag==MEM_READ) {
256 /*
257 * This is a list of the devices in our BI slots:
258 */
259 switch (node_nr) {
260 case 1: odata = BIDT_KDB50; break; /* Disk */
261 /* case 2: odata = BIDT_DEBNA; break; */
262 /* BIDT_DEBNA = Ethernet */
263 /* case 3: odata = BIDT_MS820; break; */
264 /* BIDT_MS820 = Memory */
265 default:
266 /* No device. */
267 odata = 0;
268 }
269
270 debug("[ decbi: (node %i) read from BIREG_DTYPE:"
271 " 0x%x ]\n", node_nr, (int)odata);
272 } else {
273 debug("[ decbi: (node %i) attempt to write to "
274 "BIREG_DTYPE: 0x%08x ]\n", node_nr, (int)idata);
275 }
276 break;
277 case BIREG_VAXBICSR:
278 if (writeflag==MEM_READ) {
279 odata = (d->csr[node_nr] & ~BICSR_NODEMASK) | node_nr;
280 debug("[ decbi: (node %i) read from BIREG_"
281 "VAXBICSR: 0x%x ]\n", node_nr, (int)odata);
282 } else {
283 d->csr[node_nr] = idata;
284 debug("[ decbi: (node %i) attempt to write to "
285 "BIREG_VAXBICSR: 0x%08x ]\n", node_nr, (int)idata);
286 }
287 break;
288 case 0xf4:
289 if (writeflag==MEM_READ) {
290 odata = 0xffff; /* ? */
291 debug("[ decbi: (node %i) read from 0xf4: "
292 "0x%x ]\n", node_nr, (int)odata);
293 } else {
294 debug("[ decbi: (node %i) attempt to write "
295 "to 0xf4: 0x%08x ]\n", node_nr, (int)idata);
296 }
297 break;
298 default:
299 if (writeflag==MEM_READ) {
300 debug("[ decbi: (node %i) read from unimplemented "
301 "0x%08lx ]\n", node_nr, (long)relative_addr,
302 (int)odata);
303 } else {
304 debug("[ decbi: (node %i) write to unimplemented "
305 "0x%08lx: 0x%08x ]\n", node_nr,
306 (long)relative_addr, (int)idata);
307 }
308 }
309
310 if (writeflag == MEM_READ)
311 memory_writemax64(cpu, data, len, odata);
312
313 return 1;
314 }
315
316
317 DEVINIT(decbi)
318 {
319 struct decbi_data *d;
320
321 d = malloc(sizeof(struct decbi_data));
322 if (d == NULL) {
323 fprintf(stderr, "out of memory\n");
324 exit(1);
325 }
326 memset(d, 0, sizeof(struct decbi_data));
327
328 memory_device_register(devinit->machine->memory, "decbi",
329 devinit->addr + 0x2000, DEV_DECBI_LENGTH - 0x2000,
330 dev_decbi_access, d, DM_DEFAULT, NULL);
331
332 return 1;
333 }
334
335
336 /*****************************************************************************/
337
338
339 /*
340 * CCA, "Console Communication Area" for a DEC 5800 SMP system.
341 */
342
343 struct deccca_data {
344 int dummy;
345 };
346
347
348 DEVICE_ACCESS(deccca)
349 {
350 uint64_t idata = 0, odata = 0;
351 /* struct deccca_data *d = extra; */
352
353 if (writeflag == MEM_WRITE)
354 idata = memory_readmax64(cpu, data, len);
355
356 switch (relative_addr) {
357 case 6:
358 case 7:
359 /* CCA "ID" bytes? These must be here, or Ultrix complains. */
360 if (writeflag == MEM_READ)
361 odata = 67;
362 break;
363 case 8:
364 if (writeflag == MEM_READ)
365 odata = cpu->machine->ncpus;
366 break;
367 case 20:
368 if (writeflag == MEM_READ)
369 odata = (1 << cpu->machine->ncpus) - 1;
370 /* one bit for each cpu */
371 break;
372 case 28:
373 if (writeflag == MEM_READ)
374 odata = (1 << cpu->machine->ncpus) - 1;
375 /* one bit for each enabled(?) cpu */
376 break;
377 default:
378 if (writeflag==MEM_READ) {
379 debug("[ deccca: read from 0x%08lx ]\n",
380 (long)relative_addr);
381 } else {
382 debug("[ deccca: write to 0x%08lx: 0x%08x ]\n",
383 (long)relative_addr, (int)idata);
384 }
385 }
386
387 if (writeflag == MEM_READ)
388 memory_writemax64(cpu, data, len, odata);
389
390 return 1;
391 }
392
393
394 /*
395 * dev_deccca_init():
396 */
397 void dev_deccca_init(struct memory *mem, uint64_t baseaddr)
398 {
399 struct deccca_data *d;
400
401 d = malloc(sizeof(struct deccca_data));
402 if (d == NULL) {
403 fprintf(stderr, "out of memory\n");
404 exit(1);
405 }
406 memset(d, 0, sizeof(struct deccca_data));
407
408 memory_device_register(mem, "deccca", baseaddr, DEV_DECCCA_LENGTH,
409 dev_deccca_access, d, DM_DEFAULT, NULL);
410 }
411
412
413 /*****************************************************************************/
414
415
416 /*
417 * DEC 5800 XMI (this has to do with SMP...)
418 */
419
420 #include "xmireg.h"
421
422 struct decxmi_data {
423 uint32_t reg_0xc[NNODEXMI];
424 };
425
426
427 /*
428 * dev_decxmi_access():
429 */
430 DEVICE_ACCESS(decxmi)
431 {
432 uint64_t idata = 0, odata = 0;
433 int node_nr;
434 struct decxmi_data *d = extra;
435
436 if (writeflag == MEM_WRITE)
437 idata = memory_readmax64(cpu, data, len);
438
439 node_nr = relative_addr / XMI_NODESIZE;
440 relative_addr &= (XMI_NODESIZE - 1);
441
442 if (node_nr >= cpu->machine->ncpus + 1 || node_nr >= NNODEXMI)
443 return 0;
444
445 switch (relative_addr) {
446 case XMI_TYPE:
447 if (writeflag == MEM_READ) {
448 /*
449 * The first node is an XMI->BI adapter node, and then
450 * there are n CPU nodes.
451 */
452 odata = XMIDT_ISIS;
453 if (node_nr == 0)
454 odata = XMIDT_DWMBA;
455
456 debug("[ decxmi: (node %i) read from XMI_TYPE: "
457 "0x%08x ]\n", node_nr, (int)odata);
458 } else
459 debug("[ decxmi: (node %i) write to XMI_TYPE: "
460 "0x%08x ]\n", node_nr, (int)idata);
461 break;
462 case XMI_BUSERR:
463 if (writeflag == MEM_READ) {
464 odata = 0;
465 debug("[ decxmi: (node %i) read from XMI_BUSERR: "
466 "0x%08x ]\n", node_nr, (int)odata);
467 } else
468 debug("[ decxmi: (node %i) write to XMI_BUSERR: "
469 "0x%08x ]\n", node_nr, (int)idata);
470 break;
471 case XMI_FAIL:
472 if (writeflag == MEM_READ) {
473 odata = 0;
474 debug("[ decxmi: (node %i) read from XMI_FAIL: "
475 "0x%08x ]\n", node_nr, (int)odata);
476 } else
477 debug("[ decxmi: (node %i) write to XMI_FAIL: "
478 "0x%08x ]\n", node_nr, (int)idata);
479 break;
480 case 0xc:
481 if (writeflag == MEM_READ) {
482 odata = d->reg_0xc[node_nr];
483 debug("[ decxmi: (node %i) read from REG 0xC: "
484 "0x%08x ]\n", node_nr, (int)odata);
485 } else {
486 d->reg_0xc[node_nr] = idata;
487 debug("[ decxmi: (node %i) write to REG 0xC: "
488 "0x%08x ]\n", node_nr, (int)idata);
489 }
490 break;
491 default:
492 if (writeflag==MEM_READ) {
493 debug("[ decxmi: (node %i) read from unimplemented "
494 "0x%08lx ]\n", node_nr, (long)relative_addr,
495 (int)odata);
496 } else {
497 debug("[ decxmi: (node %i) write to unimplemented "
498 "0x%08lx: 0x%08x ]\n", node_nr,
499 (long)relative_addr, (int)idata);
500 }
501 }
502
503 if (writeflag == MEM_READ)
504 memory_writemax64(cpu, data, len, odata);
505
506 return 1;
507 }
508
509
510 /*
511 * dev_decxmi_init():
512 */
513 void dev_decxmi_init(struct memory *mem, uint64_t baseaddr)
514 {
515 struct decxmi_data *d;
516
517 d = malloc(sizeof(struct decxmi_data));
518 if (d == NULL) {
519 fprintf(stderr, "out of memory\n");
520 exit(1);
521 }
522 memset(d, 0, sizeof(struct decxmi_data));
523
524 memory_device_register(mem, "decxmi", baseaddr, DEV_DECXMI_LENGTH,
525 dev_decxmi_access, d, DM_DEFAULT, NULL);
526 }
527

  ViewVC Help
Powered by ViewVC 1.1.26