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

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

unix.superglobalmegacorp.com

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