dev_dec5800.cc Source File

Back to the index.

dev_dec5800.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2003-2009 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  * COMMENT: DECsystem 58x0 devices
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;
61 
62  uint32_t vector_0x50;
63 
65 };
66 
67 
69 {
70  struct dec5800_data *d = (struct dec5800_data *) interrupt->extra;
71  d->csr |= (1 << interrupt->line);
72  if (d->csr & 0x10000000)
74 }
76 {
77  struct dec5800_data *d = (struct dec5800_data *) interrupt->extra;
78  d->csr &= ~(1 << interrupt->line);
79  if (!(d->csr & 0x10000000))
81 }
82 
83 
84 DEVICE_TICK(dec5800)
85 {
86  struct dec5800_data *d = (struct dec5800_data *) 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 
96  }
97 }
98 
99 
100 DEVICE_ACCESS(dec5800_vectors)
101 {
102  uint64_t idata = 0, odata = 0;
103  struct dec5800_data *d = (struct dec5800_data *) 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 
130 {
131  uint64_t idata = 0, odata = 0;
132  struct dec5800_data *d = (struct dec5800_data *) 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;
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  CHECK_ALLOCATION(d = (struct dec5800_data *) malloc(sizeof(struct dec5800_data)));
182  memset(d, 0, sizeof(struct dec5800_data));
183 
184  snprintf(tmpstr, sizeof(tmpstr), "%s.2", devinit->interrupt_path);
185  INTERRUPT_CONNECT(tmpstr, d->cpu_irq);
186 
187  snprintf(tmpstr, sizeof(tmpstr), "%s.3", devinit->interrupt_path);
188  INTERRUPT_CONNECT(tmpstr, d->timer_irq);
189 
190  /* Register 32 CSR interrupts, corresponding to bits in the CSR: */
191  for (i=0; i<32; i++) {
192  char n[200];
193  struct interrupt templ;
194  snprintf(n, sizeof(n), "%s.dec5800.%i",
195  devinit->interrupt_path, i);
196  memset(&templ, 0, sizeof(templ));
197  templ.line = i;
198  templ.name = n;
199  templ.extra = d;
203  }
204 
206  devinit->addr, DEV_DEC5800_LENGTH, dev_dec5800_access,
207  d, DM_DEFAULT, NULL);
208  memory_device_register(devinit->machine->memory, "dec5800_vectors",
209  devinit->addr + 0x30000000, 0x100, dev_dec5800_vectors_access,
210  d, DM_DEFAULT, NULL);
211  machine_add_tickfunction(devinit->machine, dev_dec5800_tick,
212  d, 14);
213 
214  return 1;
215 }
216 
217 
218 /*****************************************************************************/
219 
220 
221 #include "thirdparty/bireg.h"
222 
223 /* 16 slots, 0x2000 bytes each */
224 #define DEV_DECBI_LENGTH 0x20000
225 
226 struct decbi_data {
227  int csr[NNODEBI];
228 };
229 
230 
232 {
233  uint64_t idata = 0, odata = 0;
234  int node_nr;
235  struct decbi_data *d = (struct decbi_data *) extra;
236 
237  if (writeflag == MEM_WRITE)
238  idata = memory_readmax64(cpu, data, len);
239 
240  relative_addr += BI_NODESIZE; /* HACK */
241 
242  node_nr = relative_addr / BI_NODESIZE;
243  relative_addr &= (BI_NODESIZE - 1);
244 
245  /* TODO: This "1" here is the max node number in actual use. */
246  if (node_nr > 1 || node_nr >= NNODEBI)
247  return 0;
248 
249  switch (relative_addr) {
250  case BIREG_DTYPE:
251  if (writeflag==MEM_READ) {
252  /*
253  * This is a list of the devices in our BI slots:
254  */
255  switch (node_nr) {
256  case 1: odata = BIDT_KDB50; break; /* Disk */
257  /* case 2: odata = BIDT_DEBNA; break; */
258  /* BIDT_DEBNA = Ethernet */
259  /* case 3: odata = BIDT_MS820; break; */
260  /* BIDT_MS820 = Memory */
261  default:
262  /* No device. */
263  odata = 0;
264  }
265 
266  debug("[ decbi: (node %i) read from BIREG_DTYPE:"
267  " 0x%x ]\n", node_nr, (int)odata);
268  } else {
269  debug("[ decbi: (node %i) attempt to write to "
270  "BIREG_DTYPE: 0x%08x ]\n", node_nr, (int)idata);
271  }
272  break;
273  case BIREG_VAXBICSR:
274  if (writeflag==MEM_READ) {
275  odata = (d->csr[node_nr] & ~BICSR_NODEMASK) | node_nr;
276  debug("[ decbi: (node %i) read from BIREG_"
277  "VAXBICSR: 0x%x ]\n", node_nr, (int)odata);
278  } else {
279  d->csr[node_nr] = idata;
280  debug("[ decbi: (node %i) attempt to write to "
281  "BIREG_VAXBICSR: 0x%08x ]\n", node_nr, (int)idata);
282  }
283  break;
284  case 0xf4:
285  if (writeflag==MEM_READ) {
286  odata = 0xffff; /* ? */
287  debug("[ decbi: (node %i) read from 0xf4: "
288  "0x%x ]\n", node_nr, (int)odata);
289  } else {
290  debug("[ decbi: (node %i) attempt to write "
291  "to 0xf4: 0x%08x ]\n", node_nr, (int)idata);
292  }
293  break;
294  default:
295  if (writeflag==MEM_READ) {
296  debug("[ decbi: (node %i) read from unimplemented "
297  "0x%08lx ]\n", node_nr, (long)relative_addr,
298  (int)odata);
299  } else {
300  debug("[ decbi: (node %i) write to unimplemented "
301  "0x%08lx: 0x%08x ]\n", node_nr,
302  (long)relative_addr, (int)idata);
303  }
304  }
305 
306  if (writeflag == MEM_READ)
307  memory_writemax64(cpu, data, len, odata);
308 
309  return 1;
310 }
311 
312 
313 DEVINIT(decbi)
314 {
315  struct decbi_data *d;
316 
317  CHECK_ALLOCATION(d = (struct decbi_data *) malloc(sizeof(struct decbi_data)));
318  memset(d, 0, sizeof(struct decbi_data));
319 
321  devinit->addr + 0x2000, DEV_DECBI_LENGTH - 0x2000,
322  dev_decbi_access, d, DM_DEFAULT, NULL);
323 
324  return 1;
325 }
326 
327 
328 /*****************************************************************************/
329 
330 
331 /*
332  * CCA, "Console Communication Area" for a DEC 5800 SMP system.
333  */
334 
335 struct deccca_data {
336  int dummy;
337 };
338 
339 
341 {
342  uint64_t idata = 0, odata = 0;
343  /* struct deccca_data *d = extra; */
344 
345  if (writeflag == MEM_WRITE)
346  idata = memory_readmax64(cpu, data, len);
347 
348  switch (relative_addr) {
349  case 6:
350  case 7:
351  /* CCA "ID" bytes? These must be here, or Ultrix complains. */
352  if (writeflag == MEM_READ)
353  odata = 67;
354  break;
355  case 8:
356  if (writeflag == MEM_READ)
357  odata = cpu->machine->ncpus;
358  break;
359  case 20:
360  if (writeflag == MEM_READ)
361  odata = (1 << cpu->machine->ncpus) - 1;
362  /* one bit for each cpu */
363  break;
364  case 28:
365  if (writeflag == MEM_READ)
366  odata = (1 << cpu->machine->ncpus) - 1;
367  /* one bit for each enabled(?) cpu */
368  break;
369  default:
370  if (writeflag==MEM_READ) {
371  debug("[ deccca: read from 0x%08lx ]\n",
372  (long)relative_addr);
373  } else {
374  debug("[ deccca: write to 0x%08lx: 0x%08x ]\n",
375  (long)relative_addr, (int)idata);
376  }
377  }
378 
379  if (writeflag == MEM_READ)
380  memory_writemax64(cpu, data, len, odata);
381 
382  return 1;
383 }
384 
385 
386 /*
387  * dev_deccca_init():
388  */
389 void dev_deccca_init(struct memory *mem, uint64_t baseaddr)
390 {
391  struct deccca_data *d;
392 
393  CHECK_ALLOCATION(d = (struct deccca_data *) malloc(sizeof(struct deccca_data)));
394  memset(d, 0, sizeof(struct deccca_data));
395 
396  memory_device_register(mem, "deccca", baseaddr, DEV_DECCCA_LENGTH,
397  dev_deccca_access, d, DM_DEFAULT, NULL);
398 }
399 
400 
401 /*****************************************************************************/
402 
403 
404 /*
405  * DEC 5800 XMI (this has to do with SMP...)
406  */
407 
408 #include "thirdparty/xmireg.h"
409 
410 struct decxmi_data {
411  uint32_t reg_0xc[NNODEXMI];
412 };
413 
414 
415 /*
416  * dev_decxmi_access():
417  */
419 {
420  uint64_t idata = 0, odata = 0;
421  int node_nr;
422  struct decxmi_data *d = (struct decxmi_data *) extra;
423 
424  if (writeflag == MEM_WRITE)
425  idata = memory_readmax64(cpu, data, len);
426 
427  node_nr = relative_addr / XMI_NODESIZE;
428  relative_addr &= (XMI_NODESIZE - 1);
429 
430  if (node_nr >= cpu->machine->ncpus + 1 || node_nr >= NNODEXMI)
431  return 0;
432 
433  switch (relative_addr) {
434  case XMI_TYPE:
435  if (writeflag == MEM_READ) {
436  /*
437  * The first node is an XMI->BI adapter node, and then
438  * there are n CPU nodes.
439  */
440  odata = XMIDT_ISIS;
441  if (node_nr == 0)
442  odata = XMIDT_DWMBA;
443 
444  debug("[ decxmi: (node %i) read from XMI_TYPE: "
445  "0x%08x ]\n", node_nr, (int)odata);
446  } else
447  debug("[ decxmi: (node %i) write to XMI_TYPE: "
448  "0x%08x ]\n", node_nr, (int)idata);
449  break;
450  case XMI_BUSERR:
451  if (writeflag == MEM_READ) {
452  odata = 0;
453  debug("[ decxmi: (node %i) read from XMI_BUSERR: "
454  "0x%08x ]\n", node_nr, (int)odata);
455  } else
456  debug("[ decxmi: (node %i) write to XMI_BUSERR: "
457  "0x%08x ]\n", node_nr, (int)idata);
458  break;
459  case XMI_FAIL:
460  if (writeflag == MEM_READ) {
461  odata = 0;
462  debug("[ decxmi: (node %i) read from XMI_FAIL: "
463  "0x%08x ]\n", node_nr, (int)odata);
464  } else
465  debug("[ decxmi: (node %i) write to XMI_FAIL: "
466  "0x%08x ]\n", node_nr, (int)idata);
467  break;
468  case 0xc:
469  if (writeflag == MEM_READ) {
470  odata = d->reg_0xc[node_nr];
471  debug("[ decxmi: (node %i) read from REG 0xC: "
472  "0x%08x ]\n", node_nr, (int)odata);
473  } else {
474  d->reg_0xc[node_nr] = idata;
475  debug("[ decxmi: (node %i) write to REG 0xC: "
476  "0x%08x ]\n", node_nr, (int)idata);
477  }
478  break;
479  default:
480  if (writeflag==MEM_READ) {
481  debug("[ decxmi: (node %i) read from unimplemented "
482  "0x%08lx ]\n", node_nr, (long)relative_addr,
483  (int)odata);
484  } else {
485  debug("[ decxmi: (node %i) write to unimplemented "
486  "0x%08lx: 0x%08x ]\n", node_nr,
487  (long)relative_addr, (int)idata);
488  }
489  }
490 
491  if (writeflag == MEM_READ)
492  memory_writemax64(cpu, data, len, odata);
493 
494  return 1;
495 }
496 
497 
498 /*
499  * dev_decxmi_init():
500  */
501 void dev_decxmi_init(struct memory *mem, uint64_t baseaddr)
502 {
503  struct decxmi_data *d;
504 
505  CHECK_ALLOCATION(d = (struct decxmi_data *) malloc(sizeof(struct decxmi_data)));
506  memset(d, 0, sizeof(struct decxmi_data));
507 
508  memory_device_register(mem, "decxmi", baseaddr, DEV_DECXMI_LENGTH,
509  dev_decxmi_access, d, DM_DEFAULT, NULL);
510 }
511 
uint64_t memory_readmax64(struct cpu *cpu, unsigned char *buf, int len)
Definition: memory.cc:55
DEVINIT(dec5800)
Definition: dev_dec5800.cc:175
struct interrupt timer_irq
Definition: dev_dec5800.cc:64
void(* interrupt_assert)(struct interrupt *)
Definition: interrupt.h:38
#define DM_DEFAULT
Definition: memory.h:130
#define BIREG_VAXBICSR
Definition: bireg.h:111
#define DEV_DEC5800_LENGTH
Definition: dev_dec5800.cc:56
#define XMI_FAIL
Definition: xmireg.h:47
#define XMI_NODESIZE
Definition: xmireg.h:40
struct machine * machine
Definition: cpu.h:328
void interrupt_handler_register(struct interrupt *templ)
Definition: interrupt.cc:81
#define MEM_READ
Definition: memory.h:116
void(* interrupt_deassert)(struct interrupt *)
Definition: interrupt.h:39
struct memory * memory
Definition: machine.h:126
int dev_deccca_access(struct cpu *cpu, struct memory *mem, uint64_t relative_addr, unsigned char *data, size_t len, int writeflag, void *)
DEVICE_ACCESS(dec5800_vectors)
Definition: dev_dec5800.cc:100
void dec5800_interrupt_deassert(struct interrupt *interrupt)
Definition: dev_dec5800.cc:75
void dev_deccca_init(struct memory *mem, uint64_t baseaddr)
Definition: dev_dec5800.cc:389
int ncpus
Definition: machine.h:139
#define XMIDT_DWMBA
Definition: xmireg.h:56
#define CHECK_ALLOCATION(ptr)
Definition: misc.h:239
struct interrupt cpu_irq
Definition: dev_dec5800.cc:60
#define BIDT_KDB50
Definition: bireg.h:142
uint32_t vector_0x50
Definition: dev_dec5800.cc:62
#define XMIDT_ISIS
Definition: xmireg.h:54
#define XMI_TYPE
Definition: xmireg.h:45
u_short data
Definition: siireg.h:79
DEVICE_TICK(dec5800)
Definition: dev_dec5800.cc:84
#define INTERRUPT_ASSERT(istruct)
Definition: interrupt.h:74
#define MEM_WRITE
Definition: memory.h:117
#define NNODEBI
Definition: bireg.h:55
Definition: device.h:40
void dec5800_interrupt_assert(struct interrupt *interrupt)
Definition: dev_dec5800.cc:68
#define debug
Definition: dev_adb.cc:57
int cpu_id
Definition: cpu.h:359
uint32_t line
Definition: interrupt.h:51
#define INTERRUPT_CONNECT(name, istruct)
Definition: interrupt.h:77
Definition: cpu.h:326
struct machine * machine
Definition: device.h:41
#define BIREG_DTYPE
Definition: bireg.h:110
char * name
Definition: interrupt.h:66
#define DEV_DECBI_LENGTH
Definition: dev_dec5800.cc:224
#define DEV_DECXMI_LENGTH
Definition: devices.h:181
void memory_writemax64(struct cpu *cpu, unsigned char *buf, int len, uint64_t data)
Definition: memory.cc:89
#define DEV_DECCCA_LENGTH
Definition: devices.h:177
void memory_device_register(struct memory *mem, const char *, uint64_t baseaddr, uint64_t len, int(*f)(struct cpu *, struct memory *, uint64_t, unsigned char *, size_t, int, void *), void *extra, int flags, unsigned char *dyntrans_data)
Definition: memory.cc:339
#define XMI_BUSERR
Definition: xmireg.h:46
#define NNODEXMI
Definition: xmireg.h:42
#define BICSR_NODEMASK
Definition: bireg.h:165
Definition: memory.h:75
uint64_t addr
Definition: device.h:46
void machine_add_tickfunction(struct machine *machine, void(*func)(struct cpu *, void *), void *extra, int clockshift)
Definition: machine.cc:280
uint32_t csr
Definition: dev_dec5800.cc:59
void * extra
Definition: interrupt.h:59
uint32_t reg_0xc[NNODEXMI]
Definition: dev_dec5800.cc:411
void dev_decxmi_init(struct memory *mem, uint64_t baseaddr)
Definition: dev_dec5800.cc:501
int dev_decxmi_access(struct cpu *cpu, struct memory *mem, uint64_t relative_addr, unsigned char *data, size_t len, int writeflag, void *)
#define BI_NODESIZE
Definition: bireg.h:51
char * interrupt_path
Definition: device.h:50
#define INTERRUPT_DEASSERT(istruct)
Definition: interrupt.h:75
int csr[NNODEBI]
Definition: dev_dec5800.cc:227

Generated on Sun Sep 30 2018 16:05:18 for GXemul by doxygen 1.8.13