|
|
1.1.1.2 ! root 1: /* $Id: sun3-mainbus.c,v 1.6 2007/08/24 01:15:19 fredette Exp $ */ 1.1 root 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> 1.1.1.2 ! root 37: _TME_RCSID("$Id: sun3-mainbus.c,v 1.6 2007/08/24 01:15:19 fredette Exp $"); 1.1 root 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) { 1.1.1.2 ! root 166: ! 167: /* if this reset signal is coming from the m68k: */ ! 168: if (conn_bus_raiser->tme_bus_connection.tme_connection_other ! 169: == &sun3->tme_sun3_m68k->tme_m68k_bus_connection.tme_bus_connection) { ! 170: ! 171: /* XXX FIXME - note that the do_reset code is lazy and only ! 172: sends reset negation edges out to the busses. we are also ! 173: lazy (and also worried that sending out assertion edges might ! 174: break things), so we only send out reset negation edges too: */ ! 175: if (signal_asserted) { ! 176: return (TME_OK); ! 177: } ! 178: ! 179: /* propagate this reset edge to all busses: */ ! 180: (*sun3->tme_sun3_obio->tme_bus_signal) ! 181: (sun3->tme_sun3_obio, ! 182: TME_BUS_SIGNAL_RESET ! 183: | TME_BUS_SIGNAL_LEVEL_NEGATED ! 184: | TME_BUS_SIGNAL_EDGE); ! 185: (*sun3->tme_sun3_obmem->tme_bus_signal) ! 186: (sun3->tme_sun3_obmem, ! 187: TME_BUS_SIGNAL_RESET ! 188: | TME_BUS_SIGNAL_LEVEL_NEGATED ! 189: | TME_BUS_SIGNAL_EDGE); ! 190: (*sun3->tme_sun3_vmebus->tme_bus_signal) ! 191: (sun3->tme_sun3_vmebus, ! 192: TME_BUS_SIGNAL_RESET ! 193: | TME_BUS_SIGNAL_LEVEL_NEGATED ! 194: | TME_BUS_SIGNAL_EDGE); ! 195: } 1.1 root 196: } 197: 198: /* an interrupt signal: */ 199: else if (TME_BUS_SIGNAL_IS_INT(signal)) { 200: ipl = TME_BUS_SIGNAL_INDEX_INT(signal); 201: if (ipl >= TME_M68K_IPL_MIN 202: && ipl <= TME_M68K_IPL_MAX) { 203: 204: /* update this ipl in the byte array: */ 205: ipl_index = ipl >> 3; 206: ipl_mask = TME_BIT(ipl & 7); 207: sun3->tme_sun3_int_signals[ipl_index] 208: = ((sun3->tme_sun3_int_signals[ipl_index] 209: & ~ipl_mask) 210: | (signal_asserted 211: ? ipl_mask 212: : 0)); 213: 214: /* possibly update the ipl being driven to the CPU: */ 215: return (_tme_sun3_ipl_check(sun3)); 216: } 217: } 218: 219: /* an unknown signal: */ 220: else { 221: abort(); 222: } 223: 224: return (TME_OK); 225: } 226: 227: /* this handles a CPU interrupt acknowledge: */ 228: static int 229: _tme_sun3_bus_intack(struct tme_bus_connection *conn_m68k, unsigned int ipl, int *vector) 230: { 231: struct tme_sun3 *sun3; 232: tme_uint8_t interreg; 233: unsigned int signal; 234: int rc; 235: 236: /* recover our sun3: */ 237: sun3 = (struct tme_sun3 *) conn_m68k->tme_bus_connection.tme_connection_element->tme_element_private; 238: 239: /* acknowledge any soft interrupt: */ 240: interreg = sun3->tme_sun3_ints; 241: if ((ipl == 3 242: && (interreg & TME_SUN3_IREG_SOFT_INT_3)) 243: || (ipl == 2 244: && (interreg & TME_SUN3_IREG_SOFT_INT_2)) 245: || (ipl == 1 246: && (interreg & TME_SUN3_IREG_SOFT_INT_1))) { 247: *vector = TME_BUS_INTERRUPT_VECTOR_UNDEF; 248: return (TME_OK); 249: } 250: 251: /* turn the ipl into a bus signal number: */ 252: signal = TME_BUS_SIGNAL_INT(ipl); 253: 254: /* try the acknowledge on these buses, in order: */ 255: 256: /* obio: */ 257: rc = (*sun3->tme_sun3_obio->tme_bus_intack) 258: (sun3->tme_sun3_obio, signal, vector); 259: if (rc == ENOENT 260: && signal == sun3->tme_sun3_int_signal_clock_last) { 261: rc = (*sun3->tme_sun3_obio->tme_bus_intack) 262: (sun3->tme_sun3_obio, TME_BUS_SIGNAL_INT_CLOCK, vector); 263: } 264: if (rc != ENOENT) { 265: return (rc); 266: } 267: /* obmem: */ 268: rc = (*sun3->tme_sun3_obmem->tme_bus_intack) 269: (sun3->tme_sun3_obmem, signal, vector); 270: if (rc != ENOENT) { 271: return (rc); 272: } 273: /* VMEbus: */ 274: rc = (*sun3->tme_sun3_vmebus->tme_bus_intack) 275: (sun3->tme_sun3_vmebus, signal, vector); 276: if (rc != ENOENT) { 277: return (rc); 278: } 279: 280: /* done: */ 281: return (rc); 282: } 283: 284: /* our command function: */ 285: static int 286: _tme_sun3_command(struct tme_element *element, const char * const * args, char **_output) 287: { 288: struct tme_sun3 *sun3; 289: int do_reset; 290: 291: /* recover our sun3: */ 292: sun3 = (struct tme_sun3 *) element->tme_element_private; 293: 294: /* assume no reset: */ 295: do_reset = FALSE; 296: 297: /* the "power" command: */ 298: if (TME_ARG_IS(args[1], "power")) { 299: 300: if (TME_ARG_IS(args[2], "up") 301: && args[3] == NULL) { 302: do_reset = TRUE; 303: } 304: 305: else if (TME_ARG_IS(args[2], "down") 306: && args[3] == NULL) { 307: /* nothing */ 308: } 309: 310: /* return an error: */ 311: else { 312: tme_output_append_error(_output, 313: "%s %s power [ up | down ]", 314: _("usage:"), 315: args[0]); 316: return (EINVAL); 317: } 318: } 319: 320: /* the "diag-switch" command: */ 321: else if (TME_ARG_IS(args[1], "diag-switch")) { 322: 323: if (args[2] == NULL) { 324: tme_output_append_error(_output, 325: "diag-switch %s", 326: (sun3->tme_sun3_enable & TME_SUN3_ENA_DIAG 327: ? "true" 328: : "false")); 329: } 330: 331: else if (TME_ARG_IS(args[2], "true") 332: && args[3] == NULL) { 333: sun3->tme_sun3_enable |= TME_SUN3_ENA_DIAG; 334: } 335: 336: else if (TME_ARG_IS(args[2], "false") 337: && args[3] == NULL) { 338: sun3->tme_sun3_enable &= ~TME_SUN3_ENA_DIAG; 339: } 340: 341: /* return an error: */ 342: else { 343: tme_output_append_error(_output, 344: "%s %s diag-switch [ true | false ]", 345: _("usage:"), 346: args[0]); 347: return (EINVAL); 348: } 349: } 350: 351: /* any other command: */ 352: else { 353: if (args[1] != NULL) { 354: tme_output_append_error(_output, 355: "%s '%s', ", 356: _("unknown command"), 357: args[1]); 358: } 359: tme_output_append_error(_output, 360: _("available %s commands: %s"), 361: args[0], 362: "power"); 363: return (EINVAL); 364: } 365: 366: if (do_reset) { 367: 368: /* reset the CPU: */ 369: (*sun3->tme_sun3_m68k->tme_m68k_bus_connection.tme_bus_signal) 370: (&sun3->tme_sun3_m68k->tme_m68k_bus_connection, 371: TME_BUS_SIGNAL_RESET 372: | TME_BUS_SIGNAL_LEVEL_NEGATED 373: | TME_BUS_SIGNAL_EDGE); 374: 375: /* reset all busses: */ 376: (*sun3->tme_sun3_obio->tme_bus_signal) 377: (sun3->tme_sun3_obio, 378: TME_BUS_SIGNAL_RESET 379: | TME_BUS_SIGNAL_LEVEL_NEGATED 380: | TME_BUS_SIGNAL_EDGE); 381: (*sun3->tme_sun3_obmem->tme_bus_signal) 382: (sun3->tme_sun3_obmem, 383: TME_BUS_SIGNAL_RESET 384: | TME_BUS_SIGNAL_LEVEL_NEGATED 385: | TME_BUS_SIGNAL_EDGE); 386: (*sun3->tme_sun3_vmebus->tme_bus_signal) 1.1.1.2 ! root 387: (sun3->tme_sun3_vmebus, 1.1 root 388: TME_BUS_SIGNAL_RESET 389: | TME_BUS_SIGNAL_LEVEL_NEGATED 390: | TME_BUS_SIGNAL_EDGE); 391: } 392: 393: return (TME_OK); 394: } 395: 396: /* the connection scorer: */ 397: static int 398: _tme_sun3_connection_score(struct tme_connection *conn, unsigned int *_score) 399: { 400: struct tme_m68k_bus_connection *conn_m68k; 401: struct tme_sun3_bus_connection *conn_sun3; 402: struct tme_bus_connection *conn_bus; 403: struct tme_sun3 *sun3; 404: unsigned int score; 405: 406: /* recover our sun3: */ 407: sun3 = (struct tme_sun3 *) conn->tme_connection_element->tme_element_private; 408: 409: /* assume that this connection is useless: */ 410: score = 0; 411: 412: /* dispatch on the connection type: */ 413: conn_m68k = (struct tme_m68k_bus_connection *) conn->tme_connection_other; 414: conn_sun3 = (struct tme_sun3_bus_connection *) conn; 415: conn_bus = (struct tme_bus_connection *) conn->tme_connection_other; 416: switch (conn->tme_connection_type) { 417: 418: /* this must be an m68k chip, and not another bus: */ 419: case TME_CONNECTION_BUS_M68K: 420: if (conn_bus->tme_bus_tlb_set_allocate == NULL 421: && conn_m68k->tme_m68k_bus_tlb_fill == NULL 422: && conn_m68k->tme_m68k_bus_m6888x_enable != NULL) { 423: score = 10; 424: } 425: break; 426: 427: /* if this connection is not for an obio master, this must be a bus, 428: and not a chip, and vice versa. if this connection is for a bus, 429: the bus must still be free: */ 430: case TME_CONNECTION_BUS_GENERIC: 431: if (((conn_sun3->tme_sun3_bus_connection_which != TME_SUN3_CONN_OBIO_MASTER) 432: == (conn_bus->tme_bus_tlb_set_allocate != NULL 433: && conn_bus->tme_bus_tlb_fill != NULL)) 434: && (conn_sun3->tme_sun3_bus_connection_which >= TME_SUN3_CONN_BUS_COUNT 435: || sun3->tme_sun3_buses[conn_sun3->tme_sun3_bus_connection_which] == NULL)) { 436: score = 1; 437: } 438: break; 439: 440: default: abort(); 441: } 442: 443: *_score = score; 444: return (TME_OK); 445: } 446: 447: /* this makes a new connection: */ 448: static int 449: _tme_sun3_connection_make(struct tme_connection *conn, unsigned int state) 450: { 451: struct tme_sun3 *sun3; 452: struct tme_m68k_bus_connection *conn_m68k; 453: struct tme_sun3_bus_connection *conn_sun3; 454: struct tme_bus_connection *conn_bus; 455: struct tme_connection *conn_other; 456: 457: /* recover our sun3: */ 458: sun3 = (struct tme_sun3 *) conn->tme_connection_element->tme_element_private; 459: 460: /* dispatch on the connection type: */ 461: conn_other = conn->tme_connection_other; 462: conn_m68k = (struct tme_m68k_bus_connection *) conn_other; 463: conn_sun3 = (struct tme_sun3_bus_connection *) conn; 464: conn_bus = (struct tme_bus_connection *) conn_other; 465: switch (conn->tme_connection_type) { 466: 467: case TME_CONNECTION_BUS_M68K: 468: sun3->tme_sun3_m68k = conn_m68k; 469: break; 470: 471: case TME_CONNECTION_BUS_GENERIC: 472: 473: /* if this connection is for a bus: */ 474: if (conn_sun3->tme_sun3_bus_connection_which < TME_SUN3_CONN_BUS_COUNT) { 475: 476: /* remember the connection to this bus: */ 477: sun3->tme_sun3_buses[conn_sun3->tme_sun3_bus_connection_which] = conn_bus; 478: } 479: 480: /* otherwise, if this connection is for the memory error register: */ 481: else if (conn_sun3->tme_sun3_bus_connection_which == TME_SUN3_CONN_REG_MEMERR) { 482: 483: /* remember the memory error register's bus connection: */ 484: sun3->tme_sun3_memerr_bus = conn_bus; 485: } 486: 487: break; 488: 489: default: 490: assert(FALSE); 491: break; 492: } 493: return (TME_OK); 494: } 495: 496: /* this breaks a connection: */ 497: static int 498: _tme_sun3_connection_break(struct tme_connection *conn, unsigned int state) 499: { 500: abort(); 501: } 502: 503: /* this makes new connection sides: */ 504: static int 505: _tme_sun3_connections_new(struct tme_element *element, const char * const *args, struct tme_connection **_conns, char **_output) 506: { 507: struct tme_m68k_bus_connection *conn_m68k; 508: struct tme_sun3_bus_connection *conn_sun3; 509: struct tme_bus_connection *conn_bus; 510: struct tme_connection *conn; 511: struct tme_sun3 *sun3; 512: char *free_buses; 513: int which_conn; 514: 515: /* recover our sun3: */ 516: sun3 = (struct tme_sun3 *) element->tme_element_private; 517: 518: /* if we have no arguments, and we don't have a CPU yet, we can take 519: an m68k bus connection: */ 520: if (args[1] == NULL 521: && sun3->tme_sun3_m68k == NULL) { 522: 523: /* create our side of an m68k bus connection: */ 524: conn_m68k = tme_new0(struct tme_m68k_bus_connection, 1); 525: conn_bus = &conn_m68k->tme_m68k_bus_connection; 526: conn = &conn_bus->tme_bus_connection; 527: conn->tme_connection_next = *_conns; 528: 529: /* fill in the generic connection: */ 530: conn->tme_connection_type = TME_CONNECTION_BUS_M68K; 531: conn->tme_connection_score = _tme_sun3_connection_score; 532: conn->tme_connection_make = _tme_sun3_connection_make; 533: conn->tme_connection_break = _tme_sun3_connection_break; 534: 535: /* fill in the generic bus connection: */ 536: conn_bus->tme_bus_signal = _tme_sun3_bus_signal; 537: conn_bus->tme_bus_intack = _tme_sun3_bus_intack; 538: conn_bus->tme_bus_tlb_set_allocate = _tme_sun3_mmu_tlb_set_allocate; 539: 540: /* full in the m68k bus connection: */ 541: conn_m68k->tme_m68k_bus_tlb_fill = _tme_sun3_m68k_tlb_fill; 542: 543: /* add in this connection side possibility: */ 544: *_conns = conn; 545: } 546: 547: /* create our side of a generic bus connection: */ 548: conn_sun3 = tme_new0(struct tme_sun3_bus_connection, 1); 549: conn_bus = &conn_sun3->tme_sun3_bus_connection; 550: conn = &conn_bus->tme_bus_connection; 551: conn->tme_connection_next = *_conns; 552: 553: /* fill in the generic connection: */ 554: conn->tme_connection_type = TME_CONNECTION_BUS_GENERIC; 555: conn->tme_connection_score = _tme_sun3_connection_score; 556: conn->tme_connection_make = _tme_sun3_connection_make; 557: conn->tme_connection_break = _tme_sun3_connection_break; 558: 559: /* fill in the generic bus connection: */ 560: conn_bus->tme_bus_signal = _tme_sun3_bus_signal; 561: conn_bus->tme_bus_intack = NULL; 562: conn_bus->tme_bus_tlb_set_allocate = _tme_sun3_mmu_tlb_set_allocate; 563: conn_bus->tme_bus_tlb_fill = _tme_sun3_bus_tlb_fill; 564: 565: /* if we have no argument: */ 566: if (args[1] == NULL) { 567: 568: /* make this connection for an obio master: */ 569: conn_sun3->tme_sun3_bus_connection_which = TME_SUN3_CONN_OBIO_MASTER; 570: } 571: 572: /* otherwise, we have at least one argument: */ 573: else { 574: 575: /* we must have no other arguments: */ 576: if (args[2] != NULL) { 577: tme_output_append_error(_output, 578: "%s %s", 579: args[2], 580: _("unexpected")); 581: tme_free(conn_sun3); 582: return (EINVAL); 583: } 584: 585: /* start the list of buses that we don't have yet: */ 586: free_buses = NULL; 587: 588: /* poison the which connection: */ 589: which_conn = -1; 590: 591: /* check each bus: */ 592: 593: /* obio: */ 594: if (sun3->tme_sun3_obio == NULL) { 595: tme_output_append(&free_buses, " obio"); 596: } 597: if (TME_ARG_IS(args[1], "obio")) { 598: which_conn = TME_SUN3_CONN_BUS_OBIO; 599: } 600: 601: /* obmem: */ 602: if (sun3->tme_sun3_obmem == NULL) { 603: tme_output_append(&free_buses, " obmem"); 604: } 605: if (TME_ARG_IS(args[1], "obmem")) { 606: which_conn = TME_SUN3_CONN_BUS_OBMEM; 607: } 608: 609: /* VMEbus: */ 610: if (sun3->tme_sun3_vmebus == NULL) { 611: tme_output_append(&free_buses, " vme"); 612: } 613: if (TME_ARG_IS(args[1], "vme")) { 614: which_conn = TME_SUN3_CONN_BUS_VME; 615: conn_bus->tme_bus_subregions.tme_bus_subregion_address_last 616: = TME_SUN3_DVMA_SIZE_VME; 617: } 618: 619: /* random connections: */ 620: 621: if (TME_ARG_IS(args[1], "memerr")) { 622: which_conn = TME_SUN3_CONN_REG_MEMERR; 623: conn_bus->tme_bus_subregions.tme_bus_subregion_address_last 624: = TME_SUN3_MEMERR_SIZ_REG; 625: } 626: else if (TME_ARG_IS(args[1], "intreg")) { 627: which_conn = TME_SUN3_CONN_REG_INTREG; 628: conn_bus->tme_bus_subregions.tme_bus_subregion_address_last 629: = sizeof(sun3->tme_sun3_ints); 630: } 631: 632: /* if the which connection is still poison, or if this is trying 633: to connect a bus that we already have, complain: */ 634: if (which_conn < 0 635: || (which_conn < TME_SUN3_CONN_BUS_COUNT 636: && sun3->tme_sun3_buses[which_conn] != NULL)) { 637: if (which_conn < 0) { 638: tme_output_append_error(_output, 639: "%s %s", 640: _("unknown bus or register:"), 641: args[1]); 642: } 643: if (free_buses != NULL) { 644: tme_output_append_error(_output, 645: "%s %s", 646: _("remaining buses:"), 647: free_buses); 648: tme_free(free_buses); 649: } 650: else { 651: tme_output_append_error(_output, _("all buses present")); 652: } 653: tme_free(conn_sun3); 654: return (EINVAL); 655: } 656: 657: /* free the remaining bus list: */ 658: if (free_buses != NULL) { 659: tme_free(free_buses); 660: } 661: 662: /* fill in the sun3 connection: */ 663: conn_sun3->tme_sun3_bus_connection_which = which_conn; 664: } 665: 666: /* add in this connection side possibility: */ 667: *_conns = conn; 668: 669: /* done: */ 670: return (TME_OK); 671: } 672: 673: /* this creates a new sun3 element: */ 674: TME_ELEMENT_NEW_DECL(tme_machine_sun3) { 675: int usage; 676: struct tme_sun3 *sun3; 677: const char *idprom_filename; 678: FILE *idprom_fp; 679: tme_uint8_t idprom[TME_SUN_IDPROM_SIZE]; 680: int arg_i; 681: 682: arg_i = 1; 683: usage = FALSE; 684: 685: /* our first argument is the filename to load our IDPROM contents from: */ 686: idprom_filename = args[arg_i++]; 687: if (idprom_filename == NULL) { 688: usage = TRUE; 689: } 690: 691: /* we must have no more arguments: */ 692: if (args[arg_i] != NULL) { 693: tme_output_append_error(_output, 694: "%s %s, ", 695: args[arg_i], 696: _("unexpected")); 697: usage = TRUE; 698: } 699: 700: /* if our usage was bad: */ 701: if (usage) { 702: tme_output_append_error(_output, 703: "%s %s IDPROM%s", 704: _("usage:"), 705: args[0], 706: _("-FILENAME")); 707: return (EINVAL); 708: } 709: 710: /* try to read in the IDPROM: */ 711: idprom_fp = fopen(idprom_filename, "r"); 712: if (idprom_fp == NULL) { 713: tme_output_append_error(_output, idprom_filename); 714: return (errno); 715: } 716: if (fread(idprom, sizeof(tme_uint8_t), sizeof(idprom), idprom_fp) != sizeof(idprom)) { 717: tme_output_append_error(_output, idprom_filename); 718: fclose(idprom_fp); 719: return (ENOEXEC); 720: } 721: fclose(idprom_fp); 722: 723: /* allocate and initialize the new sun3: */ 724: sun3 = tme_new0(struct tme_sun3, 1); 725: sun3->tme_sun3_element = element; 726: 727: /* set the IDPROM: */ 728: memcpy(sun3->tme_sun3_idprom_contents, idprom, sizeof(idprom)); 729: 730: /* the context register: */ 731: sun3->tme_sun3_context = 0; 732: 733: /* the diagnostics register: */ 734: sun3->tme_sun3_diag = 0; 735: 736: /* the bus error register: */ 737: sun3->tme_sun3_buserr = 0; 738: 739: /* the enable register: */ 740: sun3->tme_sun3_enable = 0; 741: 742: /* the memory error register: */ 743: sun3->tme_sun3_memerr_csr = 0; 744: sun3->tme_sun3_memerr_vaddr = 0; 745: 746: /* the interrupt register: */ 747: sun3->tme_sun3_ints = 0; 748: 749: /* the MMU: */ 750: _tme_sun3_mmu_new(sun3); 751: 752: /* the busses: */ 753: sun3->tme_sun3_obio = NULL; 754: sun3->tme_sun3_obmem = NULL; 755: sun3->tme_sun3_vmebus = NULL; 756: 757: /* the last clock interrupt signal: */ 758: sun3->tme_sun3_int_signal_clock_last = TME_BUS_SIGNAL_INT_UNSPEC; 759: 760: /* fill the element: */ 761: element->tme_element_private = sun3; 762: element->tme_element_connections_new = _tme_sun3_connections_new; 763: element->tme_element_command = _tme_sun3_command; 764: 765: return (TME_OK); 766: } 767: 768: /* this creates a new Sun-3 isil7170: */ 769: TME_ELEMENT_SUB_NEW_DECL(tme_machine_sun3,clock) { 770: struct tme_isil7170_socket socket; 771: const char *sub_args[4]; 772: int arg_i; 773: 774: /* create the isil7170 socket: */ 775: memset (&socket, 0, sizeof(socket)); 776: socket.tme_isil7170_socket_version = TME_ISIL7170_SOCKET_0; 777: socket.tme_isil7170_socket_addr_shift = 0; 778: socket.tme_isil7170_socket_port_least_lane = 3; /* D31-D24 */ 779: socket.tme_isil7170_socket_clock_basic = TME_ISIL7170_FREQ_32K; 780: socket.tme_isil7170_socket_int_signal = TME_BUS_SIGNAL_INT_CLOCK; 781: 782: /* create the isil7170. we allow at most two arguments to pass 783: through, which is an awful hack: */ 784: sub_args[0] = "tme/ic/isil7170"; 785: for (arg_i = 1;; arg_i++) { 786: if (arg_i == TME_ARRAY_ELS(sub_args)) { 787: abort(); 788: } 789: sub_args[arg_i] = args[arg_i]; 790: if (args[arg_i] == NULL) { 791: break; 792: } 793: } 794: return (tme_element_new(element, (const char * const *) sub_args, &socket, _output)); 795: } 796: 797: /* this creates a new Sun-3 z8530: */ 798: TME_ELEMENT_SUB_NEW_DECL(tme_machine_sun3,zs) { 799: struct tme_z8530_socket socket = TME_SUN_Z8530_SOCKET_INIT; 800: char *sub_args[2]; 801: 802: /* create the z8530: */ 803: sub_args[0] = "tme/ic/z8530"; 804: sub_args[1] = NULL; 805: return (tme_element_new(element, (const char * const *) sub_args, &socket, _output)); 806: } 807: 808: /* this creates a new Sun-3 obie: */ 809: TME_ELEMENT_SUB_NEW_DECL(tme_machine_sun3,obie) { 810: return (tme_sun_obie(element, args, _output)); 811: } 812: 813: /* this creates a new Sun-3 bwtwo: */ 814: TME_ELEMENT_SUB_NEW_DECL(tme_machine_sun3,bwtwo) { 815: return (tme_sun_bwtwo(element, args, _output)); 816: } 817: 818: /* this creates a new Sun-3 si: */ 819: TME_ELEMENT_SUB_NEW_DECL(tme_machine_sun3,si) { 820: return (tme_sun_si(element, args, _output)); 821: } 822: 823: /* this creates a new Sun-3 cgtwo: */ 824: TME_ELEMENT_SUB_NEW_DECL(tme_machine_sun3,cgtwo) { 825: return (tme_sun_cgtwo(element, args, _output)); 826: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.