|
|
1.1 ! root 1: /* $Id: sun4-mainbus.c,v 1.5 2007/02/15 01:32:14 fredette Exp $ */ ! 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> ! 37: _TME_RCSID("$Id: sun4-mainbus.c,v 1.5 2007/02/15 01:32:14 fredette Exp $"); ! 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: ! 409: if (conn_bus->tme_bus_tlb_set_allocate == NULL ! 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: ! 419: if ((conn_bus->tme_bus_tlb_set_allocate != NULL ! 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; ! 516: conn_bus->tme_bus_tlb_set_allocate ! 517: = (TME_SUN4_IS_SUN44C(sun4) ! 518: ? _tme_sun44c_mmu_tlb_set_allocate ! 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) { ! 679: conn_bus->tme_bus_tlb_set_allocate = _tme_sun44c_mmu_tlb_set_allocate; ! 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) { ! 760: tme_output_append_error(_output, idprom_filename); ! 761: return (errno); ! 762: } ! 763: if (fread(idprom, sizeof(tme_uint8_t), sizeof(idprom), idprom_fp) != sizeof(idprom)) { ! 764: tme_output_append_error(_output, idprom_filename); ! 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.