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