|
|
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.