|
|
1.1.1.3 root 1: /* $Id: sun3-mainbus.c,v 1.7 2009/08/30 14:17:53 fredette Exp $ */
1.1 root 2:
3: /* machine/sun3/sun3-mainbus.c - implementation of Sun 3 emulation: */
4:
5: /*
6: * Copyright (c) 2003, 2004 Matt Fredette
7: * All rights reserved.
8: *
9: * Redistribution and use in source and binary forms, with or without
10: * modification, are permitted provided that the following conditions
11: * are met:
12: * 1. Redistributions of source code must retain the above copyright
13: * notice, this list of conditions and the following disclaimer.
14: * 2. Redistributions in binary form must reproduce the above copyright
15: * notice, this list of conditions and the following disclaimer in the
16: * documentation and/or other materials provided with the distribution.
17: * 3. All advertising materials mentioning features or use of this software
18: * must display the following acknowledgement:
19: * This product includes software developed by Matt Fredette.
20: * 4. The name of the author may not be used to endorse or promote products
21: * derived from this software without specific prior written permission.
22: *
23: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26: * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
27: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
31: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32: * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33: * POSSIBILITY OF SUCH DAMAGE.
34: */
35:
36: #include <tme/common.h>
1.1.1.3 root 37: _TME_RCSID("$Id: sun3-mainbus.c,v 1.7 2009/08/30 14:17:53 fredette Exp $");
1.1 root 38:
39: /* includes: */
40: #include "sun3-impl.h"
41: #include <tme/ic/z8530.h>
42: #include <tme/ic/isil7170.h>
43: #include <stdio.h>
44:
45: /* macros: */
46: #define TME_BUS_SIGNAL_INT_CLOCK TME_BUS_SIGNAL_INT(8)
47:
48: /* this possibly updates that the interrupt priority level driven to the CPU: */
49: int
50: _tme_sun3_ipl_check(struct tme_sun3 *sun3)
51: {
52: tme_uint8_t interreg;
53: unsigned int ipl, ipl_index;
54: tme_uint8_t ipl_mask;
55:
56: /* get the interrupt register: */
57: interreg = sun3->tme_sun3_ints;
58:
59: /* assume that interrupts are completely masked: */
60: ipl = TME_M68K_IPL_NONE;
61:
62: /* if interrupts are enabled: */
63: if (interreg & TME_SUN3_IREG_INTS_ENAB) {
64:
65: /* find the highest ipl now asserted on the buses: */
66: for (ipl = TME_M68K_IPL_MAX;
67: ipl > TME_M68K_IPL_NONE;
68: ipl--) {
69: ipl_index = ipl >> 3;
70: ipl_mask = TME_BIT(ipl & 7);
71: if (sun3->tme_sun3_int_signals[ipl_index] & ipl_mask) {
72: break;
73: }
74: }
75:
76: /* check the soft interrupts: */
77: if (interreg & TME_SUN3_IREG_SOFT_INT_3) {
78: ipl = TME_MAX(ipl, 3);
79: }
80: else if (interreg & TME_SUN3_IREG_SOFT_INT_2) {
81: ipl = TME_MAX(ipl, 2);
82: }
83: else if (interreg & TME_SUN3_IREG_SOFT_INT_1) {
84: ipl = TME_MAX(ipl, 1);
85: }
86: }
87:
88: /* possibly update the CPU: */
89: if (ipl != sun3->tme_sun3_int_ipl_last) {
90: sun3->tme_sun3_int_ipl_last = ipl;
91: return ((*sun3->tme_sun3_m68k->tme_m68k_bus_interrupt)
92: (sun3->tme_sun3_m68k, ipl));
93: }
94: return (TME_OK);
95: }
96:
97: /* our mainbus signal handler: */
98: static int
99: _tme_sun3_bus_signal(struct tme_bus_connection *conn_bus_raiser, unsigned int signal)
100: {
101: struct tme_sun3 *sun3;
102: int signal_asserted;
103: unsigned int ipl, ipl_index;
104: tme_uint8_t ipl_mask;
105:
106: /* recover our sun3: */
107: sun3 = (struct tme_sun3 *) conn_bus_raiser->tme_bus_connection.tme_connection_element->tme_element_private;
108:
109: /* see whether the signal is asserted or negated: */
110: signal_asserted = TRUE;
111: switch (signal & TME_BUS_SIGNAL_LEVEL_MASK) {
112: case TME_BUS_SIGNAL_LEVEL_NEGATED:
113: signal_asserted = FALSE;
114: case TME_BUS_SIGNAL_LEVEL_ASSERTED:
115: break;
116: default:
117: abort();
118: }
119: signal = TME_BUS_SIGNAL_WHICH(signal);
120:
121: /* ipl 8 doesn't really exist - it's the interrupt signal from the
122: isil7170. we must map it into either ipl 7 (NMI) or ipl 5
123: (clock) depending on the state of the interrupt register: */
124: if (signal == TME_BUS_SIGNAL_INT_CLOCK) {
125:
126: /* if the signal is being asserted: */
127: if (signal_asserted) {
128:
129: /* map the interrupt signal: */
130: if (sun3->tme_sun3_ints & TME_SUN3_IREG_CLOCK_ENAB_5) {
131: signal = TME_BUS_SIGNAL_INT(5);
132: }
133: else if (sun3->tme_sun3_ints & TME_SUN3_IREG_CLOCK_ENAB_7) {
134: signal = TME_BUS_SIGNAL_INT(7);
135: }
136: else {
137: /* the clock interrupt isn't connected to any ipl: */
138: signal = TME_BUS_SIGNAL_INT_UNSPEC;
139: }
140:
141: /* remember the last clock interrupt signal: */
142: sun3->tme_sun3_int_signal_clock_last = signal;
143: }
144:
145: else {
146:
147: /* recover the last clock interrupt signal: */
148: signal = sun3->tme_sun3_int_signal_clock_last;
149: }
150:
151: /* if we're supposed to ignore this signal: */
152: if (signal == TME_BUS_SIGNAL_INT_UNSPEC) {
153: return (TME_OK);
154: }
155: }
156:
157: /* dispatch on the signal: */
158:
159: /* halt: */
160: if (signal == TME_BUS_SIGNAL_HALT) {
161: abort();
162: }
163:
164: /* reset: */
165: else if (signal == TME_BUS_SIGNAL_RESET) {
1.1.1.2 root 166:
167: /* if this reset signal is coming from the m68k: */
168: if (conn_bus_raiser->tme_bus_connection.tme_connection_other
169: == &sun3->tme_sun3_m68k->tme_m68k_bus_connection.tme_bus_connection) {
170:
171: /* XXX FIXME - note that the do_reset code is lazy and only
172: sends reset negation edges out to the busses. we are also
173: lazy (and also worried that sending out assertion edges might
174: break things), so we only send out reset negation edges too: */
175: if (signal_asserted) {
176: return (TME_OK);
177: }
178:
179: /* propagate this reset edge to all busses: */
180: (*sun3->tme_sun3_obio->tme_bus_signal)
181: (sun3->tme_sun3_obio,
182: TME_BUS_SIGNAL_RESET
183: | TME_BUS_SIGNAL_LEVEL_NEGATED
184: | TME_BUS_SIGNAL_EDGE);
185: (*sun3->tme_sun3_obmem->tme_bus_signal)
186: (sun3->tme_sun3_obmem,
187: TME_BUS_SIGNAL_RESET
188: | TME_BUS_SIGNAL_LEVEL_NEGATED
189: | TME_BUS_SIGNAL_EDGE);
190: (*sun3->tme_sun3_vmebus->tme_bus_signal)
191: (sun3->tme_sun3_vmebus,
192: TME_BUS_SIGNAL_RESET
193: | TME_BUS_SIGNAL_LEVEL_NEGATED
194: | TME_BUS_SIGNAL_EDGE);
195: }
1.1 root 196: }
197:
198: /* an interrupt signal: */
199: else if (TME_BUS_SIGNAL_IS_INT(signal)) {
200: ipl = TME_BUS_SIGNAL_INDEX_INT(signal);
201: if (ipl >= TME_M68K_IPL_MIN
202: && ipl <= TME_M68K_IPL_MAX) {
203:
204: /* update this ipl in the byte array: */
205: ipl_index = ipl >> 3;
206: ipl_mask = TME_BIT(ipl & 7);
207: sun3->tme_sun3_int_signals[ipl_index]
208: = ((sun3->tme_sun3_int_signals[ipl_index]
209: & ~ipl_mask)
210: | (signal_asserted
211: ? ipl_mask
212: : 0));
213:
214: /* possibly update the ipl being driven to the CPU: */
215: return (_tme_sun3_ipl_check(sun3));
216: }
217: }
218:
219: /* an unknown signal: */
220: else {
221: abort();
222: }
223:
224: return (TME_OK);
225: }
226:
227: /* this handles a CPU interrupt acknowledge: */
228: static int
229: _tme_sun3_bus_intack(struct tme_bus_connection *conn_m68k, unsigned int ipl, int *vector)
230: {
231: struct tme_sun3 *sun3;
232: tme_uint8_t interreg;
233: unsigned int signal;
234: int rc;
235:
236: /* recover our sun3: */
237: sun3 = (struct tme_sun3 *) conn_m68k->tme_bus_connection.tme_connection_element->tme_element_private;
238:
239: /* acknowledge any soft interrupt: */
240: interreg = sun3->tme_sun3_ints;
241: if ((ipl == 3
242: && (interreg & TME_SUN3_IREG_SOFT_INT_3))
243: || (ipl == 2
244: && (interreg & TME_SUN3_IREG_SOFT_INT_2))
245: || (ipl == 1
246: && (interreg & TME_SUN3_IREG_SOFT_INT_1))) {
247: *vector = TME_BUS_INTERRUPT_VECTOR_UNDEF;
248: return (TME_OK);
249: }
250:
251: /* turn the ipl into a bus signal number: */
252: signal = TME_BUS_SIGNAL_INT(ipl);
253:
254: /* try the acknowledge on these buses, in order: */
255:
256: /* obio: */
257: rc = (*sun3->tme_sun3_obio->tme_bus_intack)
258: (sun3->tme_sun3_obio, signal, vector);
259: if (rc == ENOENT
260: && signal == sun3->tme_sun3_int_signal_clock_last) {
261: rc = (*sun3->tme_sun3_obio->tme_bus_intack)
262: (sun3->tme_sun3_obio, TME_BUS_SIGNAL_INT_CLOCK, vector);
263: }
264: if (rc != ENOENT) {
265: return (rc);
266: }
267: /* obmem: */
268: rc = (*sun3->tme_sun3_obmem->tme_bus_intack)
269: (sun3->tme_sun3_obmem, signal, vector);
270: if (rc != ENOENT) {
271: return (rc);
272: }
273: /* VMEbus: */
274: rc = (*sun3->tme_sun3_vmebus->tme_bus_intack)
275: (sun3->tme_sun3_vmebus, signal, vector);
276: if (rc != ENOENT) {
277: return (rc);
278: }
279:
280: /* done: */
281: return (rc);
282: }
283:
284: /* our command function: */
285: static int
286: _tme_sun3_command(struct tme_element *element, const char * const * args, char **_output)
287: {
288: struct tme_sun3 *sun3;
289: int do_reset;
290:
291: /* recover our sun3: */
292: sun3 = (struct tme_sun3 *) element->tme_element_private;
293:
294: /* assume no reset: */
295: do_reset = FALSE;
296:
297: /* the "power" command: */
298: if (TME_ARG_IS(args[1], "power")) {
299:
300: if (TME_ARG_IS(args[2], "up")
301: && args[3] == NULL) {
302: do_reset = TRUE;
303: }
304:
305: else if (TME_ARG_IS(args[2], "down")
306: && args[3] == NULL) {
307: /* nothing */
308: }
309:
310: /* return an error: */
311: else {
312: tme_output_append_error(_output,
313: "%s %s power [ up | down ]",
314: _("usage:"),
315: args[0]);
316: return (EINVAL);
317: }
318: }
319:
320: /* the "diag-switch" command: */
321: else if (TME_ARG_IS(args[1], "diag-switch")) {
322:
323: if (args[2] == NULL) {
324: tme_output_append_error(_output,
325: "diag-switch %s",
326: (sun3->tme_sun3_enable & TME_SUN3_ENA_DIAG
327: ? "true"
328: : "false"));
329: }
330:
331: else if (TME_ARG_IS(args[2], "true")
332: && args[3] == NULL) {
333: sun3->tme_sun3_enable |= TME_SUN3_ENA_DIAG;
334: }
335:
336: else if (TME_ARG_IS(args[2], "false")
337: && args[3] == NULL) {
338: sun3->tme_sun3_enable &= ~TME_SUN3_ENA_DIAG;
339: }
340:
341: /* return an error: */
342: else {
343: tme_output_append_error(_output,
344: "%s %s diag-switch [ true | false ]",
345: _("usage:"),
346: args[0]);
347: return (EINVAL);
348: }
349: }
350:
351: /* any other command: */
352: else {
353: if (args[1] != NULL) {
354: tme_output_append_error(_output,
355: "%s '%s', ",
356: _("unknown command"),
357: args[1]);
358: }
359: tme_output_append_error(_output,
360: _("available %s commands: %s"),
361: args[0],
362: "power");
363: return (EINVAL);
364: }
365:
366: if (do_reset) {
367:
368: /* reset the CPU: */
369: (*sun3->tme_sun3_m68k->tme_m68k_bus_connection.tme_bus_signal)
370: (&sun3->tme_sun3_m68k->tme_m68k_bus_connection,
371: TME_BUS_SIGNAL_RESET
372: | TME_BUS_SIGNAL_LEVEL_NEGATED
373: | TME_BUS_SIGNAL_EDGE);
374:
375: /* reset all busses: */
376: (*sun3->tme_sun3_obio->tme_bus_signal)
377: (sun3->tme_sun3_obio,
378: TME_BUS_SIGNAL_RESET
379: | TME_BUS_SIGNAL_LEVEL_NEGATED
380: | TME_BUS_SIGNAL_EDGE);
381: (*sun3->tme_sun3_obmem->tme_bus_signal)
382: (sun3->tme_sun3_obmem,
383: TME_BUS_SIGNAL_RESET
384: | TME_BUS_SIGNAL_LEVEL_NEGATED
385: | TME_BUS_SIGNAL_EDGE);
386: (*sun3->tme_sun3_vmebus->tme_bus_signal)
1.1.1.2 root 387: (sun3->tme_sun3_vmebus,
1.1 root 388: TME_BUS_SIGNAL_RESET
389: | TME_BUS_SIGNAL_LEVEL_NEGATED
390: | TME_BUS_SIGNAL_EDGE);
391: }
392:
393: return (TME_OK);
394: }
395:
396: /* the connection scorer: */
397: static int
398: _tme_sun3_connection_score(struct tme_connection *conn, unsigned int *_score)
399: {
400: struct tme_m68k_bus_connection *conn_m68k;
401: struct tme_sun3_bus_connection *conn_sun3;
402: struct tme_bus_connection *conn_bus;
403: struct tme_sun3 *sun3;
404: unsigned int score;
405:
406: /* recover our sun3: */
407: sun3 = (struct tme_sun3 *) conn->tme_connection_element->tme_element_private;
408:
409: /* assume that this connection is useless: */
410: score = 0;
411:
412: /* dispatch on the connection type: */
413: conn_m68k = (struct tme_m68k_bus_connection *) conn->tme_connection_other;
414: conn_sun3 = (struct tme_sun3_bus_connection *) conn;
415: conn_bus = (struct tme_bus_connection *) conn->tme_connection_other;
416: switch (conn->tme_connection_type) {
417:
418: /* this must be an m68k chip, and not another bus: */
419: case TME_CONNECTION_BUS_M68K:
1.1.1.3 root 420: if (conn_bus->tme_bus_tlb_set_add == NULL
1.1 root 421: && conn_m68k->tme_m68k_bus_tlb_fill == NULL
422: && conn_m68k->tme_m68k_bus_m6888x_enable != NULL) {
423: score = 10;
424: }
425: break;
426:
427: /* if this connection is not for an obio master, this must be a bus,
428: and not a chip, and vice versa. if this connection is for a bus,
429: the bus must still be free: */
430: case TME_CONNECTION_BUS_GENERIC:
431: if (((conn_sun3->tme_sun3_bus_connection_which != TME_SUN3_CONN_OBIO_MASTER)
1.1.1.3 root 432: == (conn_bus->tme_bus_tlb_set_add != NULL
1.1 root 433: && conn_bus->tme_bus_tlb_fill != NULL))
434: && (conn_sun3->tme_sun3_bus_connection_which >= TME_SUN3_CONN_BUS_COUNT
435: || sun3->tme_sun3_buses[conn_sun3->tme_sun3_bus_connection_which] == NULL)) {
436: score = 1;
437: }
438: break;
439:
440: default: abort();
441: }
442:
443: *_score = score;
444: return (TME_OK);
445: }
446:
447: /* this makes a new connection: */
448: static int
449: _tme_sun3_connection_make(struct tme_connection *conn, unsigned int state)
450: {
451: struct tme_sun3 *sun3;
452: struct tme_m68k_bus_connection *conn_m68k;
453: struct tme_sun3_bus_connection *conn_sun3;
454: struct tme_bus_connection *conn_bus;
455: struct tme_connection *conn_other;
456:
457: /* recover our sun3: */
458: sun3 = (struct tme_sun3 *) conn->tme_connection_element->tme_element_private;
459:
460: /* dispatch on the connection type: */
461: conn_other = conn->tme_connection_other;
462: conn_m68k = (struct tme_m68k_bus_connection *) conn_other;
463: conn_sun3 = (struct tme_sun3_bus_connection *) conn;
464: conn_bus = (struct tme_bus_connection *) conn_other;
465: switch (conn->tme_connection_type) {
466:
467: case TME_CONNECTION_BUS_M68K:
468: sun3->tme_sun3_m68k = conn_m68k;
469: break;
470:
471: case TME_CONNECTION_BUS_GENERIC:
472:
473: /* if this connection is for a bus: */
474: if (conn_sun3->tme_sun3_bus_connection_which < TME_SUN3_CONN_BUS_COUNT) {
475:
476: /* remember the connection to this bus: */
477: sun3->tme_sun3_buses[conn_sun3->tme_sun3_bus_connection_which] = conn_bus;
478: }
479:
480: /* otherwise, if this connection is for the memory error register: */
481: else if (conn_sun3->tme_sun3_bus_connection_which == TME_SUN3_CONN_REG_MEMERR) {
482:
483: /* remember the memory error register's bus connection: */
484: sun3->tme_sun3_memerr_bus = conn_bus;
485: }
486:
487: break;
488:
489: default:
490: assert(FALSE);
491: break;
492: }
493: return (TME_OK);
494: }
495:
496: /* this breaks a connection: */
497: static int
498: _tme_sun3_connection_break(struct tme_connection *conn, unsigned int state)
499: {
500: abort();
501: }
502:
503: /* this makes new connection sides: */
504: static int
505: _tme_sun3_connections_new(struct tme_element *element, const char * const *args, struct tme_connection **_conns, char **_output)
506: {
507: struct tme_m68k_bus_connection *conn_m68k;
508: struct tme_sun3_bus_connection *conn_sun3;
509: struct tme_bus_connection *conn_bus;
510: struct tme_connection *conn;
511: struct tme_sun3 *sun3;
512: char *free_buses;
513: int which_conn;
514:
515: /* recover our sun3: */
516: sun3 = (struct tme_sun3 *) element->tme_element_private;
517:
518: /* if we have no arguments, and we don't have a CPU yet, we can take
519: an m68k bus connection: */
520: if (args[1] == NULL
521: && sun3->tme_sun3_m68k == NULL) {
522:
523: /* create our side of an m68k bus connection: */
524: conn_m68k = tme_new0(struct tme_m68k_bus_connection, 1);
525: conn_bus = &conn_m68k->tme_m68k_bus_connection;
526: conn = &conn_bus->tme_bus_connection;
527: conn->tme_connection_next = *_conns;
528:
529: /* fill in the generic connection: */
530: conn->tme_connection_type = TME_CONNECTION_BUS_M68K;
531: conn->tme_connection_score = _tme_sun3_connection_score;
532: conn->tme_connection_make = _tme_sun3_connection_make;
533: conn->tme_connection_break = _tme_sun3_connection_break;
534:
535: /* fill in the generic bus connection: */
536: conn_bus->tme_bus_signal = _tme_sun3_bus_signal;
537: conn_bus->tme_bus_intack = _tme_sun3_bus_intack;
1.1.1.3 root 538: conn_bus->tme_bus_tlb_set_add = _tme_sun3_mmu_tlb_set_add;
1.1 root 539:
540: /* full in the m68k bus connection: */
541: conn_m68k->tme_m68k_bus_tlb_fill = _tme_sun3_m68k_tlb_fill;
542:
543: /* add in this connection side possibility: */
544: *_conns = conn;
545: }
546:
547: /* create our side of a generic bus connection: */
548: conn_sun3 = tme_new0(struct tme_sun3_bus_connection, 1);
549: conn_bus = &conn_sun3->tme_sun3_bus_connection;
550: conn = &conn_bus->tme_bus_connection;
551: conn->tme_connection_next = *_conns;
552:
553: /* fill in the generic connection: */
554: conn->tme_connection_type = TME_CONNECTION_BUS_GENERIC;
555: conn->tme_connection_score = _tme_sun3_connection_score;
556: conn->tme_connection_make = _tme_sun3_connection_make;
557: conn->tme_connection_break = _tme_sun3_connection_break;
558:
559: /* fill in the generic bus connection: */
560: conn_bus->tme_bus_signal = _tme_sun3_bus_signal;
561: conn_bus->tme_bus_intack = NULL;
1.1.1.3 root 562: conn_bus->tme_bus_tlb_set_add = _tme_sun3_mmu_tlb_set_add;
1.1 root 563: conn_bus->tme_bus_tlb_fill = _tme_sun3_bus_tlb_fill;
564:
565: /* if we have no argument: */
566: if (args[1] == NULL) {
567:
568: /* make this connection for an obio master: */
569: conn_sun3->tme_sun3_bus_connection_which = TME_SUN3_CONN_OBIO_MASTER;
570: }
571:
572: /* otherwise, we have at least one argument: */
573: else {
574:
575: /* we must have no other arguments: */
576: if (args[2] != NULL) {
577: tme_output_append_error(_output,
578: "%s %s",
579: args[2],
580: _("unexpected"));
581: tme_free(conn_sun3);
582: return (EINVAL);
583: }
584:
585: /* start the list of buses that we don't have yet: */
586: free_buses = NULL;
587:
588: /* poison the which connection: */
589: which_conn = -1;
590:
591: /* check each bus: */
592:
593: /* obio: */
594: if (sun3->tme_sun3_obio == NULL) {
595: tme_output_append(&free_buses, " obio");
596: }
597: if (TME_ARG_IS(args[1], "obio")) {
598: which_conn = TME_SUN3_CONN_BUS_OBIO;
599: }
600:
601: /* obmem: */
602: if (sun3->tme_sun3_obmem == NULL) {
603: tme_output_append(&free_buses, " obmem");
604: }
605: if (TME_ARG_IS(args[1], "obmem")) {
606: which_conn = TME_SUN3_CONN_BUS_OBMEM;
607: }
608:
609: /* VMEbus: */
610: if (sun3->tme_sun3_vmebus == NULL) {
611: tme_output_append(&free_buses, " vme");
612: }
613: if (TME_ARG_IS(args[1], "vme")) {
614: which_conn = TME_SUN3_CONN_BUS_VME;
615: conn_bus->tme_bus_subregions.tme_bus_subregion_address_last
616: = TME_SUN3_DVMA_SIZE_VME;
617: }
618:
619: /* random connections: */
620:
621: if (TME_ARG_IS(args[1], "memerr")) {
622: which_conn = TME_SUN3_CONN_REG_MEMERR;
623: conn_bus->tme_bus_subregions.tme_bus_subregion_address_last
624: = TME_SUN3_MEMERR_SIZ_REG;
625: }
626: else if (TME_ARG_IS(args[1], "intreg")) {
627: which_conn = TME_SUN3_CONN_REG_INTREG;
628: conn_bus->tme_bus_subregions.tme_bus_subregion_address_last
629: = sizeof(sun3->tme_sun3_ints);
630: }
631:
632: /* if the which connection is still poison, or if this is trying
633: to connect a bus that we already have, complain: */
634: if (which_conn < 0
635: || (which_conn < TME_SUN3_CONN_BUS_COUNT
636: && sun3->tme_sun3_buses[which_conn] != NULL)) {
637: if (which_conn < 0) {
638: tme_output_append_error(_output,
639: "%s %s",
640: _("unknown bus or register:"),
641: args[1]);
642: }
643: if (free_buses != NULL) {
644: tme_output_append_error(_output,
645: "%s %s",
646: _("remaining buses:"),
647: free_buses);
648: tme_free(free_buses);
649: }
650: else {
651: tme_output_append_error(_output, _("all buses present"));
652: }
653: tme_free(conn_sun3);
654: return (EINVAL);
655: }
656:
657: /* free the remaining bus list: */
658: if (free_buses != NULL) {
659: tme_free(free_buses);
660: }
661:
662: /* fill in the sun3 connection: */
663: conn_sun3->tme_sun3_bus_connection_which = which_conn;
664: }
665:
666: /* add in this connection side possibility: */
667: *_conns = conn;
668:
669: /* done: */
670: return (TME_OK);
671: }
672:
673: /* this creates a new sun3 element: */
674: TME_ELEMENT_NEW_DECL(tme_machine_sun3) {
675: int usage;
676: struct tme_sun3 *sun3;
677: const char *idprom_filename;
678: FILE *idprom_fp;
679: tme_uint8_t idprom[TME_SUN_IDPROM_SIZE];
680: int arg_i;
681:
682: arg_i = 1;
683: usage = FALSE;
684:
685: /* our first argument is the filename to load our IDPROM contents from: */
686: idprom_filename = args[arg_i++];
687: if (idprom_filename == NULL) {
688: usage = TRUE;
689: }
690:
691: /* we must have no more arguments: */
692: if (args[arg_i] != NULL) {
693: tme_output_append_error(_output,
694: "%s %s, ",
695: args[arg_i],
696: _("unexpected"));
697: usage = TRUE;
698: }
699:
700: /* if our usage was bad: */
701: if (usage) {
702: tme_output_append_error(_output,
703: "%s %s IDPROM%s",
704: _("usage:"),
705: args[0],
706: _("-FILENAME"));
707: return (EINVAL);
708: }
709:
710: /* try to read in the IDPROM: */
711: idprom_fp = fopen(idprom_filename, "r");
712: if (idprom_fp == NULL) {
1.1.1.4 ! root 713: tme_output_append_error(_output, "%s", idprom_filename);
1.1 root 714: return (errno);
715: }
716: if (fread(idprom, sizeof(tme_uint8_t), sizeof(idprom), idprom_fp) != sizeof(idprom)) {
1.1.1.4 ! root 717: tme_output_append_error(_output, "%s", idprom_filename);
1.1 root 718: fclose(idprom_fp);
719: return (ENOEXEC);
720: }
721: fclose(idprom_fp);
722:
723: /* allocate and initialize the new sun3: */
724: sun3 = tme_new0(struct tme_sun3, 1);
725: sun3->tme_sun3_element = element;
726:
727: /* set the IDPROM: */
728: memcpy(sun3->tme_sun3_idprom_contents, idprom, sizeof(idprom));
729:
730: /* the context register: */
731: sun3->tme_sun3_context = 0;
732:
733: /* the diagnostics register: */
734: sun3->tme_sun3_diag = 0;
735:
736: /* the bus error register: */
737: sun3->tme_sun3_buserr = 0;
738:
739: /* the enable register: */
740: sun3->tme_sun3_enable = 0;
741:
742: /* the memory error register: */
743: sun3->tme_sun3_memerr_csr = 0;
744: sun3->tme_sun3_memerr_vaddr = 0;
745:
746: /* the interrupt register: */
747: sun3->tme_sun3_ints = 0;
748:
749: /* the MMU: */
750: _tme_sun3_mmu_new(sun3);
751:
752: /* the busses: */
753: sun3->tme_sun3_obio = NULL;
754: sun3->tme_sun3_obmem = NULL;
755: sun3->tme_sun3_vmebus = NULL;
756:
757: /* the last clock interrupt signal: */
758: sun3->tme_sun3_int_signal_clock_last = TME_BUS_SIGNAL_INT_UNSPEC;
759:
760: /* fill the element: */
761: element->tme_element_private = sun3;
762: element->tme_element_connections_new = _tme_sun3_connections_new;
763: element->tme_element_command = _tme_sun3_command;
764:
765: return (TME_OK);
766: }
767:
768: /* this creates a new Sun-3 isil7170: */
769: TME_ELEMENT_SUB_NEW_DECL(tme_machine_sun3,clock) {
770: struct tme_isil7170_socket socket;
771: const char *sub_args[4];
772: int arg_i;
773:
774: /* create the isil7170 socket: */
775: memset (&socket, 0, sizeof(socket));
776: socket.tme_isil7170_socket_version = TME_ISIL7170_SOCKET_0;
777: socket.tme_isil7170_socket_addr_shift = 0;
778: socket.tme_isil7170_socket_port_least_lane = 3; /* D31-D24 */
779: socket.tme_isil7170_socket_clock_basic = TME_ISIL7170_FREQ_32K;
780: socket.tme_isil7170_socket_int_signal = TME_BUS_SIGNAL_INT_CLOCK;
781:
782: /* create the isil7170. we allow at most two arguments to pass
783: through, which is an awful hack: */
784: sub_args[0] = "tme/ic/isil7170";
785: for (arg_i = 1;; arg_i++) {
786: if (arg_i == TME_ARRAY_ELS(sub_args)) {
787: abort();
788: }
789: sub_args[arg_i] = args[arg_i];
790: if (args[arg_i] == NULL) {
791: break;
792: }
793: }
794: return (tme_element_new(element, (const char * const *) sub_args, &socket, _output));
795: }
796:
797: /* this creates a new Sun-3 z8530: */
798: TME_ELEMENT_SUB_NEW_DECL(tme_machine_sun3,zs) {
799: struct tme_z8530_socket socket = TME_SUN_Z8530_SOCKET_INIT;
800: char *sub_args[2];
801:
802: /* create the z8530: */
803: sub_args[0] = "tme/ic/z8530";
804: sub_args[1] = NULL;
805: return (tme_element_new(element, (const char * const *) sub_args, &socket, _output));
806: }
807:
808: /* this creates a new Sun-3 obie: */
809: TME_ELEMENT_SUB_NEW_DECL(tme_machine_sun3,obie) {
810: return (tme_sun_obie(element, args, _output));
811: }
812:
813: /* this creates a new Sun-3 bwtwo: */
814: TME_ELEMENT_SUB_NEW_DECL(tme_machine_sun3,bwtwo) {
815: return (tme_sun_bwtwo(element, args, _output));
816: }
817:
818: /* this creates a new Sun-3 si: */
819: TME_ELEMENT_SUB_NEW_DECL(tme_machine_sun3,si) {
820: return (tme_sun_si(element, args, _output));
821: }
822:
823: /* this creates a new Sun-3 cgtwo: */
824: TME_ELEMENT_SUB_NEW_DECL(tme_machine_sun3,cgtwo) {
825: return (tme_sun_cgtwo(element, args, _output));
826: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.