1 /*
2  *  Copyright (C) 2007-2014  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: Peripheral Channel Controller (PCC2) bus (used in MVME machines)
29  *
30  *  See "Single Board Computers Programmer's Reference Guide (Part 2 of 2)",
31  *  "VMESBCA2/PG1" (vmesbcp2.pdf) for more details.
32  *
33  *  Note: This is somewhat MVME187-specific, at the moment.
34  *
35  *  Implemented so far:
36  *	Timers 1 and 2.
37  *	The interrupt controller mechanism (partially!)
38  *
39  *  TODO:
40  *	All devices appart from the timers.
41  */
42 
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46 
47 #include "cpu.h"
48 #include "device.h"
49 #include "emul.h"
50 #include "interrupt.h"
51 #include "machine.h"
52 #include "memory.h"
53 #include "misc.h"
54 
55 #include "thirdparty/mvme187.h"
56 #include "thirdparty/mvme_pcctworeg.h"
57 
58 
59 #define	INTERRUPT_LEVEL_MASK	0x07
60 
61 #define	PCC_TIMER_TICK_HZ	100.0
62 #define DEV_PCC2_TICK_SHIFT	14
63 
64 
65 // #define	debug fatal
66 
67 struct pcc2_data {
68 	struct interrupt	cpu_irq;
69 
70 	uint8_t			pcctwo_reg[PCC2_SIZE];
71 
72 	uint8_t			cur_int_vec[8];
73 
74 	/*  Timers:  */
75 	struct timer		*timer;
76 	int			pending_timer1_interrupts;
77 	int			pending_timer2_interrupts;
78 };
79 
80 
read32(unsigned char * p)81 static uint32_t read32(unsigned char *p)
82 {
83 	uint32_t x = 0;
84 	size_t i;
85 
86 	for (i=0; i<sizeof(x); i++) {
87 		x <<= 8;
88 		x |= p[i];
89 	}
90 
91 	return x;
92 }
93 
94 
write32(unsigned char * p,uint32_t x)95 static void write32(unsigned char *p, uint32_t x)
96 {
97 	size_t i;
98 
99 	for (i=0; i<sizeof(x); i++) {
100 		p[sizeof(x) - 1 - i] = x;
101 		x >>= 8;
102 	}
103 }
104 
105 
pcc_timer_tick(struct timer * t,void * extra)106 static void pcc_timer_tick(struct timer *t, void *extra)
107 {
108 	struct pcc2_data *d = (struct pcc2_data *) extra;
109 
110 	/*  The PCC2 timers run at 1 MHz.  */
111 	int steps = (int) (1000000.0 / PCC_TIMER_TICK_HZ);
112 
113 	uint32_t count1, count2, compare1, compare2;
114 	int interrupt1 = 0, interrupt2 = 0;
115 
116 	/*  Read values:  */
117 	count1 = read32(&d->pcctwo_reg[PCCTWO_T1COUNT]);
118 	count2 = read32(&d->pcctwo_reg[PCCTWO_T2COUNT]);
119 	compare1 = read32(&d->pcctwo_reg[PCCTWO_T1CMP]);
120 	compare2 = read32(&d->pcctwo_reg[PCCTWO_T2CMP]);
121 
122 	/*  Timer enabled? Then count...  */
123 	if (d->pcctwo_reg[PCCTWO_T1CTL] & PCC2_TCTL_CEN) {
124 		uint32_t old_count1 = count1;
125 		count1 += steps;
126 
127 		/*  Did we pass the compare value?  */
128 		if ((old_count1 < compare1 && count1 >= compare1) ||
129 		    (old_count1 < compare1 && count1 < old_count1)) {
130 			interrupt1 = 1;
131 
132 			if (d->pcctwo_reg[PCCTWO_T1CTL] & PCC2_TCTL_COC) {
133 				while (count1 >= compare1) {
134 					count1 -= compare1;
135 					interrupt1 ++;
136 				}
137 				interrupt1 --;
138 			}
139 		}
140 
141 		/*  Overflow?  */
142 		if ((int32_t) old_count1 >= 0 && (int32_t) count1 < 0) {
143 			int oc = 1 + (d->pcctwo_reg[PCCTWO_T1CTL] >> 4);
144 			d->pcctwo_reg[PCCTWO_T1CTL] &= ~PCC2_TCTL_OVF;
145 			d->pcctwo_reg[PCCTWO_T1CTL] |= (oc << 4);
146 		}
147 	}
148 
149 	/*  ... and the same for timer 2:  */
150 	if (d->pcctwo_reg[PCCTWO_T2CTL] & PCC2_TCTL_CEN) {
151 		uint32_t old_count2 = count2;
152 		count2 += steps;
153 
154 		if ((old_count2 < compare2 && count2 >= compare2) ||
155 		    (old_count2 < compare2 && count2 < old_count2)) {
156 			interrupt2 = 1;
157 			if (d->pcctwo_reg[PCCTWO_T2CTL] & PCC2_TCTL_COC) {
158 				while (count2 >= compare2) {
159 					count2 -= compare2;
160 					interrupt2 ++;
161 				}
162 				interrupt2 --;
163 			}
164 		}
165 
166 		if ((int32_t) old_count2 >= 0 && (int32_t) count2 < 0) {
167 			int oc = 1 + (d->pcctwo_reg[PCCTWO_T2CTL] >> 4);
168 			d->pcctwo_reg[PCCTWO_T2CTL] &= ~PCC2_TCTL_OVF;
169 			d->pcctwo_reg[PCCTWO_T2CTL] |= (oc << 4);
170 		}
171 	}
172 
173 	/*  Should we cause interrupts?  */
174 	if (interrupt1 && d->pcctwo_reg[PCCTWO_T1ICR] & PCC2_TTIRQ_IEN)
175 		d->pending_timer1_interrupts += interrupt1;
176 	if (interrupt2 && d->pcctwo_reg[PCCTWO_T2ICR] & PCC2_TTIRQ_IEN)
177 		d->pending_timer2_interrupts += interrupt2;
178 
179 	/*  Write back values:  */
180 	write32(&d->pcctwo_reg[PCCTWO_T1COUNT], count1);
181 	write32(&d->pcctwo_reg[PCCTWO_T2COUNT], count2);
182 }
183 
184 
reassert_interrupts(struct pcc2_data * d)185 static void reassert_interrupts(struct pcc2_data *d)
186 {
187 	int assert = 0;
188 
189 	if (d->pcctwo_reg[PCCTWO_GENCTL] & PCC2_C040) {
190 		/*  The M68000 interrupt mechanism involves outputting
191 		    interrupt level on pins EIPL<2..0>. Not implemented
192 		    yet.  */
193 		fatal("pcc2: C040 interrupt assertions... TODO\n");
194 		exit(1);
195 	}
196 
197 	/*
198 	 *  Recalculate current interrupt level:
199 	 */
200 	d->pcctwo_reg[PCCTWO_IPL] = 0;
201 
202 	/*  Timer interrupts?  */
203 	if (d->pending_timer1_interrupts > 0 &&
204 	    d->pcctwo_reg[PCCTWO_T1ICR] & PCC2_TTIRQ_IEN)
205 		d->pcctwo_reg[PCCTWO_T1ICR] |= PCC2_TTIRQ_INT;
206 	if (d->pending_timer2_interrupts > 0 &&
207 	    d->pcctwo_reg[PCCTWO_T2ICR] & PCC2_TTIRQ_IEN)
208 		d->pcctwo_reg[PCCTWO_T2ICR] |= PCC2_TTIRQ_INT;
209 
210 	if (d->pcctwo_reg[PCCTWO_T1ICR] & PCC2_TTIRQ_INT) {
211 		int intlevel = d->pcctwo_reg[PCCTWO_T1ICR] & PCC2_TTIRQ_IL;
212 		d->cur_int_vec[intlevel] = PCC2V_TIMER1;
213 		if (d->pcctwo_reg[PCCTWO_IPL] < intlevel)
214 			d->pcctwo_reg[PCCTWO_IPL] = intlevel;
215 	}
216 	if (d->pcctwo_reg[PCCTWO_T2ICR] & PCC2_TTIRQ_INT) {
217 		int intlevel = d->pcctwo_reg[PCCTWO_T2ICR] & PCC2_TTIRQ_IL;
218 		d->cur_int_vec[intlevel] = PCC2V_TIMER2;
219 		if (d->pcctwo_reg[PCCTWO_IPL] < intlevel)
220 			d->pcctwo_reg[PCCTWO_IPL] = intlevel;
221 	}
222 
223 	if (d->pcctwo_reg[PCCTWO_SCCTX] & PCC2_IRQ_IEN &&
224 	    d->pcctwo_reg[PCCTWO_SCCTX] & PCC2_IRQ_INT) {
225 		int intlevel = d->pcctwo_reg[PCCTWO_SCCTX] & PCC2_IRQ_IPL;
226 		d->cur_int_vec[intlevel] = PCC2V_SCC_TX;
227 		if (d->pcctwo_reg[PCCTWO_IPL] < intlevel)
228 			d->pcctwo_reg[PCCTWO_IPL] = intlevel;
229 	}
230 
231 	if (d->pcctwo_reg[PCCTWO_SCCRX] & PCC2_IRQ_IEN &&
232 	    d->pcctwo_reg[PCCTWO_SCCRX] & PCC2_IRQ_INT) {
233 		int intlevel = d->pcctwo_reg[PCCTWO_SCCRX] & PCC2_IRQ_IPL;
234 		d->cur_int_vec[intlevel] = PCC2V_SCC_RX;
235 		if (d->pcctwo_reg[PCCTWO_IPL] < intlevel)
236 			d->pcctwo_reg[PCCTWO_IPL] = intlevel;
237 	}
238 
239 	if (d->pcctwo_reg[PCCTWO_SCSIICR] & PCC2_IRQ_IEN &&
240 	    d->pcctwo_reg[PCCTWO_SCSIICR] & PCC2_IRQ_INT) {
241 		int intlevel = d->pcctwo_reg[PCCTWO_SCSIICR] & PCC2_IRQ_IPL;
242 		d->cur_int_vec[intlevel] = PCC2V_SCSI;
243 		if (d->pcctwo_reg[PCCTWO_IPL] < intlevel)
244 			d->pcctwo_reg[PCCTWO_IPL] = intlevel;
245 	}
246 
247 	/*  TODO: Other interrupt sources.  */
248 
249 	/*  Assert interrupt on the CPU if the IPL is higher than the mask:  */
250 	if ((d->pcctwo_reg[PCCTWO_IPL] & INTERRUPT_LEVEL_MASK) >
251 	    (d->pcctwo_reg[PCCTWO_MASK] & INTERRUPT_LEVEL_MASK))
252 		assert = 1;
253 
254 	debug("[ pcc2: IPL = %i, MASK = %i => %s ]\n", d->pcctwo_reg[PCCTWO_IPL]& INTERRUPT_LEVEL_MASK,
255 		d->pcctwo_reg[PCCTWO_MASK] & INTERRUPT_LEVEL_MASK,
256 		assert ? "ASSERT" : "no assert");
257 
258 	/*  ... but only allow interrupts if Master Interrupt Enable is on:  */
259 	if (!(d->pcctwo_reg[PCCTWO_GENCTL] & PCC2_MIEN))
260 		assert = 0;
261 
262 	if (assert)
263 		INTERRUPT_ASSERT(d->cpu_irq);
264 	else
265 		INTERRUPT_DEASSERT(d->cpu_irq);
266 }
267 
268 
pcctwo_interrupt_common(struct interrupt * interrupt,int assert)269 void pcctwo_interrupt_common(struct interrupt *interrupt, int assert)
270 {
271 	struct pcc2_data *d = (struct pcc2_data *) interrupt->extra;
272 
273 	switch (interrupt->line) {
274 
275 	case PCC2V_SCSI:
276 		if (assert)
277 			d->pcctwo_reg[PCCTWO_SCSIICR] |= PCC2_IRQ_INT;
278 		else
279 			d->pcctwo_reg[PCCTWO_SCSIICR] &= ~PCC2_IRQ_INT;
280 		break;
281 
282 	case PCC2V_SCC_TX:
283 		if (assert)
284 			d->pcctwo_reg[PCCTWO_SCCTX] |= PCC2_IRQ_INT;
285 		else
286 			d->pcctwo_reg[PCCTWO_SCCTX] &= ~PCC2_IRQ_INT;
287 		break;
288 
289 	case PCC2V_SCC_RX:
290 		if (assert)
291 			d->pcctwo_reg[PCCTWO_SCCRX] |= PCC2_IRQ_INT;
292 		else
293 			d->pcctwo_reg[PCCTWO_SCCRX] &= ~PCC2_IRQ_INT;
294 		break;
295 
296 	default:fatal("[ pcctwo_interrupt_common: TODO: line = %i ]\n",
297 		    interrupt->line);
298 		exit(1);
299 	}
300 
301 	reassert_interrupts(d);
302 }
303 
304 
pcctwo_interrupt_assert(struct interrupt * interrupt)305 static void pcctwo_interrupt_assert(struct interrupt *interrupt)
306 {
307 	pcctwo_interrupt_common(interrupt, 1);
308 }
pcctwo_interrupt_deassert(struct interrupt * interrupt)309 static void pcctwo_interrupt_deassert(struct interrupt *interrupt)
310 {
311 	pcctwo_interrupt_common(interrupt, 0);
312 }
313 
314 
DEVICE_TICK(pcc2)315 DEVICE_TICK(pcc2)
316 {
317 	struct pcc2_data *d = (struct pcc2_data *) extra;
318 	reassert_interrupts(d);
319 }
320 
321 
DEVICE_ACCESS(pcc2)322 DEVICE_ACCESS(pcc2)
323 {
324 	uint64_t idata = 0;
325 	struct pcc2_data *d = (struct pcc2_data *) extra;
326 
327 	/*  0xfff42000..0xfff42fff, but only 0x40 unique registers:  */
328 	relative_addr %= PCC2_SIZE;
329 
330 	if (writeflag == MEM_WRITE)
331 		idata = memory_readmax64(cpu, data, len);
332 
333 	if (writeflag == MEM_READ)
334 		memcpy(data, d->pcctwo_reg + relative_addr, len);
335 
336 	switch (relative_addr) {
337 
338 	case PCCTWO_CHIPID:
339 	case PCCTWO_CHIPREV:
340 		if (writeflag == MEM_WRITE) {
341 			fatal("[ IGNORING write to read-only PCCTWO_CHIPID/"
342 			    "CHIPREV register ]\n");
343 		}
344 		break;
345 
346 	case PCCTWO_GENCTL:
347 		if (len != 1) {
348 			fatal("TODO: pcc2: non-byte reads and writes of "
349 			    "PCCTWO_GENCTL\n");
350 			exit(1);
351 		}
352 		if (writeflag == MEM_WRITE) {
353 			d->pcctwo_reg[relative_addr] = idata;
354 			reassert_interrupts(d);
355 		}
356 		break;
357 
358 	case PCCTWO_VECBASE:
359 		if (len != 1) {
360 			fatal("TODO: pcc2: non-byte reads and writes of "
361 			    "PCCTWO_VECBASE\n");
362 			exit(1);
363 		}
364 		if (writeflag == MEM_WRITE) {
365 			d->pcctwo_reg[relative_addr] = idata & 0xf0;
366 			if (idata & ~0xf0)
367 				fatal("[ pcc2: HUH? write to PCCTWO_VECBASE"
368 				    " with value 0x%02x. ]\n", (int) idata);
369 		}
370 		break;
371 
372 	case PCCTWO_T1CMP:
373 	case PCCTWO_T2CMP:
374 	case PCCTWO_T1COUNT:
375 	case PCCTWO_T2COUNT:
376 		if (writeflag == MEM_WRITE)
377 			memcpy(d->pcctwo_reg + relative_addr, data, len);
378 		break;
379 
380 	case PCCTWO_PSCALEADJ:
381 		if (len != 1) {
382 			fatal("TODO: pcc2: non-byte reads and writes of "
383 			    "PCCTWO_PSCALEADJ\n");
384 			exit(1);
385 		}
386 		if (writeflag == MEM_WRITE) {
387 			fatal("[ pcc2: write to PSCALEADJ ignored (value "
388 			    "0x%02x) ]\n", (int)idata);
389 		}
390 		break;
391 
392 	case PCCTWO_T2CTL:
393 	case PCCTWO_T1CTL:
394 		if (len != 1) {
395 			fatal("TODO: pcc2: non-byte reads and writes of "
396 			    "PCCTWO_TxCTL\n");
397 			exit(1);
398 		}
399 		if (writeflag == MEM_WRITE) {
400 			/*  PCC2_TCTL_CEN and PCC2_TCTL_COC:  */
401 			d->pcctwo_reg[relative_addr] &= 0xfc;
402 			d->pcctwo_reg[relative_addr] |= (idata & 3);
403 
404 			if (idata & PCC2_TCTL_COVF)
405 				d->pcctwo_reg[relative_addr] &=
406 				    ~(PCC2_TCTL_OVF | PCC2_TCTL_COVF);
407 
408 			if (idata & ~7)
409 				fatal("[ pcc2: HUH? write to PCCTWO_TxCTL"
410 				    " with value 0x%02x. ]\n", (int) idata);
411 		}
412 		break;
413 
414 	case PCCTWO_T2ICR:
415 	case PCCTWO_T1ICR:
416 		if (len != 1) {
417 			fatal("TODO: pcc2: non-byte reads and writes of "
418 			    "PCCTWO_TxICR\n");
419 			exit(1);
420 		}
421 		if (writeflag == MEM_WRITE) {
422 			d->pcctwo_reg[relative_addr] &= ~0x17;
423 			d->pcctwo_reg[relative_addr] |= (idata & 0x17);
424 
425 			if (relative_addr == PCCTWO_T1ICR &&
426 			    !(idata & PCC2_TTIRQ_IEN))
427 				d->pending_timer1_interrupts = 0;
428 			if (relative_addr == PCCTWO_T2ICR &&
429 			    !(idata & PCC2_TTIRQ_IEN))
430 				d->pending_timer2_interrupts = 0;
431 
432 			if (relative_addr == PCCTWO_T1ICR && (idata & PCC2_TTIRQ_ICLR)
433 			    && d->pcctwo_reg[relative_addr] & PCC2_TTIRQ_INT
434 			    && d->pending_timer1_interrupts > 0)
435 				d->pending_timer1_interrupts --;
436 
437 			if (relative_addr == PCCTWO_T2ICR && (idata & PCC2_TTIRQ_ICLR)
438 			    && d->pcctwo_reg[relative_addr] & PCC2_TTIRQ_INT
439 			    && d->pending_timer2_interrupts > 0)
440 				d->pending_timer2_interrupts --;
441 
442 			if (idata & PCC2_TTIRQ_ICLR)
443 				d->pcctwo_reg[relative_addr] &= ~PCC2_TTIRQ_INT;
444 
445 			if (idata & 0xe0)
446 				fatal("[ pcc2: HUH? write to PCCTWO_TxICR"
447 				    " with value 0x%02x. ]\n", (int) idata);
448 
449 			reassert_interrupts(d);
450 		}
451 		break;
452 
453 	case PCCTWO_SCCERR:
454 		if (len != 1) {
455 			fatal("TODO: pcc2: non-byte reads and writes of "
456 			    "PCCTWO_SCCERR\n");
457 			exit(1);
458 		}
459 		if (writeflag == MEM_WRITE)
460 			d->pcctwo_reg[relative_addr] = 0;	/*  clear  */
461 		break;
462 
463 	case PCCTWO_SCCICR:
464 		if (len != 1) {
465 			fatal("TODO: pcc2: non-byte reads and writes of "
466 			    "PCCTWO_SCCICR\n");
467 			exit(1);
468 		}
469 		if (writeflag == MEM_WRITE) {
470 			d->pcctwo_reg[relative_addr] = idata & 0x1f;
471 			if (idata & ~0x1f)
472 				fatal("[ pcc2: HUH? write to PCCTWO_SCCICR"
473 				    " with value 0x%02x. ]\n", (int) idata);
474 			reassert_interrupts(d);
475 		}
476 		break;
477 
478 	case PCCTWO_SCCTX:
479 		if (len != 1) {
480 			fatal("TODO: pcc2: non-byte reads and writes of "
481 			    "PCCTWO_SCCTX\n");
482 			exit(1);
483 		}
484 		if (writeflag == MEM_WRITE) {
485 			d->pcctwo_reg[relative_addr] = idata & 0x1f;
486 			if (idata & ~0x1f)
487 				fatal("[ pcc2: HUH? write to PCCTWO_SCCTX"
488 				    " with value 0x%02x. ]\n", (int) idata);
489 			reassert_interrupts(d);
490 		}
491 		break;
492 
493 	case PCCTWO_SCCRX:
494 		if (len != 1) {
495 			fatal("TODO: pcc2: non-byte reads and writes of "
496 			    "PCCTWO_SCCRX\n");
497 			exit(1);
498 		}
499 		if (writeflag == MEM_WRITE) {
500 			d->pcctwo_reg[relative_addr] = idata & 0xdf;
501 			if (idata & ~0xdf)
502 				fatal("[ pcc2: HUH? write to PCCTWO_SCCRX"
503 				    " with value 0x%02x. ]\n", (int) idata);
504 			reassert_interrupts(d);
505 		}
506 		break;
507 
508 	case PCCTWO_SCCRXIACK:
509 		/*  TODO. Hm. Is this enough?  */
510 		d->pcctwo_reg[PCCTWO_SCCRX] &= ~PCC2_IRQ_INT;
511 		reassert_interrupts(d);
512 		break;
513 
514 	case PCCTWO_SCSIICR:
515 		if (len != 1) {
516 			fatal("TODO: pcc2: non-byte reads and writes of "
517 			    "PCCTWO_SCSIICR\n");
518 			exit(1);
519 		}
520 		if (writeflag == MEM_WRITE) {
521 			d->pcctwo_reg[relative_addr] = idata & 0xdf;
522 			if (idata & ~0xdf)
523 				fatal("[ pcc2: HUH? write to PCCTWO_SCSIICR"
524 				    " with value 0x%02x. ]\n", (int) idata);
525 			reassert_interrupts(d);
526 		}
527 		break;
528 
529 	case PCCTWO_IPL:
530 		if (len != 1) {
531 			fatal("TODO: pcc2: non-byte reads and writes of "
532 			    "PCCTWO_IPL\n");
533 			exit(1);
534 		}
535 		if (writeflag == MEM_WRITE) {
536 			fatal("[ pcc2: HUH? Write attempt to PCCTWO_IPL. ]\n");
537 			exit(1);
538 		} else {
539 			if (d->pcctwo_reg[PCCTWO_IPL] == 0) {
540 				fatal("pcc2: IPL == 0 on read!\n");
541 				exit(1);
542 			}
543 		}
544 		break;
545 
546 	case PCCTWO_MASK:
547 		if (len != 1) {
548 			fatal("TODO: pcc2: non-byte reads and writes of "
549 			    "PCCTWO_MASK\n");
550 			exit(1);
551 		}
552 		if (writeflag == MEM_WRITE) {
553 			d->pcctwo_reg[relative_addr] = idata;
554 			reassert_interrupts(d);
555 		}
556 		break;
557 
558 	default:
559 		debug("[ pcc2: unimplemented %s offset 0x%x",
560 		    writeflag == MEM_WRITE? "write to" : "read from",
561 		    (int) relative_addr);
562 		if (writeflag == MEM_WRITE)
563 			debug(": 0x%x", (int)idata);
564 		debug(" ]\n");
565 		exit(1);
566 	}
567 
568 	return 1;
569 }
570 
571 
DEVICE_ACCESS(mvme187_iack)572 DEVICE_ACCESS(mvme187_iack)
573 {
574 	uint64_t odata = 0;
575 	struct pcc2_data *d = (struct pcc2_data *) extra;
576 
577 	if (writeflag == MEM_WRITE) {
578 		fatal("[ pcc2: write to mvme187_iack? ]\n");
579 	} else {
580 		odata = d->pcctwo_reg[PCCTWO_VECBASE] + d->cur_int_vec[
581 		    (relative_addr >> 2) & INTERRUPT_LEVEL_MASK];
582 		debug("[ pcc2: mvme187_iack level %i => vector 0x%02x ]\n",
583 		    (int)(relative_addr >> 2), (int)odata);
584 
585 		memory_writemax64(cpu, data, len, odata);
586 	}
587 
588 	return 1;
589 }
590 
591 
DEVINIT(pcc2)592 DEVINIT(pcc2)
593 {
594 	struct pcc2_data *d;
595 	int i;
596 
597 	CHECK_ALLOCATION(d = (struct pcc2_data *) malloc(sizeof(struct pcc2_data)));
598 	memset(d, 0, sizeof(struct pcc2_data));
599 
600 	/*
601 	 *  Initial values, according to the manual:
602 	 *
603 	 *  VECBASE is 0x0f after a reset, although the lowest four bits
604 	 *  cannot be manually written to after startup.
605 	 */
606 	d->pcctwo_reg[PCCTWO_CHIPID] = PCC2_ID;
607 	d->pcctwo_reg[PCCTWO_CHIPREV] = 0x00;
608 	d->pcctwo_reg[PCCTWO_GENCTL] = 0x00;
609 	d->pcctwo_reg[PCCTWO_VECBASE] = 0x0f;
610 	d->pcctwo_reg[PCCTWO_PSCALEADJ] = 256 - 33;	// 256 - MHz (fake)
611 
612 	/*  Connect to the CPU's interrupt pin:  */
613 	INTERRUPT_CONNECT(devinit->interrupt_path, d->cpu_irq);
614 
615 	/*
616 	 *  Register the 16 PCC2 interrupt vectors:
617 	 */
618 	for (i=0; i<16; i++) {
619 		struct interrupt templ;
620 		char n[300];
621 		snprintf(n, sizeof(n), "%s.pcc2.%i",
622 		    devinit->interrupt_path, i);
623 
624 		memset(&templ, 0, sizeof(templ));
625 		templ.line = i;
626 		templ.name = n;
627 		templ.extra = d;
628 		templ.interrupt_assert = pcctwo_interrupt_assert;
629 		templ.interrupt_deassert = pcctwo_interrupt_deassert;
630 
631 		interrupt_handler_register(&templ);
632 	}
633 
634 	memory_device_register(devinit->machine->memory, "pcc2",
635 	    devinit->addr, 4096, dev_pcc2_access, (void *)d,
636 	    DM_DEFAULT, NULL);
637 
638 	memory_device_register(devinit->machine->memory, "mvme187_iack",
639 	    M187_IACK, 32, dev_mvme187_iack_access, (void *)d,
640 	    DM_DEFAULT, NULL);
641 
642 	d->timer = timer_add(PCC_TIMER_TICK_HZ, pcc_timer_tick, d);
643 
644 	machine_add_tickfunction(devinit->machine,
645 	    dev_pcc2_tick, d, DEV_PCC2_TICK_SHIFT);
646 
647 	return 1;
648 }
649 
650