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

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

unix.superglobalmegacorp.com

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