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;
60 	struct interrupt cpu_irq;
61 
62 	uint32_t	vector_0x50;
63 
64 	struct interrupt timer_irq;
65 };
66 
67 
dec5800_interrupt_assert(struct interrupt * interrupt)68 void dec5800_interrupt_assert(struct interrupt *interrupt)
69 {
70 	struct dec5800_data *d = (struct dec5800_data *) interrupt->extra;
71 	d->csr |= (1 << interrupt->line);
72 	if (d->csr & 0x10000000)
73 		INTERRUPT_ASSERT(d->cpu_irq);
74 }
dec5800_interrupt_deassert(struct interrupt * interrupt)75 void dec5800_interrupt_deassert(struct interrupt *interrupt)
76 {
77 	struct dec5800_data *d = (struct dec5800_data *) interrupt->extra;
78 	d->csr &= ~(1 << interrupt->line);
79 	if (!(d->csr & 0x10000000))
80 		INTERRUPT_DEASSERT(d->cpu_irq);
81 }
82 
83 
DEVICE_TICK(dec5800)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 
95 		INTERRUPT_ASSERT(d->timer_irq);
96 	}
97 }
98 
99 
DEVICE_ACCESS(dec5800_vectors)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 
DEVICE_ACCESS(dec5800)129 DEVICE_ACCESS(dec5800)
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;
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 
DEVINIT(dec5800)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;
200 		templ.interrupt_assert = dec5800_interrupt_assert;
201 		templ.interrupt_deassert = dec5800_interrupt_deassert;
202 		interrupt_handler_register(&templ);
203 	}
204 
205 	memory_device_register(devinit->machine->memory, "dec5800",
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 
DEVICE_ACCESS(decbi)231 DEVICE_ACCESS(decbi)
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 
DEVINIT(decbi)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 
320 	memory_device_register(devinit->machine->memory, "decbi",
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 
DEVICE_ACCESS(deccca)340 DEVICE_ACCESS(deccca)
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  */
dev_deccca_init(struct memory * mem,uint64_t baseaddr)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  */
DEVICE_ACCESS(decxmi)418 DEVICE_ACCESS(decxmi)
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  */
dev_decxmi_init(struct memory * mem,uint64_t baseaddr)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 
512