|
|
1.1 root 1: /* $Id: sun3-mainbus.c,v 1.4 2005/05/11 00:14:30 fredette Exp $ */
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>
37: _TME_RCSID("$Id: sun3-mainbus.c,v 1.4 2005/05/11 00:14:30 fredette Exp $");
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) {
166: /* XXX reset is just ignored for now: */
167: }
168:
169: /* an interrupt signal: */
170: else if (TME_BUS_SIGNAL_IS_INT(signal)) {
171: ipl = TME_BUS_SIGNAL_INDEX_INT(signal);
172: if (ipl >= TME_M68K_IPL_MIN
173: && ipl <= TME_M68K_IPL_MAX) {
174:
175: /* update this ipl in the byte array: */
176: ipl_index = ipl >> 3;
177: ipl_mask = TME_BIT(ipl & 7);
178: sun3->tme_sun3_int_signals[ipl_index]
179: = ((sun3->tme_sun3_int_signals[ipl_index]
180: & ~ipl_mask)
181: | (signal_asserted
182: ? ipl_mask
183: : 0));
184:
185: /* possibly update the ipl being driven to the CPU: */
186: return (_tme_sun3_ipl_check(sun3));
187: }
188: }
189:
190: /* an unknown signal: */
191: else {
192: abort();
193: }
194:
195: return (TME_OK);
196: }
197:
198: /* this handles a CPU interrupt acknowledge: */
199: static int
200: _tme_sun3_bus_intack(struct tme_bus_connection *conn_m68k, unsigned int ipl, int *vector)
201: {
202: struct tme_sun3 *sun3;
203: tme_uint8_t interreg;
204: unsigned int signal;
205: int rc;
206:
207: /* recover our sun3: */
208: sun3 = (struct tme_sun3 *) conn_m68k->tme_bus_connection.tme_connection_element->tme_element_private;
209:
210: /* acknowledge any soft interrupt: */
211: interreg = sun3->tme_sun3_ints;
212: if ((ipl == 3
213: && (interreg & TME_SUN3_IREG_SOFT_INT_3))
214: || (ipl == 2
215: && (interreg & TME_SUN3_IREG_SOFT_INT_2))
216: || (ipl == 1
217: && (interreg & TME_SUN3_IREG_SOFT_INT_1))) {
218: *vector = TME_BUS_INTERRUPT_VECTOR_UNDEF;
219: return (TME_OK);
220: }
221:
222: /* turn the ipl into a bus signal number: */
223: signal = TME_BUS_SIGNAL_INT(ipl);
224:
225: /* try the acknowledge on these buses, in order: */
226:
227: /* obio: */
228: rc = (*sun3->tme_sun3_obio->tme_bus_intack)
229: (sun3->tme_sun3_obio, signal, vector);
230: if (rc == ENOENT
231: && signal == sun3->tme_sun3_int_signal_clock_last) {
232: rc = (*sun3->tme_sun3_obio->tme_bus_intack)
233: (sun3->tme_sun3_obio, TME_BUS_SIGNAL_INT_CLOCK, vector);
234: }
235: if (rc != ENOENT) {
236: return (rc);
237: }
238: /* obmem: */
239: rc = (*sun3->tme_sun3_obmem->tme_bus_intack)
240: (sun3->tme_sun3_obmem, signal, vector);
241: if (rc != ENOENT) {
242: return (rc);
243: }
244: /* VMEbus: */
245: rc = (*sun3->tme_sun3_vmebus->tme_bus_intack)
246: (sun3->tme_sun3_vmebus, signal, vector);
247: if (rc != ENOENT) {
248: return (rc);
249: }
250:
251: /* done: */
252: return (rc);
253: }
254:
255: /* our command function: */
256: static int
257: _tme_sun3_command(struct tme_element *element, const char * const * args, char **_output)
258: {
259: struct tme_sun3 *sun3;
260: int do_reset;
261:
262: /* recover our sun3: */
263: sun3 = (struct tme_sun3 *) element->tme_element_private;
264:
265: /* assume no reset: */
266: do_reset = FALSE;
267:
268: /* the "power" command: */
269: if (TME_ARG_IS(args[1], "power")) {
270:
271: if (TME_ARG_IS(args[2], "up")
272: && args[3] == NULL) {
273: do_reset = TRUE;
274: }
275:
276: else if (TME_ARG_IS(args[2], "down")
277: && args[3] == NULL) {
278: /* nothing */
279: }
280:
281: /* return an error: */
282: else {
283: tme_output_append_error(_output,
284: "%s %s power [ up | down ]",
285: _("usage:"),
286: args[0]);
287: return (EINVAL);
288: }
289: }
290:
291: /* the "diag-switch" command: */
292: else if (TME_ARG_IS(args[1], "diag-switch")) {
293:
294: if (args[2] == NULL) {
295: tme_output_append_error(_output,
296: "diag-switch %s",
297: (sun3->tme_sun3_enable & TME_SUN3_ENA_DIAG
298: ? "true"
299: : "false"));
300: }
301:
302: else if (TME_ARG_IS(args[2], "true")
303: && args[3] == NULL) {
304: sun3->tme_sun3_enable |= TME_SUN3_ENA_DIAG;
305: }
306:
307: else if (TME_ARG_IS(args[2], "false")
308: && args[3] == NULL) {
309: sun3->tme_sun3_enable &= ~TME_SUN3_ENA_DIAG;
310: }
311:
312: /* return an error: */
313: else {
314: tme_output_append_error(_output,
315: "%s %s diag-switch [ true | false ]",
316: _("usage:"),
317: args[0]);
318: return (EINVAL);
319: }
320: }
321:
322: /* any other command: */
323: else {
324: if (args[1] != NULL) {
325: tme_output_append_error(_output,
326: "%s '%s', ",
327: _("unknown command"),
328: args[1]);
329: }
330: tme_output_append_error(_output,
331: _("available %s commands: %s"),
332: args[0],
333: "power");
334: return (EINVAL);
335: }
336:
337: if (do_reset) {
338:
339: /* reset the CPU: */
340: (*sun3->tme_sun3_m68k->tme_m68k_bus_connection.tme_bus_signal)
341: (&sun3->tme_sun3_m68k->tme_m68k_bus_connection,
342: TME_BUS_SIGNAL_RESET
343: | TME_BUS_SIGNAL_LEVEL_NEGATED
344: | TME_BUS_SIGNAL_EDGE);
345:
346: /* reset all busses: */
347: (*sun3->tme_sun3_obio->tme_bus_signal)
348: (sun3->tme_sun3_obio,
349: TME_BUS_SIGNAL_RESET
350: | TME_BUS_SIGNAL_LEVEL_NEGATED
351: | TME_BUS_SIGNAL_EDGE);
352: (*sun3->tme_sun3_obmem->tme_bus_signal)
353: (sun3->tme_sun3_obmem,
354: TME_BUS_SIGNAL_RESET
355: | TME_BUS_SIGNAL_LEVEL_NEGATED
356: | TME_BUS_SIGNAL_EDGE);
357: (*sun3->tme_sun3_vmebus->tme_bus_signal)
358: (sun3->tme_sun3_obmem,
359: TME_BUS_SIGNAL_RESET
360: | TME_BUS_SIGNAL_LEVEL_NEGATED
361: | TME_BUS_SIGNAL_EDGE);
362: }
363:
364: return (TME_OK);
365: }
366:
367: /* the connection scorer: */
368: static int
369: _tme_sun3_connection_score(struct tme_connection *conn, unsigned int *_score)
370: {
371: struct tme_m68k_bus_connection *conn_m68k;
372: struct tme_sun3_bus_connection *conn_sun3;
373: struct tme_bus_connection *conn_bus;
374: struct tme_sun3 *sun3;
375: unsigned int score;
376:
377: /* recover our sun3: */
378: sun3 = (struct tme_sun3 *) conn->tme_connection_element->tme_element_private;
379:
380: /* assume that this connection is useless: */
381: score = 0;
382:
383: /* dispatch on the connection type: */
384: conn_m68k = (struct tme_m68k_bus_connection *) conn->tme_connection_other;
385: conn_sun3 = (struct tme_sun3_bus_connection *) conn;
386: conn_bus = (struct tme_bus_connection *) conn->tme_connection_other;
387: switch (conn->tme_connection_type) {
388:
389: /* this must be an m68k chip, and not another bus: */
390: case TME_CONNECTION_BUS_M68K:
391: if (conn_bus->tme_bus_tlb_set_allocate == NULL
392: && conn_m68k->tme_m68k_bus_tlb_fill == NULL
393: && conn_m68k->tme_m68k_bus_m6888x_enable != NULL) {
394: score = 10;
395: }
396: break;
397:
398: /* if this connection is not for an obio master, this must be a bus,
399: and not a chip, and vice versa. if this connection is for a bus,
400: the bus must still be free: */
401: case TME_CONNECTION_BUS_GENERIC:
402: if (((conn_sun3->tme_sun3_bus_connection_which != TME_SUN3_CONN_OBIO_MASTER)
403: == (conn_bus->tme_bus_tlb_set_allocate != NULL
404: && conn_bus->tme_bus_tlb_fill != NULL))
405: && (conn_sun3->tme_sun3_bus_connection_which >= TME_SUN3_CONN_BUS_COUNT
406: || sun3->tme_sun3_buses[conn_sun3->tme_sun3_bus_connection_which] == NULL)) {
407: score = 1;
408: }
409: break;
410:
411: default: abort();
412: }
413:
414: *_score = score;
415: return (TME_OK);
416: }
417:
418: /* this makes a new connection: */
419: static int
420: _tme_sun3_connection_make(struct tme_connection *conn, unsigned int state)
421: {
422: struct tme_sun3 *sun3;
423: struct tme_m68k_bus_connection *conn_m68k;
424: struct tme_sun3_bus_connection *conn_sun3;
425: struct tme_bus_connection *conn_bus;
426: struct tme_connection *conn_other;
427:
428: /* recover our sun3: */
429: sun3 = (struct tme_sun3 *) conn->tme_connection_element->tme_element_private;
430:
431: /* dispatch on the connection type: */
432: conn_other = conn->tme_connection_other;
433: conn_m68k = (struct tme_m68k_bus_connection *) conn_other;
434: conn_sun3 = (struct tme_sun3_bus_connection *) conn;
435: conn_bus = (struct tme_bus_connection *) conn_other;
436: switch (conn->tme_connection_type) {
437:
438: case TME_CONNECTION_BUS_M68K:
439: sun3->tme_sun3_m68k = conn_m68k;
440: break;
441:
442: case TME_CONNECTION_BUS_GENERIC:
443:
444: /* if this connection is for a bus: */
445: if (conn_sun3->tme_sun3_bus_connection_which < TME_SUN3_CONN_BUS_COUNT) {
446:
447: /* remember the connection to this bus: */
448: sun3->tme_sun3_buses[conn_sun3->tme_sun3_bus_connection_which] = conn_bus;
449: }
450:
451: /* otherwise, if this connection is for the memory error register: */
452: else if (conn_sun3->tme_sun3_bus_connection_which == TME_SUN3_CONN_REG_MEMERR) {
453:
454: /* remember the memory error register's bus connection: */
455: sun3->tme_sun3_memerr_bus = conn_bus;
456: }
457:
458: break;
459:
460: default:
461: assert(FALSE);
462: break;
463: }
464: return (TME_OK);
465: }
466:
467: /* this breaks a connection: */
468: static int
469: _tme_sun3_connection_break(struct tme_connection *conn, unsigned int state)
470: {
471: abort();
472: }
473:
474: /* this makes new connection sides: */
475: static int
476: _tme_sun3_connections_new(struct tme_element *element, const char * const *args, struct tme_connection **_conns, char **_output)
477: {
478: struct tme_m68k_bus_connection *conn_m68k;
479: struct tme_sun3_bus_connection *conn_sun3;
480: struct tme_bus_connection *conn_bus;
481: struct tme_connection *conn;
482: struct tme_sun3 *sun3;
483: char *free_buses;
484: int which_conn;
485:
486: /* recover our sun3: */
487: sun3 = (struct tme_sun3 *) element->tme_element_private;
488:
489: /* if we have no arguments, and we don't have a CPU yet, we can take
490: an m68k bus connection: */
491: if (args[1] == NULL
492: && sun3->tme_sun3_m68k == NULL) {
493:
494: /* create our side of an m68k bus connection: */
495: conn_m68k = tme_new0(struct tme_m68k_bus_connection, 1);
496: conn_bus = &conn_m68k->tme_m68k_bus_connection;
497: conn = &conn_bus->tme_bus_connection;
498: conn->tme_connection_next = *_conns;
499:
500: /* fill in the generic connection: */
501: conn->tme_connection_type = TME_CONNECTION_BUS_M68K;
502: conn->tme_connection_score = _tme_sun3_connection_score;
503: conn->tme_connection_make = _tme_sun3_connection_make;
504: conn->tme_connection_break = _tme_sun3_connection_break;
505:
506: /* fill in the generic bus connection: */
507: conn_bus->tme_bus_signal = _tme_sun3_bus_signal;
508: conn_bus->tme_bus_intack = _tme_sun3_bus_intack;
509: conn_bus->tme_bus_tlb_set_allocate = _tme_sun3_mmu_tlb_set_allocate;
510:
511: /* full in the m68k bus connection: */
512: conn_m68k->tme_m68k_bus_tlb_fill = _tme_sun3_m68k_tlb_fill;
513:
514: /* add in this connection side possibility: */
515: *_conns = conn;
516: }
517:
518: /* create our side of a generic bus connection: */
519: conn_sun3 = tme_new0(struct tme_sun3_bus_connection, 1);
520: conn_bus = &conn_sun3->tme_sun3_bus_connection;
521: conn = &conn_bus->tme_bus_connection;
522: conn->tme_connection_next = *_conns;
523:
524: /* fill in the generic connection: */
525: conn->tme_connection_type = TME_CONNECTION_BUS_GENERIC;
526: conn->tme_connection_score = _tme_sun3_connection_score;
527: conn->tme_connection_make = _tme_sun3_connection_make;
528: conn->tme_connection_break = _tme_sun3_connection_break;
529:
530: /* fill in the generic bus connection: */
531: conn_bus->tme_bus_signal = _tme_sun3_bus_signal;
532: conn_bus->tme_bus_intack = NULL;
533: conn_bus->tme_bus_tlb_set_allocate = _tme_sun3_mmu_tlb_set_allocate;
534: conn_bus->tme_bus_tlb_fill = _tme_sun3_bus_tlb_fill;
535:
536: /* if we have no argument: */
537: if (args[1] == NULL) {
538:
539: /* make this connection for an obio master: */
540: conn_sun3->tme_sun3_bus_connection_which = TME_SUN3_CONN_OBIO_MASTER;
541: }
542:
543: /* otherwise, we have at least one argument: */
544: else {
545:
546: /* we must have no other arguments: */
547: if (args[2] != NULL) {
548: tme_output_append_error(_output,
549: "%s %s",
550: args[2],
551: _("unexpected"));
552: tme_free(conn_sun3);
553: return (EINVAL);
554: }
555:
556: /* start the list of buses that we don't have yet: */
557: free_buses = NULL;
558:
559: /* poison the which connection: */
560: which_conn = -1;
561:
562: /* check each bus: */
563:
564: /* obio: */
565: if (sun3->tme_sun3_obio == NULL) {
566: tme_output_append(&free_buses, " obio");
567: }
568: if (TME_ARG_IS(args[1], "obio")) {
569: which_conn = TME_SUN3_CONN_BUS_OBIO;
570: }
571:
572: /* obmem: */
573: if (sun3->tme_sun3_obmem == NULL) {
574: tme_output_append(&free_buses, " obmem");
575: }
576: if (TME_ARG_IS(args[1], "obmem")) {
577: which_conn = TME_SUN3_CONN_BUS_OBMEM;
578: }
579:
580: /* VMEbus: */
581: if (sun3->tme_sun3_vmebus == NULL) {
582: tme_output_append(&free_buses, " vme");
583: }
584: if (TME_ARG_IS(args[1], "vme")) {
585: which_conn = TME_SUN3_CONN_BUS_VME;
586: conn_bus->tme_bus_subregions.tme_bus_subregion_address_last
587: = TME_SUN3_DVMA_SIZE_VME;
588: }
589:
590: /* random connections: */
591:
592: if (TME_ARG_IS(args[1], "memerr")) {
593: which_conn = TME_SUN3_CONN_REG_MEMERR;
594: conn_bus->tme_bus_subregions.tme_bus_subregion_address_last
595: = TME_SUN3_MEMERR_SIZ_REG;
596: }
597: else if (TME_ARG_IS(args[1], "intreg")) {
598: which_conn = TME_SUN3_CONN_REG_INTREG;
599: conn_bus->tme_bus_subregions.tme_bus_subregion_address_last
600: = sizeof(sun3->tme_sun3_ints);
601: }
602:
603: /* if the which connection is still poison, or if this is trying
604: to connect a bus that we already have, complain: */
605: if (which_conn < 0
606: || (which_conn < TME_SUN3_CONN_BUS_COUNT
607: && sun3->tme_sun3_buses[which_conn] != NULL)) {
608: if (which_conn < 0) {
609: tme_output_append_error(_output,
610: "%s %s",
611: _("unknown bus or register:"),
612: args[1]);
613: }
614: if (free_buses != NULL) {
615: tme_output_append_error(_output,
616: "%s %s",
617: _("remaining buses:"),
618: free_buses);
619: tme_free(free_buses);
620: }
621: else {
622: tme_output_append_error(_output, _("all buses present"));
623: }
624: tme_free(conn_sun3);
625: return (EINVAL);
626: }
627:
628: /* free the remaining bus list: */
629: if (free_buses != NULL) {
630: tme_free(free_buses);
631: }
632:
633: /* fill in the sun3 connection: */
634: conn_sun3->tme_sun3_bus_connection_which = which_conn;
635: }
636:
637: /* add in this connection side possibility: */
638: *_conns = conn;
639:
640: /* done: */
641: return (TME_OK);
642: }
643:
644: /* this creates a new sun3 element: */
645: TME_ELEMENT_NEW_DECL(tme_machine_sun3) {
646: int usage;
647: struct tme_sun3 *sun3;
648: const char *idprom_filename;
649: FILE *idprom_fp;
650: tme_uint8_t idprom[TME_SUN_IDPROM_SIZE];
651: int arg_i;
652:
653: arg_i = 1;
654: usage = FALSE;
655:
656: /* our first argument is the filename to load our IDPROM contents from: */
657: idprom_filename = args[arg_i++];
658: if (idprom_filename == NULL) {
659: usage = TRUE;
660: }
661:
662: /* we must have no more arguments: */
663: if (args[arg_i] != NULL) {
664: tme_output_append_error(_output,
665: "%s %s, ",
666: args[arg_i],
667: _("unexpected"));
668: usage = TRUE;
669: }
670:
671: /* if our usage was bad: */
672: if (usage) {
673: tme_output_append_error(_output,
674: "%s %s IDPROM%s",
675: _("usage:"),
676: args[0],
677: _("-FILENAME"));
678: return (EINVAL);
679: }
680:
681: /* try to read in the IDPROM: */
682: idprom_fp = fopen(idprom_filename, "r");
683: if (idprom_fp == NULL) {
684: tme_output_append_error(_output, idprom_filename);
685: return (errno);
686: }
687: if (fread(idprom, sizeof(tme_uint8_t), sizeof(idprom), idprom_fp) != sizeof(idprom)) {
688: tme_output_append_error(_output, idprom_filename);
689: fclose(idprom_fp);
690: return (ENOEXEC);
691: }
692: fclose(idprom_fp);
693:
694: /* allocate and initialize the new sun3: */
695: sun3 = tme_new0(struct tme_sun3, 1);
696: sun3->tme_sun3_element = element;
697:
698: /* set the IDPROM: */
699: memcpy(sun3->tme_sun3_idprom_contents, idprom, sizeof(idprom));
700:
701: /* the context register: */
702: sun3->tme_sun3_context = 0;
703:
704: /* the diagnostics register: */
705: sun3->tme_sun3_diag = 0;
706:
707: /* the bus error register: */
708: sun3->tme_sun3_buserr = 0;
709:
710: /* the enable register: */
711: sun3->tme_sun3_enable = 0;
712:
713: /* the memory error register: */
714: sun3->tme_sun3_memerr_csr = 0;
715: sun3->tme_sun3_memerr_vaddr = 0;
716:
717: /* the interrupt register: */
718: sun3->tme_sun3_ints = 0;
719:
720: /* the MMU: */
721: _tme_sun3_mmu_new(sun3);
722:
723: /* the busses: */
724: sun3->tme_sun3_obio = NULL;
725: sun3->tme_sun3_obmem = NULL;
726: sun3->tme_sun3_vmebus = NULL;
727:
728: /* the last clock interrupt signal: */
729: sun3->tme_sun3_int_signal_clock_last = TME_BUS_SIGNAL_INT_UNSPEC;
730:
731: /* fill the element: */
732: element->tme_element_private = sun3;
733: element->tme_element_connections_new = _tme_sun3_connections_new;
734: element->tme_element_command = _tme_sun3_command;
735:
736: return (TME_OK);
737: }
738:
739: /* this creates a new Sun-3 isil7170: */
740: TME_ELEMENT_SUB_NEW_DECL(tme_machine_sun3,clock) {
741: struct tme_isil7170_socket socket;
742: const char *sub_args[4];
743: int arg_i;
744:
745: /* create the isil7170 socket: */
746: memset (&socket, 0, sizeof(socket));
747: socket.tme_isil7170_socket_version = TME_ISIL7170_SOCKET_0;
748: socket.tme_isil7170_socket_addr_shift = 0;
749: socket.tme_isil7170_socket_port_least_lane = 3; /* D31-D24 */
750: socket.tme_isil7170_socket_clock_basic = TME_ISIL7170_FREQ_32K;
751: socket.tme_isil7170_socket_int_signal = TME_BUS_SIGNAL_INT_CLOCK;
752:
753: /* create the isil7170. we allow at most two arguments to pass
754: through, which is an awful hack: */
755: sub_args[0] = "tme/ic/isil7170";
756: for (arg_i = 1;; arg_i++) {
757: if (arg_i == TME_ARRAY_ELS(sub_args)) {
758: abort();
759: }
760: sub_args[arg_i] = args[arg_i];
761: if (args[arg_i] == NULL) {
762: break;
763: }
764: }
765: return (tme_element_new(element, (const char * const *) sub_args, &socket, _output));
766: }
767:
768: /* this creates a new Sun-3 z8530: */
769: TME_ELEMENT_SUB_NEW_DECL(tme_machine_sun3,zs) {
770: struct tme_z8530_socket socket = TME_SUN_Z8530_SOCKET_INIT;
771: char *sub_args[2];
772:
773: /* create the z8530: */
774: sub_args[0] = "tme/ic/z8530";
775: sub_args[1] = NULL;
776: return (tme_element_new(element, (const char * const *) sub_args, &socket, _output));
777: }
778:
779: /* this creates a new Sun-3 obie: */
780: TME_ELEMENT_SUB_NEW_DECL(tme_machine_sun3,obie) {
781: return (tme_sun_obie(element, args, _output));
782: }
783:
784: /* this creates a new Sun-3 bwtwo: */
785: TME_ELEMENT_SUB_NEW_DECL(tme_machine_sun3,bwtwo) {
786: return (tme_sun_bwtwo(element, args, _output));
787: }
788:
789: /* this creates a new Sun-3 si: */
790: TME_ELEMENT_SUB_NEW_DECL(tme_machine_sun3,si) {
791: return (tme_sun_si(element, args, _output));
792: }
793:
794: /* this creates a new Sun-3 cgtwo: */
795: TME_ELEMENT_SUB_NEW_DECL(tme_machine_sun3,cgtwo) {
796: return (tme_sun_cgtwo(element, args, _output));
797: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.