|
|
1.1.1.2 root 1: /* $Id: sun4-mainbus.c,v 1.6 2009/08/30 14:03:11 fredette Exp $ */
1.1 root 2:
3: /* machine/sun4/sun4-mainbus.c - implementation of Sun 4 emulation: */
4:
5: /*
6: * Copyright (c) 2003, 2004, 2006 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.2 root 37: _TME_RCSID("$Id: sun4-mainbus.c,v 1.6 2009/08/30 14:03:11 fredette Exp $");
1.1 root 38:
39: /* includes: */
40: #include "sun4-impl.h"
41: #include <tme/ic/z8530.h>
42: #include <tme/ic/isil7170.h>
43: #include <tme/ic/mk48txx.h>
44: #include <stdio.h>
45:
46: /* this possibly updates that the interrupt priority level driven to the CPU: */
47: int
48: _tme_sun4_ipl_check(struct tme_sun4 *sun4)
49: {
50: unsigned int ipl;
51: unsigned int ipl_index;
52: tme_uint8_t ipl_mask;
53: tme_uint32_t interreg;
54: int rc;
55:
56: /* find the highest ipl now asserted on the buses, that is enabled
57: to the CPU: */
58: ipl = TME_SPARC_IPL_MAX;
59: ipl_index = ipl / 8;
60: ipl_mask = TME_BIT(ipl % 8);
61: do {
62:
63: /* if this ipl is asserted: */
64: if ((sun4->tme_sun4_int_signals[ipl_index] & ipl_mask) != 0) {
65:
66: /* if this ipl is not disabled: */
67: if (TME_SUN4_IS_SUN44C(sun4)
68: ? ((sun4->tme_sun44c_ints & TME_SUN44C_IREG_INTS_ENAB)
69: && (ipl != 10 || (sun4->tme_sun44c_ints & TME_SUN44C_IREG_COUNTER_L10))
70: && (ipl != 14 || (sun4->tme_sun44c_ints & TME_SUN44C_IREG_COUNTER_L14)))
71: : TRUE) {
72:
73: /* stop now: */
74: break;
75: }
76: }
77:
78: /* advance to the next ipl: */
79: ipl--;
80: ipl_mask >>= 1;
81: if (ipl_mask == 0) {
82: ipl_mask = 0x80;
83: ipl_index--;
84: }
85: } while (ipl != TME_SPARC_IPL_NONE);
86:
87: /* if this is a sun4 or sun4c: */
88: if (TME_SUN4_IS_SUN44C(sun4)) {
89:
90: /* get the sun4/4c interrupt register: */
91: interreg = sun4->tme_sun44c_ints;
92:
93: /* if interrupts are enabled: */
94: if (interreg & TME_SUN44C_IREG_INTS_ENAB) {
95:
96: /* check the soft interrupts: */
97: if (interreg & TME_SUN44C_IREG_SOFT_INT_L6) {
98: ipl = TME_MAX(ipl, 6);
99: }
100: else if (interreg & TME_SUN44C_IREG_SOFT_INT_L4) {
101: ipl = TME_MAX(ipl, 4);
102: }
103: else if (interreg & TME_SUN44C_IREG_SOFT_INT_L1) {
104: ipl = TME_MAX(ipl, 1);
105: }
106: }
107: }
108:
109: /* possibly update the CPU: */
110: if (ipl != sun4->tme_sun4_int_ipl_last) {
111: sun4->tme_sun4_int_ipl_last = ipl;
112: rc = ((*sun4->tme_sun4_sparc->tme_sparc_bus_interrupt)
113: (sun4->tme_sun4_sparc, ipl));
114: assert (rc == TME_OK);
115: }
116:
117: /* return nonzero if any interrupt is pending: */
118: return (ipl != TME_SPARC_IPL_NONE);
119: }
120:
121: /* our mainbus signal handler: */
122: static int
123: _tme_sun4_bus_signal(struct tme_bus_connection *conn_bus_raiser, unsigned int signal)
124: {
125: struct tme_sun4 *sun4;
126: int signal_asserted;
127: unsigned int ipl, ipl_index;
128: tme_uint8_t ipl_mask;
129:
130: /* recover our sun4: */
131: sun4 = (struct tme_sun4 *) conn_bus_raiser->tme_bus_connection.tme_connection_element->tme_element_private;
132:
133: /* see whether the signal is asserted or negated: */
134: signal_asserted = TRUE;
135: switch (signal & TME_BUS_SIGNAL_LEVEL_MASK) {
136: case TME_BUS_SIGNAL_LEVEL_NEGATED:
137: signal_asserted = FALSE;
138: case TME_BUS_SIGNAL_LEVEL_ASSERTED:
139: break;
140: default:
141: abort();
142: }
143: signal = TME_BUS_SIGNAL_WHICH(signal);
144:
145: /* dispatch on the signal: */
146:
147: /* halt: */
148: if (signal == TME_BUS_SIGNAL_HALT) {
149: abort();
150: }
151:
152: /* reset: */
153: else if (signal == TME_BUS_SIGNAL_RESET) {
154: /* XXX reset is just ignored for now: */
155: }
156:
157: /* an interrupt signal: */
158: else if (TME_BUS_SIGNAL_IS_INT(signal)) {
159: ipl = TME_BUS_SIGNAL_INDEX_INT(signal);
160: if (ipl >= TME_SPARC_IPL_MIN
161: && ipl <= TME_SPARC_IPL_MAX) {
162:
163: /* update this ipl in the byte array: */
164: ipl_index = ipl / 8;
165: ipl_mask = TME_BIT(ipl % 8);
166: sun4->tme_sun4_int_signals[ipl_index]
167: = ((sun4->tme_sun4_int_signals[ipl_index]
168: & ~ipl_mask)
169: | (signal_asserted
170: ? ipl_mask
171: : 0));
172:
173: /* possibly update the ipl being driven to the CPU: */
174: _tme_sun4_ipl_check(sun4);
175: return (TME_OK);
176: }
177: }
178:
179: /* an unknown signal: */
180: else {
181: abort();
182: }
183:
184: return (TME_OK);
185: }
186:
187: /* this handles a CPU interrupt acknowledge: */
188: static int
189: _tme_sun4_bus_intack(struct tme_bus_connection *conn_sparc, unsigned int ipl, int *vector)
190: {
191: struct tme_sun4 *sun4;
192: tme_uint32_t interreg;
193: unsigned int signal;
194: int rc;
195:
196: /* recover our sun4: */
197: sun4 = (struct tme_sun4 *) conn_sparc->tme_bus_connection.tme_connection_element->tme_element_private;
198:
199: /* acknowledge any soft interrupt: */
200: if (TME_SUN4_IS_SUN44C(sun4)) {
201: interreg = sun4->tme_sun44c_ints;
202: if ((ipl == 6
203: && (interreg & TME_SUN44C_IREG_SOFT_INT_L6))
204: || (ipl == 4
205: && (interreg & TME_SUN44C_IREG_SOFT_INT_L4))
206: || (ipl == 1
207: && (interreg & TME_SUN44C_IREG_SOFT_INT_L1))) {
208: *vector = TME_BUS_INTERRUPT_VECTOR_UNDEF;
209: return (TME_OK);
210: }
211: }
212:
213: /* turn the ipl into a bus signal number: */
214: signal = TME_BUS_SIGNAL_INT(ipl);
215:
216: /* try the acknowledge on these buses, in order: */
217:
218: /* obio: */
219: rc = (*sun4->tme_sun4_32_obio->tme_bus_intack)
220: (sun4->tme_sun4_32_obio, signal, vector);
221: if (rc != ENOENT) {
222: return (rc);
223: }
224: /* obmem: */
225: if (!TME_SUN4_IS_SUN4C(sun4)) {
226: rc = (*sun4->tme_sun4_32_obmem->tme_bus_intack)
227: (sun4->tme_sun4_32_obmem, signal, vector);
228: if (rc != ENOENT) {
229: return (rc);
230: }
231: }
232: /* VMEbus: */
233: if (TME_SUN4_IS_SUN4(sun4)) {
234: rc = (*sun4->tme_sun4_vmebus->tme_bus_intack)
235: (sun4->tme_sun4_vmebus, signal, vector);
236: if (rc != ENOENT) {
237: return (rc);
238: }
239: }
240:
241: /* done: */
242: return (rc);
243: }
244:
245: /* this resets the board: */
246: int
247: _tme_sun4_reset(struct tme_sun4 *sun4, int soft)
248: {
249:
250: /* clear the sun4/4c enable register: */
251: sun4->tme_sun44c_enable = 0;
252:
253: /* clear the sun4/4c interrupt register: */
254: sun4->tme_sun44c_ints = 0;
255:
256: /* clear any NMI: */
257: sun4->tme_sun4_int_signals[TME_SPARC_IPL_NMI / 8] &= ~TME_BIT(TME_SPARC_IPL_NMI % 8);
258:
259: /* reset the CPU: */
260: (*sun4->tme_sun4_sparc->tme_sparc_bus_connection.tme_bus_signal)
261: (&sun4->tme_sun4_sparc->tme_sparc_bus_connection,
262: TME_BUS_SIGNAL_RESET
263: | TME_BUS_SIGNAL_LEVEL_NEGATED
264: | TME_BUS_SIGNAL_EDGE);
265:
266: /* reset all busses: */
267: (*sun4->tme_sun4_32_obio->tme_bus_signal)
268: (sun4->tme_sun4_32_obio,
269: TME_BUS_SIGNAL_RESET
270: | TME_BUS_SIGNAL_LEVEL_NEGATED
271: | TME_BUS_SIGNAL_EDGE);
272: if (!TME_SUN4_IS_SUN4C(sun4)) {
273: (*sun4->tme_sun4_32_obmem->tme_bus_signal)
274: (sun4->tme_sun4_32_obmem,
275: TME_BUS_SIGNAL_RESET
276: | TME_BUS_SIGNAL_LEVEL_NEGATED
277: | TME_BUS_SIGNAL_EDGE);
278: }
279: if (TME_SUN4_IS_SUN4(sun4)) {
280: (*sun4->tme_sun4_vmebus->tme_bus_signal)
281: (sun4->tme_sun4_vmebus,
282: TME_BUS_SIGNAL_RESET
283: | TME_BUS_SIGNAL_LEVEL_NEGATED
284: | TME_BUS_SIGNAL_EDGE);
285: }
286:
287: /* in case this reset was caused by a bus cycle, be sure to tell the
288: initiator to check for a synchronous event: */
289: return (TME_BUS_CYCLE_SYNCHRONOUS_EVENT);
290: }
291:
292: /* our command function: */
293: static int
294: _tme_sun4_command(struct tme_element *element, const char * const * args, char **_output)
295: {
296: struct tme_sun4 *sun4;
297: int do_reset;
298:
299: /* recover our sun4: */
300: sun4 = (struct tme_sun4 *) element->tme_element_private;
301:
302: /* assume no reset: */
303: do_reset = FALSE;
304:
305: /* the "power" command: */
306: if (TME_ARG_IS(args[1], "power")) {
307:
308: if (TME_ARG_IS(args[2], "up")
309: && args[3] == NULL) {
310: do_reset = TRUE;
311: }
312:
313: else if (TME_ARG_IS(args[2], "down")
314: && args[3] == NULL) {
315: /* nothing */
316: }
317:
318: /* return an error: */
319: else {
320: tme_output_append_error(_output,
321: "%s %s power [ up | down ]",
322: _("usage:"),
323: args[0]);
324: return (EINVAL);
325: }
326: }
327:
328: /* the "diag-switch" command: */
329: else if (TME_SUN4_IS_SUN4(sun4)
330: && TME_ARG_IS(args[1], "diag-switch")) {
331:
332: if (args[2] == NULL) {
333: tme_output_append_error(_output,
334: "diag-switch %s",
335: (sun4->tme_sun44c_enable & TME_SUN4_ENA_DIAG
336: ? "true"
337: : "false"));
338: }
339:
340: else if (TME_ARG_IS(args[2], "true")
341: && args[3] == NULL) {
342: sun4->tme_sun44c_enable |= TME_SUN4_ENA_DIAG;
343: }
344:
345: else if (TME_ARG_IS(args[2], "false")
346: && args[3] == NULL) {
347: sun4->tme_sun44c_enable &= ~TME_SUN4_ENA_DIAG;
348: }
349:
350: /* return an error: */
351: else {
352: tme_output_append_error(_output,
353: "%s %s diag-switch [ true | false ]",
354: _("usage:"),
355: args[0]);
356: return (EINVAL);
357: }
358: }
359:
360: /* any other command: */
361: else {
362: if (args[1] != NULL) {
363: tme_output_append_error(_output,
364: "%s '%s', ",
365: _("unknown command"),
366: args[1]);
367: }
368: tme_output_append_error(_output,
369: _("available %s commands: %s%s"),
370: args[0],
371: "power",
372: (TME_SUN4_IS_SUN4(sun4)
373: ? "diag-switch"
374: : ""));
375: return (EINVAL);
376: }
377:
378: if (do_reset) {
379: _tme_sun4_reset(sun4, FALSE);
380: }
381:
382: return (TME_OK);
383: }
384:
385: /* the connection scorer: */
386: static int
387: _tme_sun4_connection_score(struct tme_connection *conn, unsigned int *_score)
388: {
389: struct tme_sparc_bus_connection *conn_sparc;
390: struct tme_sun4_bus_connection *conn_sun4;
391: struct tme_bus_connection *conn_bus;
392: struct tme_sun4 *sun4;
393: unsigned int score;
394:
395: /* recover our sun4: */
396: sun4 = (struct tme_sun4 *) conn->tme_connection_element->tme_element_private;
397:
398: /* assume that this connection is useless: */
399: score = 0;
400:
401: /* dispatch on the connection type: */
402: conn_sparc = (struct tme_sparc_bus_connection *) conn->tme_connection_other;
403: conn_sun4 = (struct tme_sun4_bus_connection *) conn;
404: conn_bus = (struct tme_bus_connection *) conn->tme_connection_other;
405: switch (conn->tme_connection_type) {
406:
407: /* this must be an SPARC chip, and not another bus: */
408: case TME_CONNECTION_BUS_SPARC:
1.1.1.2 root 409: if (conn_bus->tme_bus_tlb_set_add == NULL
1.1 root 410: && conn_sparc->tme_sparc_bus_tlb_fill == NULL
411: && conn_sparc->tme_sparc_bus_fpu_strict != NULL) {
412: score = 10;
413: }
414: break;
415:
416: /* this must be a bus, and not a chip, and the bus must still be
417: free: */
418: case TME_CONNECTION_BUS_GENERIC:
1.1.1.2 root 419: if ((conn_bus->tme_bus_tlb_set_add != NULL
1.1 root 420: && conn_bus->tme_bus_tlb_fill != NULL)
421: && (conn_sun4->tme_sun4_bus_connection_which >= TME_SUN4_32_CONN_BUS_COUNT
422: || sun4->tme_sun4_buses[conn_sun4->tme_sun4_bus_connection_which] == NULL)) {
423: score = 1;
424: }
425: break;
426:
427: default: abort();
428: }
429:
430: *_score = score;
431: return (TME_OK);
432: }
433:
434: /* this makes a new connection: */
435: static int
436: _tme_sun4_connection_make(struct tme_connection *conn, unsigned int state)
437: {
438: struct tme_sun4 *sun4;
439: struct tme_sparc_bus_connection *conn_sparc;
440: struct tme_sun4_bus_connection *conn_sun4;
441: struct tme_bus_connection *conn_bus;
442: struct tme_connection *conn_other;
443:
444: /* recover our sun4: */
445: sun4 = (struct tme_sun4 *) conn->tme_connection_element->tme_element_private;
446:
447: /* dispatch on the connection type: */
448: conn_other = conn->tme_connection_other;
449: conn_sparc = (struct tme_sparc_bus_connection *) conn_other;
450: conn_sun4 = (struct tme_sun4_bus_connection *) conn;
451: conn_bus = (struct tme_bus_connection *) conn_other;
452: switch (conn->tme_connection_type) {
453:
454: case TME_CONNECTION_BUS_SPARC:
455: sun4->tme_sun4_sparc = conn_sparc;
456: break;
457:
458: case TME_CONNECTION_BUS_GENERIC:
459:
460: /* remember the connection to this bus: */
461: if (state == TME_CONNECTION_FULL) {
462: assert (sun4->tme_sun4_buses[conn_sun4->tme_sun4_bus_connection_which] == NULL);
463: sun4->tme_sun4_buses[conn_sun4->tme_sun4_bus_connection_which] = conn_bus;
464: }
465: break;
466:
467: default:
468: assert(FALSE);
469: break;
470: }
471: return (TME_OK);
472: }
473:
474: /* this breaks a connection: */
475: static int
476: _tme_sun4_connection_break(struct tme_connection *conn, unsigned int state)
477: {
478: abort();
479: }
480:
481: /* this makes new connection sides: */
482: static int
483: _tme_sun4_connections_new(struct tme_element *element, const char * const *args, struct tme_connection **_conns, char **_output)
484: {
485: struct tme_sparc_bus_connection *conn_sparc;
486: struct tme_sun4_bus_connection *conn_sun4;
487: struct tme_bus_connection *conn_bus;
488: struct tme_connection *conn;
489: struct tme_sun4 *sun4;
490: char *free_buses;
491: int which_conn;
492:
493: /* recover our sun4: */
494: sun4 = (struct tme_sun4 *) element->tme_element_private;
495:
496: /* if we have no arguments, and we don't have a CPU yet, we can take
497: a SPARC bus connection: */
498: if (args[1] == NULL
499: && sun4->tme_sun4_sparc == NULL) {
500:
501: /* create our side of a SPARC bus connection: */
502: conn_sparc = tme_new0(struct tme_sparc_bus_connection, 1);
503: conn_bus = &conn_sparc->tme_sparc_bus_connection;
504: conn = &conn_bus->tme_bus_connection;
505: conn->tme_connection_next = *_conns;
506:
507: /* fill in the generic connection: */
508: conn->tme_connection_type = TME_CONNECTION_BUS_SPARC;
509: conn->tme_connection_score = _tme_sun4_connection_score;
510: conn->tme_connection_make = _tme_sun4_connection_make;
511: conn->tme_connection_break = _tme_sun4_connection_break;
512:
513: /* fill in the generic bus connection: */
514: conn_bus->tme_bus_signal = _tme_sun4_bus_signal;
515: conn_bus->tme_bus_intack = _tme_sun4_bus_intack;
1.1.1.2 root 516: conn_bus->tme_bus_tlb_set_add
1.1 root 517: = (TME_SUN4_IS_SUN44C(sun4)
1.1.1.2 root 518: ? _tme_sun44c_mmu_tlb_set_add
1.1 root 519: : NULL);
520:
521: /* full in the SPARC bus connection: */
522: conn_sparc->tme_sparc_bus_tlb_fill
523: = (TME_SUN4_IS_SUN44C(sun4)
524: ? _tme_sun44c_tlb_fill_sparc
525: : NULL);
526:
527: /* add in this connection side possibility: */
528: *_conns = conn;
529: }
530:
531: /* create our side of a generic bus connection: */
532: conn_sun4 = tme_new0(struct tme_sun4_bus_connection, 1);
533: conn_bus = &conn_sun4->tme_sun4_bus_connection;
534: conn = &conn_bus->tme_bus_connection;
535: conn->tme_connection_next = *_conns;
536:
537: /* fill in the generic connection: */
538: conn->tme_connection_type = TME_CONNECTION_BUS_GENERIC;
539: conn->tme_connection_score = _tme_sun4_connection_score;
540: conn->tme_connection_make = _tme_sun4_connection_make;
541: conn->tme_connection_break = _tme_sun4_connection_break;
542:
543: /* fill in the generic bus connection: */
544: conn_bus->tme_bus_signal = _tme_sun4_bus_signal;
545: conn_bus->tme_bus_intack = NULL;
546: if (TME_SUN4_IS_SUN44C(sun4)) {
547: conn_bus->tme_bus_tlb_fill = _tme_sun44c_tlb_fill_bus;
548: }
549: else {
550: abort();
551: }
552:
553: /* if we have no argument: */
554: if (args[1] == NULL) {
555:
556: /* return no more connections: */
557: tme_free(conn_sun4);
558: return (TME_OK);
559: }
560:
561: /* otherwise, we have at least one argument: */
562: else {
563:
564: /* we must have no other arguments: */
565: if (args[2] != NULL) {
566: tme_output_append_error(_output,
567: "%s %s",
568: args[2],
569: _("unexpected"));
570: tme_free(conn_sun4);
571: return (EINVAL);
572: }
573:
574: /* start the list of buses that we don't have yet: */
575: free_buses = NULL;
576:
577: /* poison the which connection: */
578: which_conn = -1;
579:
580: /* check each bus: */
581:
582: /* obio: */
583: if (sun4->tme_sun4_32_obio == NULL) {
584: tme_output_append(&free_buses,
585: (TME_SUN4_IS_SUN4C(sun4)
586: ? " sbus"
587: : " obio"));
588: }
589: if (TME_ARG_IS(args[1],
590: (TME_SUN4_IS_SUN4C(sun4)
591: ? "sbus"
592: : "obio"))) {
593: which_conn = TME_SUN4_32_CONN_BUS_OBIO;
594: }
595:
596: /* obmem: */
597: if (!TME_SUN4_IS_SUN4C(sun4)) {
598: if (sun4->tme_sun4_32_obmem == NULL) {
599: tme_output_append(&free_buses, " obmem");
600: }
601: if (TME_ARG_IS(args[1], "obmem")) {
602: which_conn = TME_SUN4_32_CONN_BUS_OBMEM;
603: }
604: }
605:
606: /* VMEbus: */
607: if (TME_SUN4_IS_SUN4(sun4)) {
608: if (sun4->tme_sun4_vmebus == NULL) {
609: tme_output_append(&free_buses, " vme");
610: }
611: if (TME_ARG_IS(args[1], "vme")) {
612: which_conn = TME_SUN4_CONN_BUS_VME;
613: conn_bus->tme_bus_subregions.tme_bus_subregion_address_last
614: = TME_SUN4_DVMA_SIZE_VME;
615: }
616: }
617:
618: /* random connections: */
619:
620: if (TME_ARG_IS(args[1], "timer")) {
621: which_conn = TME_SUN4_32_CONN_REG_TIMER;
622: conn_bus->tme_bus_subregions.tme_bus_subregion_address_last
623: = TME_SUN44C_TIMER_SIZ_REG * 2;
624: }
625: else if (TME_ARG_IS(args[1], "memerr")) {
626: which_conn = TME_SUN4_32_CONN_REG_MEMERR;
627: conn_bus->tme_bus_subregions.tme_bus_subregion_address_last
628: = (TME_SUN4_IS_MODEL(sun4, TME_SUN_IDPROM_TYPE_CODE_CALVIN)
629: ? (TME_SUN44C_MEMERR_SIZ_REG * 2)
630: : TME_SUN44C_MEMERR_SIZ_REG);
631: }
632: else if (TME_ARG_IS(args[1], "intreg")) {
633: which_conn = TME_SUN4_32_CONN_REG_INTREG;
634: conn_bus->tme_bus_subregions.tme_bus_subregion_address_last
635: = sizeof(sun4->tme_sun44c_ints);
636: }
637: else if (TME_SUN4_IS_SUN4C4M(sun4)
638: && TME_ARG_IS(args[1], "auxreg")) {
639: which_conn = TME_SUN4C4M_CONN_REG_AUXREG;
640: conn_bus->tme_bus_subregions.tme_bus_subregion_address_last
641: = sizeof(sun4->tme_sun4c4m_aux);
642: }
643:
644: /* if the which connection is still poison, or if this is trying
645: to connect a bus that we already have, complain: */
646: if (which_conn < 0
647: || (which_conn < TME_SUN4_32_CONN_BUS_COUNT
648: && sun4->tme_sun4_buses[which_conn] != NULL)) {
649: if (which_conn < 0) {
650: tme_output_append_error(_output,
651: "%s %s ",
652: _("unknown bus or register:"),
653: args[1]);
654: }
655: if (free_buses != NULL) {
656: tme_output_append_error(_output,
657: "%s %s",
658: _("remaining buses:"),
659: free_buses);
660: tme_free(free_buses);
661: }
662: else {
663: tme_output_append_error(_output, _("all buses present"));
664: }
665: tme_free(conn_sun4);
666: return (EINVAL);
667: }
668:
669: /* free the remaining bus list: */
670: if (free_buses != NULL) {
671: tme_free(free_buses);
672: }
673:
674: /* fill in the sun4 connection: */
675: conn_sun4->tme_sun4_bus_connection_which = which_conn;
676:
677: /* fill in the generic bus connection for a bus: */
678: if (which_conn < TME_SUN4_32_CONN_BUS_COUNT) {
1.1.1.2 root 679: conn_bus->tme_bus_tlb_set_add = _tme_sun44c_mmu_tlb_set_add;
1.1 root 680: }
681: }
682:
683: /* add in this connection side possibility: */
684: *_conns = conn;
685:
686: /* done: */
687: return (TME_OK);
688: }
689:
690: /* this creates a new sun4 element: */
691: TME_ELEMENT_NEW_DECL(tme_machine_sun4) {
692: int usage;
693: struct tme_sun4 *sun4;
694: const char *idprom_filename;
695: FILE *idprom_fp;
696: tme_uint8_t idprom[TME_SUN_IDPROM_SIZE];
697: int arg_i;
698:
699: arg_i = 1;
700: usage = FALSE;
701:
702: /* if we've been given an IDPROM filename: */
703: idprom_filename = NULL;
704: if (TME_ARG_IS(args[arg_i], "idprom")) {
705: arg_i++;
706: idprom_filename = args[arg_i];
707: if (idprom_filename == NULL) {
708: usage = TRUE;
709: }
710: else {
711: arg_i++;
712: }
713: }
714:
715: /* otherwise, if we've been given a board name: */
716: else if (TME_ARG_IS(args[arg_i], "name")) {
717: arg_i++;
718: if (TME_ARG_IS(args[arg_i], "Calvin")) {
719: idprom[TME_SUN_IDPROM_OFF_MACHTYPE] = TME_SUN_IDPROM_TYPE_CODE_CALVIN;
720: arg_i++;
721: }
722: else if (args[arg_i] != NULL) {
723: tme_output_append_error(_output,
724: "%s %s, ",
725: _("unknown name"),
726: args[arg_i]);
727: usage = TRUE;
728: }
729: else {
730: tme_output_append_error(_output,
731: "%s, ",
732: _("missing name"));
733: usage = TRUE;
734: }
735: }
736:
737: /* we must have no more arguments: */
738: if (args[arg_i] != NULL) {
739: tme_output_append_error(_output,
740: "%s %s, ",
741: args[arg_i],
742: _("unexpected"));
743: usage = TRUE;
744: }
745:
746: /* if our usage was bad: */
747: if (usage) {
748: tme_output_append_error(_output,
749: "%s %s { idprom IDPROM%s | name { Calvin } } ",
750: _("usage:"),
751: args[0],
752: _("-FILENAME"));
753: return (EINVAL);
754: }
755:
756: /* if we've been given an IDPROM filename, try to read it in: */
757: if (idprom_filename != NULL) {
758: idprom_fp = fopen(idprom_filename, "r");
759: if (idprom_fp == NULL) {
1.1.1.3 ! root 760: tme_output_append_error(_output, "%s", idprom_filename);
1.1 root 761: return (errno);
762: }
763: if (fread(idprom, sizeof(tme_uint8_t), sizeof(idprom), idprom_fp) != sizeof(idprom)) {
1.1.1.3 ! root 764: tme_output_append_error(_output, "%s", idprom_filename);
1.1 root 765: fclose(idprom_fp);
766: return (ENOEXEC);
767: }
768: fclose(idprom_fp);
769: }
770:
771: /* allocate and initialize the new sun4: */
772: sun4 = tme_new0(struct tme_sun4, 1);
773: sun4->tme_sun4_element = element;
774: tme_mutex_init(&sun4->tme_sun4_mutex);
775:
776: /* set the IDPROM: */
777: memcpy(sun4->tme_sun4_idprom_contents, idprom, sizeof(idprom));
778:
779: /* the MMU: */
780: if (TME_SUN4_IS_SUN44C(sun4)) {
781: _tme_sun44c_mmu_new(sun4);
782: sun4->tme_sun4_tlb_fill = _tme_sun44c_tlb_fill_mmu;
783: }
784: else {
785: abort();
786: }
787:
788: /* the cache: */
789: if (TME_SUN4_IS_SUN44C(sun4)) {
790: _tme_sun44c_cache_new(sun4);
791: }
792: else {
793: abort();
794: }
795:
796: /* the control ASIs: */
797: sun4->tme_sun4_asis[TME_SUN4_32_ASI_CONTROL].tme_sun4_asi_sun4 = sun4;
798: if (TME_SUN4_IS_SUN44C(sun4)) {
799: sun4->tme_sun4_asis[TME_SUN44C_ASI_SEGMAP].tme_sun4_asi_sun4 = sun4;
800: sun4->tme_sun4_asis[TME_SUN44C_ASI_PGMAP].tme_sun4_asi_sun4 = sun4;
801: sun4->tme_sun4_asis[TME_SUN4C_ASI_HW_FLUSH_SEG /* TME_SUN4_ASI_COPY */].tme_sun4_asi_sun4 = sun4;
802: sun4->tme_sun4_asis[TME_SUN4C_ASI_HW_FLUSH_PG /* TME_SUN4_ASI_REGMAP */].tme_sun4_asi_sun4 = sun4;
803: sun4->tme_sun4_asis[TME_SUN4C_ASI_HW_FLUSH_CONTEXT /* TME_SUN4_ASI_FLUSH_REG */].tme_sun4_asi_sun4 = sun4;
804: sun4->tme_sun4_asis[TME_SUN44C_ASI_FLUSH_SEG].tme_sun4_asi_sun4 = sun4;
805: sun4->tme_sun4_asis[TME_SUN44C_ASI_FLUSH_PG].tme_sun4_asi_sun4 = sun4;
806: sun4->tme_sun4_asis[TME_SUN44C_ASI_FLUSH_CONTEXT].tme_sun4_asi_sun4 = sun4;
807: sun4->tme_sun4_asis[TME_SUN4C_ASI_HW_FLUSH_ALL /* TME_SUN4_ASI_FLUSH_USER */].tme_sun4_asi_sun4 = sun4;
808: }
809: else {
810: abort();
811: }
812:
813: /* the timers: */
814: _tme_sun4_timer_new(sun4);
815:
816: /* fill the element: */
817: element->tme_element_private = sun4;
818: element->tme_element_connections_new = _tme_sun4_connections_new;
819: element->tme_element_command = _tme_sun4_command;
820:
821: return (TME_OK);
822: }
823:
824: /* this creates a new Sun-4 isil7170: */
825: TME_ELEMENT_SUB_NEW_DECL(tme_machine_sun4,oclock) {
826: struct tme_isil7170_socket socket;
827: const char *sub_args[4];
828: int arg_i;
829:
830: /* create the isil7170 socket: */
831: memset (&socket, 0, sizeof(socket));
832: socket.tme_isil7170_socket_version = TME_ISIL7170_SOCKET_0;
833: socket.tme_isil7170_socket_addr_shift = 0;
834: socket.tme_isil7170_socket_port_least_lane = 3; /* D31-D24 */
835: socket.tme_isil7170_socket_clock_basic = TME_ISIL7170_FREQ_32K;
836: socket.tme_isil7170_socket_int_signal = TME_BUS_SIGNAL_INT_UNSPEC;
837:
838: /* create the isil7170. we allow at most two arguments to pass
839: through, which is an awful hack: */
840: sub_args[0] = "tme/ic/isil7170";
841: for (arg_i = 1;; arg_i++) {
842: if (arg_i == TME_ARRAY_ELS(sub_args)) {
843: abort();
844: }
845: sub_args[arg_i] = args[arg_i];
846: if (args[arg_i] == NULL) {
847: break;
848: }
849: }
850: return (tme_element_new(element, (const char * const *) sub_args, &socket, _output));
851: }
852:
853: /* this creates a new Sun-4 mk48txx: */
854: TME_ELEMENT_SUB_NEW_DECL(tme_machine_sun4,clock) {
855: struct tme_mk48txx_socket socket;
856:
857: /* create the mk48txx socket: */
858: memset (&socket, 0, sizeof(socket));
859: socket.tme_mk48txx_socket_version = TME_MK48TXX_SOCKET_0;
860: socket.tme_mk48txx_socket_addr_shift = 0;
861: socket.tme_mk48txx_socket_port_least_lane = 3; /* D31-D24 */
862: socket.tme_mk48txx_socket_year_zero = 1968;
863:
864: if (!TME_ARG_IS(args[1], "type")
865: || args[2] == NULL) {
866: tme_output_append_error(_output,
867: "%s %s type CLOCK-%s",
868: _("usage:"),
869: args[0],
870: _("TYPE"));
871: return (EINVAL);
872: }
873:
874: return (tme_element_new(element, args + 2, &socket, _output));
875: }
876:
877: /* this creates a new Sun-4 z8530: */
878: TME_ELEMENT_SUB_NEW_DECL(tme_machine_sun4,zs) {
879: struct tme_z8530_socket socket = TME_SUN_Z8530_SOCKET_INIT;
880: char *sub_args[2];
881:
882: /* create the z8530: */
883: sub_args[0] = "tme/ic/z8530";
884: sub_args[1] = NULL;
885: return (tme_element_new(element, (const char * const *) sub_args, &socket, _output));
886: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.