|
|
1.1 ! root 1: /* $Id: sun2-mainbus.c,v 1.10 2003/05/17 20:16:06 fredette Exp $ */ ! 2: ! 3: /* machine/sun2/sun2-mainbus.c - implementation of Sun 2 emulation: */ ! 4: ! 5: /* ! 6: * Copyright (c) 2003 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: sun2-mainbus.c,v 1.10 2003/05/17 20:16:06 fredette Exp $"); ! 38: ! 39: /* includes: */ ! 40: #include "sun2-impl.h" ! 41: #include <tme/ic/am9513.h> ! 42: #include <tme/ic/z8530.h> ! 43: #include <tme/ic/mm58167.h> ! 44: #include <stdio.h> ! 45: ! 46: /* macros: */ ! 47: ! 48: /* a sun2 mainbus connection: */ ! 49: struct tme_sun2_bus_connection { ! 50: ! 51: /* the generic bus connection: */ ! 52: struct tme_bus_connection tme_sun2_bus_connection; ! 53: ! 54: /* which bus this is: */ ! 55: unsigned int tme_sun2_bus_connection_which; ! 56: }; ! 57: ! 58: /* this possibly updates that the interrupt priority level driven to the CPU: */ ! 59: int ! 60: _tme_sun2_ipl_check(struct tme_sun2 *sun2) ! 61: { ! 62: tme_uint16_t ena; ! 63: unsigned int ipl, ipl_index; ! 64: tme_uint8_t ipl_mask; ! 65: ! 66: /* get the enable register: */ ! 67: ena = sun2->tme_sun2_enable; ! 68: ! 69: /* assume that interrupts are completely masked: */ ! 70: ipl = TME_M68K_IPL_NONE; ! 71: ! 72: /* if interrupts are enabled: */ ! 73: if (ena & TME_SUN2_ENA_INTS) { ! 74: ! 75: /* find the highest ipl now asserted on the buses: */ ! 76: for (ipl = TME_M68K_IPL_MAX; ! 77: ipl > TME_M68K_IPL_NONE; ! 78: ipl--) { ! 79: ipl_index = ipl >> 3; ! 80: ipl_mask = TME_BIT(ipl & 7); ! 81: if (sun2->tme_sun2_int_signals[ipl_index] & ipl_mask) { ! 82: break; ! 83: } ! 84: } ! 85: ! 86: /* check the soft interrupts: */ ! 87: if (ena & TME_SUN2_ENA_SOFT_INT_3) { ! 88: ipl = TME_MAX(ipl, 3); ! 89: } ! 90: else if (ena & TME_SUN2_ENA_SOFT_INT_2) { ! 91: ipl = TME_MAX(ipl, 2); ! 92: } ! 93: else if (ena & TME_SUN2_ENA_SOFT_INT_1) { ! 94: ipl = TME_MAX(ipl, 1); ! 95: } ! 96: } ! 97: ! 98: /* possibly update the CPU: */ ! 99: if (ipl != sun2->tme_sun2_int_ipl_last) { ! 100: sun2->tme_sun2_int_ipl_last = ipl; ! 101: return ((*sun2->tme_sun2_m68k->tme_m68k_bus_interrupt) ! 102: (sun2->tme_sun2_m68k, ipl)); ! 103: } ! 104: return (TME_OK); ! 105: } ! 106: ! 107: /* our mainbus signal handler: */ ! 108: static int ! 109: _tme_sun2_bus_signal(struct tme_bus_connection *conn_bus_raiser, unsigned int signal) ! 110: { ! 111: struct tme_sun2 *sun2; ! 112: int signal_asserted; ! 113: unsigned int ipl, ipl_index; ! 114: tme_uint8_t ipl_mask; ! 115: ! 116: /* recover our sun2: */ ! 117: sun2 = (struct tme_sun2 *) conn_bus_raiser->tme_bus_connection.tme_connection_element->tme_element_private; ! 118: ! 119: /* take out the level and edge. all of our signals are active low: */ ! 120: signal_asserted = TRUE; ! 121: switch (signal & TME_BUS_SIGNAL_LEVEL_MASK) { ! 122: case TME_BUS_SIGNAL_LEVEL_LOW: ! 123: case TME_BUS_SIGNAL_LEVEL_ASSERTED: ! 124: break; ! 125: case TME_BUS_SIGNAL_LEVEL_HIGH: ! 126: case TME_BUS_SIGNAL_LEVEL_NEGATED: ! 127: signal_asserted = FALSE; ! 128: break; ! 129: } ! 130: signal &= ~(TME_BUS_SIGNAL_LEVEL_MASK ! 131: | TME_BUS_SIGNAL_EDGE); ! 132: ! 133: /* dispatch on the signal: */ ! 134: ! 135: /* halt: */ ! 136: if (signal == TME_BUS_SIGNAL_HALT) { ! 137: abort(); ! 138: } ! 139: ! 140: /* reset: */ ! 141: else if (signal == TME_BUS_SIGNAL_RESET) { ! 142: abort(); ! 143: } ! 144: ! 145: /* an interrupt signal: */ ! 146: else if (TME_BUS_SIGNAL_IS_INT(signal)) { ! 147: ipl = TME_BUS_SIGNAL_WHICH_INT(signal); ! 148: if (ipl >= TME_M68K_IPL_MIN ! 149: && ipl <= TME_M68K_IPL_MAX) { ! 150: ! 151: /* update this ipl in the byte array: */ ! 152: ipl_index = ipl >> 3; ! 153: ipl_mask = TME_BIT(ipl & 7); ! 154: sun2->tme_sun2_int_signals[ipl_index] ! 155: = ((sun2->tme_sun2_int_signals[ipl_index] ! 156: & ~ipl_mask) ! 157: | (signal_asserted ! 158: ? ipl_mask ! 159: : 0)); ! 160: ! 161: /* possibly update the ipl being driven to the CPU: */ ! 162: return (_tme_sun2_ipl_check(sun2)); ! 163: } ! 164: } ! 165: ! 166: /* an unknown signal: */ ! 167: else { ! 168: abort(); ! 169: } ! 170: ! 171: return (TME_OK); ! 172: } ! 173: ! 174: /* this handles a CPU interrupt acknowledge: */ ! 175: static int ! 176: _tme_sun2_bus_intack(struct tme_bus_connection *conn_m68k, unsigned int ipl, int *vector) ! 177: { ! 178: struct tme_sun2 *sun2; ! 179: tme_uint16_t ena; ! 180: int signal; ! 181: int rc; ! 182: ! 183: /* recover our sun2: */ ! 184: sun2 = (struct tme_sun2 *) conn_m68k->tme_bus_connection.tme_connection_element->tme_element_private; ! 185: ! 186: /* acknowledge any soft interrupt: */ ! 187: ena = sun2->tme_sun2_enable; ! 188: if ((ipl == 3 ! 189: && (ena & TME_SUN2_ENA_SOFT_INT_3)) ! 190: || (ipl == 2 ! 191: && (ena & TME_SUN2_ENA_SOFT_INT_2)) ! 192: || (ipl == 1 ! 193: && (ena & TME_SUN2_ENA_SOFT_INT_1))) { ! 194: *vector = TME_BUS_INTERRUPT_VECTOR_UNDEF; ! 195: return (TME_OK); ! 196: } ! 197: ! 198: /* turn the ipl into a bus signal number: */ ! 199: signal = TME_BUS_SIGNAL_INT(ipl); ! 200: ! 201: /* try the acknowledge on these buses, in order: */ ! 202: ! 203: /* obio: */ ! 204: rc = (*sun2->tme_sun2_obio->tme_bus_intack) ! 205: (sun2->tme_sun2_obio, signal, vector); ! 206: if (rc != ENOENT) { ! 207: return (rc); ! 208: } ! 209: if (sun2->tme_sun2_has_vme) { ! 210: /* VME: */ ! 211: rc = (*sun2->tme_sun2_vmebus->tme_bus_intack) ! 212: (sun2->tme_sun2_vmebus, signal, vector); ! 213: if (rc != ENOENT) { ! 214: return (rc); ! 215: } ! 216: } ! 217: else { ! 218: /* mbio: */ ! 219: rc = (*sun2->tme_sun2_mbio->tme_bus_intack) ! 220: (sun2->tme_sun2_mbio, signal, vector); ! 221: if (rc != ENOENT) { ! 222: return (rc); ! 223: } ! 224: /* mbmem: */ ! 225: rc = (*sun2->tme_sun2_mbmem->tme_bus_intack) ! 226: (sun2->tme_sun2_mbmem, signal, vector); ! 227: if (rc != ENOENT) { ! 228: return (rc); ! 229: } ! 230: } ! 231: ! 232: /* done: */ ! 233: return (rc); ! 234: } ! 235: ! 236: /* our command function: */ ! 237: static int ! 238: _tme_sun2_command(struct tme_element *element, const char * const * args, char **_output) ! 239: { ! 240: struct tme_sun2 *sun2; ! 241: int do_reset; ! 242: ! 243: /* recover our sun2: */ ! 244: sun2 = (struct tme_sun2 *) element->tme_element_private; ! 245: ! 246: /* assume no reset: */ ! 247: do_reset = FALSE; ! 248: ! 249: /* the "power" command: */ ! 250: if (TME_ARG_IS(args[1], "power")) { ! 251: ! 252: if (TME_ARG_IS(args[2], "up") ! 253: && args[3] == NULL) { ! 254: do_reset = TRUE; ! 255: } ! 256: ! 257: else if (TME_ARG_IS(args[2], "down") ! 258: && args[3] == NULL) { ! 259: /* nothing */ ! 260: } ! 261: ! 262: /* return an error: */ ! 263: else { ! 264: tme_output_append_error(_output, ! 265: "%s %s power [ up | down ]", ! 266: _("usage:"), ! 267: args[0]); ! 268: return (EINVAL); ! 269: } ! 270: } ! 271: ! 272: /* any other command: */ ! 273: else { ! 274: if (args[1] != NULL) { ! 275: tme_output_append_error(_output, ! 276: "%s '%s', ", ! 277: _("unknown command"), ! 278: args[1]); ! 279: } ! 280: tme_output_append_error(_output, ! 281: _("available %s commands: %s"), ! 282: args[0], ! 283: "power"); ! 284: return (EINVAL); ! 285: } ! 286: ! 287: if (do_reset) { ! 288: ! 289: /* reset the MMU: */ ! 290: _tme_sun2_mmu_reset(sun2); ! 291: ! 292: /* reset the CPU: */ ! 293: (*sun2->tme_sun2_m68k->tme_m68k_bus_connection.tme_bus_signal) ! 294: (&sun2->tme_sun2_m68k->tme_m68k_bus_connection, ! 295: TME_BUS_SIGNAL_RESET ! 296: | TME_BUS_SIGNAL_LEVEL_NEGATED ! 297: | TME_BUS_SIGNAL_EDGE); ! 298: ! 299: /* reset all busses: */ ! 300: (*sun2->tme_sun2_obio->tme_bus_signal) ! 301: (sun2->tme_sun2_obio, ! 302: TME_BUS_SIGNAL_RESET ! 303: | TME_BUS_SIGNAL_LEVEL_NEGATED ! 304: | TME_BUS_SIGNAL_EDGE); ! 305: (*sun2->tme_sun2_obmem->tme_bus_signal) ! 306: (sun2->tme_sun2_obmem, ! 307: TME_BUS_SIGNAL_RESET ! 308: | TME_BUS_SIGNAL_LEVEL_NEGATED ! 309: | TME_BUS_SIGNAL_EDGE); ! 310: if (sun2->tme_sun2_has_vme) { ! 311: (*sun2->tme_sun2_vmebus->tme_bus_signal) ! 312: (sun2->tme_sun2_obmem, ! 313: TME_BUS_SIGNAL_RESET ! 314: | TME_BUS_SIGNAL_LEVEL_NEGATED ! 315: | TME_BUS_SIGNAL_EDGE); ! 316: } ! 317: else { ! 318: (*sun2->tme_sun2_mbio->tme_bus_signal) ! 319: (sun2->tme_sun2_mbio, ! 320: TME_BUS_SIGNAL_RESET ! 321: | TME_BUS_SIGNAL_LEVEL_NEGATED ! 322: | TME_BUS_SIGNAL_EDGE); ! 323: (*sun2->tme_sun2_mbmem->tme_bus_signal) ! 324: (sun2->tme_sun2_mbmem, ! 325: TME_BUS_SIGNAL_RESET ! 326: | TME_BUS_SIGNAL_LEVEL_NEGATED ! 327: | TME_BUS_SIGNAL_EDGE); ! 328: } ! 329: } ! 330: ! 331: return (TME_OK); ! 332: } ! 333: ! 334: /* the connection scorer: */ ! 335: static int ! 336: _tme_sun2_connection_score(struct tme_connection *conn, unsigned int *_score) ! 337: { ! 338: struct tme_m68k_bus_connection *conn_m68k; ! 339: struct tme_sun2_bus_connection *conn_sun2; ! 340: struct tme_bus_connection *conn_bus; ! 341: struct tme_sun2 *sun2; ! 342: unsigned int score; ! 343: ! 344: /* recover our sun2: */ ! 345: sun2 = (struct tme_sun2 *) conn->tme_connection_element->tme_element_private; ! 346: ! 347: /* assume that this connection is useless: */ ! 348: score = 0; ! 349: ! 350: /* dispatch on the connection type: */ ! 351: conn_m68k = (struct tme_m68k_bus_connection *) conn->tme_connection_other; ! 352: conn_sun2 = (struct tme_sun2_bus_connection *) conn; ! 353: conn_bus = (struct tme_bus_connection *) conn->tme_connection_other; ! 354: switch (conn->tme_connection_type) { ! 355: ! 356: /* this must be an m68k chip, and not another bus: */ ! 357: case TME_CONNECTION_BUS_M68K: ! 358: if (conn_bus->tme_bus_tlb_set_allocate == NULL ! 359: && conn_m68k->tme_m68k_bus_tlb_fill == NULL) { ! 360: score = 10; ! 361: } ! 362: break; ! 363: ! 364: /* this must be a bus, and not a chip: */ ! 365: case TME_CONNECTION_BUS_GENERIC: ! 366: if (conn_bus->tme_bus_tlb_set_allocate != NULL ! 367: && conn_bus->tme_bus_tlb_fill != NULL ! 368: && sun2->tme_sun2_buses[conn_sun2->tme_sun2_bus_connection_which] == NULL) { ! 369: score = 1; ! 370: } ! 371: break; ! 372: ! 373: default: abort(); ! 374: } ! 375: ! 376: *_score = score; ! 377: return (TME_OK); ! 378: } ! 379: ! 380: /* this makes a new connection: */ ! 381: static int ! 382: _tme_sun2_connection_make(struct tme_connection *conn, unsigned int state) ! 383: { ! 384: struct tme_sun2 *sun2; ! 385: struct tme_m68k_bus_connection *conn_m68k; ! 386: struct tme_sun2_bus_connection *conn_sun2; ! 387: struct tme_bus_connection *conn_bus; ! 388: struct tme_connection *conn_other; ! 389: ! 390: /* recover our sun2: */ ! 391: sun2 = (struct tme_sun2 *) conn->tme_connection_element->tme_element_private; ! 392: ! 393: /* dispatch on the connection type: */ ! 394: conn_other = conn->tme_connection_other; ! 395: conn_m68k = (struct tme_m68k_bus_connection *) conn_other; ! 396: conn_sun2 = (struct tme_sun2_bus_connection *) conn; ! 397: conn_bus = (struct tme_bus_connection *) conn_other; ! 398: switch (conn->tme_connection_type) { ! 399: ! 400: case TME_CONNECTION_BUS_M68K: ! 401: sun2->tme_sun2_m68k = conn_m68k; ! 402: break; ! 403: ! 404: case TME_CONNECTION_BUS_GENERIC: ! 405: sun2->tme_sun2_buses[conn_sun2->tme_sun2_bus_connection_which] = conn_bus; ! 406: break; ! 407: ! 408: default: assert(FALSE); ! 409: } ! 410: return (TME_OK); ! 411: } ! 412: ! 413: /* this breaks a connection: */ ! 414: static int ! 415: _tme_sun2_connection_break(struct tme_connection *conn, unsigned int state) ! 416: { ! 417: abort(); ! 418: } ! 419: ! 420: /* this makes new connection sides: */ ! 421: static int ! 422: _tme_sun2_connections_new(struct tme_element *element, const char * const *args, struct tme_connection **_conns, char **_output) ! 423: { ! 424: struct tme_m68k_bus_connection *conn_m68k; ! 425: struct tme_sun2_bus_connection *conn_sun2; ! 426: struct tme_bus_connection *conn_bus; ! 427: struct tme_connection *conn; ! 428: struct tme_sun2 *sun2; ! 429: char *free_buses; ! 430: int which_bus; ! 431: ! 432: /* recover our sun2: */ ! 433: sun2 = (struct tme_sun2 *) element->tme_element_private; ! 434: ! 435: /* if we have no arguments and don't have a CPU yet, we can take an m68k connection: */ ! 436: if (args[1] == NULL ! 437: && sun2->tme_sun2_m68k == NULL) { ! 438: ! 439: /* create our side of an m68k bus connection: */ ! 440: conn_m68k = tme_new0(struct tme_m68k_bus_connection, 1); ! 441: conn_bus = &conn_m68k->tme_m68k_bus_connection; ! 442: conn = &conn_bus->tme_bus_connection; ! 443: ! 444: /* fill in the generic connection: */ ! 445: conn->tme_connection_next = *_conns; ! 446: conn->tme_connection_type = TME_CONNECTION_BUS_M68K; ! 447: conn->tme_connection_score = _tme_sun2_connection_score; ! 448: conn->tme_connection_make = _tme_sun2_connection_make; ! 449: conn->tme_connection_break = _tme_sun2_connection_break; ! 450: ! 451: /* fill in the generic bus connection: */ ! 452: conn_bus->tme_bus_signal = _tme_sun2_bus_signal; ! 453: conn_bus->tme_bus_intack = _tme_sun2_bus_intack; ! 454: conn_bus->tme_bus_tlb_set_allocate = _tme_sun2_mmu_tlb_set_allocate; ! 455: ! 456: /* full in the m68k bus connection: */ ! 457: conn_m68k->tme_m68k_bus_tlb_fill = _tme_sun2_m68k_tlb_fill; ! 458: ! 459: /* add in this connection side possibility: */ ! 460: *_conns = conn; ! 461: } ! 462: ! 463: /* otherwise, we must have an argument and it must be for a bus that ! 464: we don't have yet: */ ! 465: else { ! 466: ! 467: free_buses = NULL; ! 468: which_bus = -1; ! 469: ! 470: if (sun2->tme_sun2_obio == NULL) { ! 471: tme_output_append(&free_buses, " obio"); ! 472: } ! 473: if (TME_ARG_IS(args[1], "obio")) { ! 474: which_bus = TME_SUN2_BUS_OBIO; ! 475: } ! 476: ! 477: if (sun2->tme_sun2_obio == NULL) { ! 478: tme_output_append(&free_buses, " obmem"); ! 479: } ! 480: if (TME_ARG_IS(args[1], "obmem")) { ! 481: which_bus = TME_SUN2_BUS_OBMEM; ! 482: } ! 483: ! 484: if (sun2->tme_sun2_has_vme) { ! 485: ! 486: if (sun2->tme_sun2_vmebus == NULL) { ! 487: tme_output_append(&free_buses, " vme"); ! 488: } ! 489: if (TME_ARG_IS(args[1], "vme")) { ! 490: which_bus = TME_SUN2_BUS_VME; ! 491: } ! 492: ! 493: } ! 494: ! 495: else { ! 496: ! 497: if (sun2->tme_sun2_mbio == NULL) { ! 498: tme_output_append(&free_buses, " mbio"); ! 499: } ! 500: if (TME_ARG_IS(args[1], "mbio")) { ! 501: which_bus = TME_SUN2_BUS_MBIO; ! 502: } ! 503: ! 504: if (sun2->tme_sun2_mbio == NULL) { ! 505: tme_output_append(&free_buses, " mbmem"); ! 506: } ! 507: if (TME_ARG_IS(args[1], "mbmem")) { ! 508: which_bus = TME_SUN2_BUS_MBMEM; ! 509: } ! 510: } ! 511: ! 512: if (args[1] == NULL ! 513: || which_bus < 0 ! 514: || sun2->tme_sun2_buses[which_bus] != NULL) { ! 515: if (free_buses != NULL) { ! 516: tme_output_append_error(_output, ! 517: "%s%s", ! 518: _("remaining buses:"), ! 519: free_buses); ! 520: tme_free(free_buses); ! 521: } ! 522: else { ! 523: tme_output_append_error(_output, _("all buses present")); ! 524: } ! 525: return (EINVAL); ! 526: } ! 527: if (free_buses != NULL) { ! 528: tme_free(free_buses); ! 529: } ! 530: ! 531: if (args[2] != NULL) { ! 532: tme_output_append_error(_output, ! 533: "%s %s", ! 534: args[2], ! 535: _("unexpected")); ! 536: return (EINVAL); ! 537: } ! 538: ! 539: /* create our side of a generic bus connection: */ ! 540: conn_sun2 = tme_new0(struct tme_sun2_bus_connection, 1); ! 541: conn_bus = &conn_sun2->tme_sun2_bus_connection; ! 542: conn = &conn_bus->tme_bus_connection; ! 543: conn->tme_connection_next = *_conns; ! 544: ! 545: /* fill in the generic connection: */ ! 546: conn->tme_connection_type = TME_CONNECTION_BUS_GENERIC; ! 547: conn->tme_connection_score = _tme_sun2_connection_score; ! 548: conn->tme_connection_make = _tme_sun2_connection_make; ! 549: conn->tme_connection_break = _tme_sun2_connection_break; ! 550: ! 551: /* fill in the generic bus connection: */ ! 552: conn_bus->tme_bus_signal = _tme_sun2_bus_signal; ! 553: conn_bus->tme_bus_intack = NULL; ! 554: conn_bus->tme_bus_tlb_set_allocate = _tme_sun2_mmu_tlb_set_allocate; ! 555: conn_bus->tme_bus_tlb_fill = _tme_sun2_bus_tlb_fill; ! 556: ! 557: /* fill in the sun2 connection: */ ! 558: conn_sun2->tme_sun2_bus_connection_which = which_bus; ! 559: ! 560: /* add in this connection side possibility: */ ! 561: *_conns = conn; ! 562: } ! 563: ! 564: /* done: */ ! 565: return (TME_OK); ! 566: } ! 567: ! 568: /* this creates a new sun2 element: */ ! 569: TME_ELEMENT_NEW_DECL(tme_machine_sun2) { ! 570: int usage; ! 571: struct tme_sun2 *sun2; ! 572: int sun2_has_vme; ! 573: const char *idprom_filename; ! 574: FILE *idprom_fp; ! 575: tme_uint8_t idprom[TME_SUN_IDPROM_SIZE]; ! 576: int arg_i; ! 577: ! 578: arg_i = 1; ! 579: usage = FALSE; ! 580: ! 581: /* our first argument must be either "multibus" or "vme": */ ! 582: sun2_has_vme = FALSE; ! 583: if (TME_ARG_IS(args[arg_i], "multibus")) { ! 584: arg_i++; ! 585: } ! 586: else if (TME_ARG_IS(args[arg_i], "vme")) { ! 587: arg_i++; ! 588: sun2_has_vme = TRUE; ! 589: } ! 590: else { ! 591: usage = TRUE; ! 592: } ! 593: ! 594: /* our second argument is the filename to load our IDPROM contents from: */ ! 595: idprom_filename = args[arg_i++]; ! 596: if (idprom_filename == NULL) { ! 597: usage = TRUE; ! 598: } ! 599: ! 600: /* we must have no more arguments: */ ! 601: if (args[arg_i] != NULL) { ! 602: tme_output_append_error(_output, ! 603: "%s %s, ", ! 604: args[arg_i], ! 605: _("unexpected")); ! 606: usage = TRUE; ! 607: } ! 608: ! 609: /* if our usage was bad: */ ! 610: if (usage) { ! 611: tme_output_append_error(_output, ! 612: "%s %s [ multibus | vme ] IDPROM%s", ! 613: _("usage:"), ! 614: args[0], ! 615: _("-FILENAME")); ! 616: return (EINVAL); ! 617: } ! 618: ! 619: /* try to read in the IDPROM: */ ! 620: idprom_fp = fopen(idprom_filename, "r"); ! 621: if (idprom_fp == NULL) { ! 622: tme_output_append_error(_output, idprom_filename); ! 623: return (errno); ! 624: } ! 625: if (fread(idprom, sizeof(tme_uint8_t), sizeof(idprom), idprom_fp) != sizeof(idprom)) { ! 626: tme_output_append_error(_output, idprom_filename); ! 627: fclose(idprom_fp); ! 628: return (ENOEXEC); ! 629: } ! 630: fclose(idprom_fp); ! 631: ! 632: /* allocate and initialize the new sun2: */ ! 633: sun2 = tme_new0(struct tme_sun2, 1); ! 634: sun2->tme_sun2_element = element; ! 635: ! 636: /* set the VME flag: */ ! 637: sun2->tme_sun2_has_vme = sun2_has_vme; ! 638: ! 639: /* set the IDPROM: */ ! 640: memcpy(sun2->tme_sun2_idprom_contents, idprom, sizeof(idprom)); ! 641: ! 642: /* the system and user context registers: */ ! 643: sun2->tme_sun2_context_system = 0; ! 644: sun2->tme_sun2_context_user = 0; ! 645: ! 646: /* the diagnostics register: */ ! 647: sun2->tme_sun2_diag = 0; ! 648: ! 649: /* the bus error register: */ ! 650: sun2->tme_sun2_buserr = 0; ! 651: ! 652: /* the enable register: */ ! 653: sun2->tme_sun2_enable = 0; ! 654: ! 655: /* the MMU: */ ! 656: _tme_sun2_mmu_new(sun2); ! 657: ! 658: /* the busses: */ ! 659: sun2->tme_sun2_obio = NULL; ! 660: sun2->tme_sun2_obmem = NULL; ! 661: sun2->tme_sun2_mbio = NULL; ! 662: sun2->tme_sun2_mbmem = NULL; ! 663: sun2->tme_sun2_vmebus = NULL; ! 664: ! 665: /* we don't have the CPU's reset TLBs yet: */ ! 666: sun2->tme_sun2_reset_tlbs = NULL; ! 667: ! 668: /* fill the element: */ ! 669: element->tme_element_private = sun2; ! 670: element->tme_element_connections_new = _tme_sun2_connections_new; ! 671: element->tme_element_command = _tme_sun2_command; ! 672: ! 673: return (TME_OK); ! 674: } ! 675: ! 676: /* this creates a new Sun-2 am9513: */ ! 677: TME_ELEMENT_SUB_NEW_DECL(tme_machine_sun2,clock) { ! 678: struct tme_am9513_socket socket; ! 679: char *sub_args[2]; ! 680: ! 681: /* create the am9513 socket: */ ! 682: socket.tme_am9513_socket_version = TME_AM9513_SOCKET_0; ! 683: socket.tme_am9513_socket_address_cmd = 2; ! 684: socket.tme_am9513_socket_address_data = 0; ! 685: socket.tme_am9513_socket_port_least_lane = 0; /* D7-D0 */ ! 686: socket.tme_am9513_socket_basic_clock = (19660800 / 4); ! 687: ! 688: /* Timer 1 is connected to the bus as ipl 7 (inverted): */ ! 689: socket.tme_am9513_socket_counter_signals[0] = ! 690: TME_BUS_SIGNAL_INT(7) | TME_BUS_SIGNAL_LEVEL_INVERTED; ! 691: ! 692: /* Timer 2 is connected to the bus as ipl 5 (inverted): */ ! 693: socket.tme_am9513_socket_counter_signals[1] = ! 694: TME_BUS_SIGNAL_INT(5) | TME_BUS_SIGNAL_LEVEL_INVERTED; ! 695: ! 696: /* Timer 3 is connected to the bus as ???: */ ! 697: socket.tme_am9513_socket_counter_signals[2] = TME_BUS_SIGNAL_ABORT; ! 698: ! 699: /* Timer 4 is connected to the bus as ???: */ ! 700: socket.tme_am9513_socket_counter_signals[3] = TME_BUS_SIGNAL_ABORT; ! 701: ! 702: /* Timer 5 is connected to the bus as ???: */ ! 703: socket.tme_am9513_socket_counter_signals[4] = TME_BUS_SIGNAL_ABORT; ! 704: ! 705: /* create the am9513: */ ! 706: sub_args[0] = "tme/ic/am9513"; ! 707: sub_args[1] = NULL; ! 708: return (tme_element_new(element, (const char * const *) sub_args, &socket, _output)); ! 709: } ! 710: ! 711: /* this creates a new Sun-2 mm58167: */ ! 712: TME_ELEMENT_SUB_NEW_DECL(tme_machine_sun2,tod) { ! 713: struct tme_mm58167_socket socket; ! 714: char *sub_args[2]; ! 715: ! 716: /* create the mm58167 socket: */ ! 717: socket.tme_mm58167_socket_version = TME_MM58167_SOCKET_0; ! 718: socket.tme_mm58167_socket_addr_shift = 1; ! 719: socket.tme_mm58167_socket_port_least_lane = 1; /* D15-D8 */ ! 720: ! 721: /* create the mm58167: */ ! 722: sub_args[0] = "tme/ic/mm58167"; ! 723: sub_args[1] = NULL; ! 724: return (tme_element_new(element, (const char * const *) sub_args, &socket, _output)); ! 725: } ! 726: ! 727: /* this creates a new Sun-2 z8530: */ ! 728: TME_ELEMENT_SUB_NEW_DECL(tme_machine_sun2,zs) { ! 729: struct tme_z8530_socket socket; ! 730: char *sub_args[2]; ! 731: ! 732: /* create the z8530 socket: */ ! 733: socket.tme_z8530_socket_version = TME_Z8530_SOCKET_0; ! 734: socket.tme_z8530_socket_address_chan_a = 4; ! 735: socket.tme_z8530_socket_address_chan_b = 0; ! 736: socket.tme_z8530_socket_offset_csr = 0; ! 737: socket.tme_z8530_socket_offset_data = 2; ! 738: socket.tme_z8530_socket_port_least_lane = 1; /* D15-D8 */ ! 739: socket.tme_z8530_socket_pclk = (9600 * 512); ! 740: ! 741: /* create the z8530: */ ! 742: sub_args[0] = "tme/ic/z8530"; ! 743: sub_args[1] = NULL; ! 744: return (tme_element_new(element, (const char * const *) sub_args, &socket, _output)); ! 745: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.