Annotation of tme/machine/sun4/sun4-mainbus.c, revision 1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.