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

1.1.1.2 ! root        1: /* $Id: sun3-mainbus.c,v 1.6 2007/08/24 01:15:19 fredette Exp $ */
1.1       root        2: 
                      3: /* machine/sun3/sun3-mainbus.c - implementation of Sun 3 emulation: */
                      4: 
                      5: /*
                      6:  * Copyright (c) 2003, 2004 Matt Fredette
                      7:  * All rights reserved.
                      8:  *
                      9:  * Redistribution and use in source and binary forms, with or without
                     10:  * modification, are permitted provided that the following conditions
                     11:  * are met:
                     12:  * 1. Redistributions of source code must retain the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer.
                     14:  * 2. Redistributions in binary form must reproduce the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer in the
                     16:  *    documentation and/or other materials provided with the distribution.
                     17:  * 3. All advertising materials mentioning features or use of this software
                     18:  *    must display the following acknowledgement:
                     19:  *      This product includes software developed by Matt Fredette.
                     20:  * 4. The name of the author may not be used to endorse or promote products
                     21:  *    derived from this software without specific prior written permission.
                     22:  *
                     23:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     24:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
                     25:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
                     26:  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
                     27:  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
                     28:  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
                     29:  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     30:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
                     31:  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
                     32:  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     33:  * POSSIBILITY OF SUCH DAMAGE.
                     34:  */
                     35: 
                     36: #include <tme/common.h>
1.1.1.2 ! root       37: _TME_RCSID("$Id: sun3-mainbus.c,v 1.6 2007/08/24 01:15:19 fredette Exp $");
1.1       root       38: 
                     39: /* includes: */
                     40: #include "sun3-impl.h"
                     41: #include <tme/ic/z8530.h>
                     42: #include <tme/ic/isil7170.h>
                     43: #include <stdio.h>
                     44: 
                     45: /* macros: */
                     46: #define TME_BUS_SIGNAL_INT_CLOCK       TME_BUS_SIGNAL_INT(8)
                     47: 
                     48: /* this possibly updates that the interrupt priority level driven to the CPU: */
                     49: int
                     50: _tme_sun3_ipl_check(struct tme_sun3 *sun3)
                     51: {
                     52:   tme_uint8_t interreg;
                     53:   unsigned int ipl, ipl_index;
                     54:   tme_uint8_t ipl_mask;
                     55: 
                     56:   /* get the interrupt register: */
                     57:   interreg = sun3->tme_sun3_ints;
                     58: 
                     59:   /* assume that interrupts are completely masked: */
                     60:   ipl = TME_M68K_IPL_NONE;
                     61: 
                     62:   /* if interrupts are enabled: */
                     63:   if (interreg & TME_SUN3_IREG_INTS_ENAB) {
                     64: 
                     65:     /* find the highest ipl now asserted on the buses: */
                     66:     for (ipl = TME_M68K_IPL_MAX;
                     67:         ipl > TME_M68K_IPL_NONE;
                     68:         ipl--) {
                     69:       ipl_index = ipl >> 3;
                     70:       ipl_mask = TME_BIT(ipl & 7);
                     71:       if (sun3->tme_sun3_int_signals[ipl_index] & ipl_mask) {
                     72:        break;
                     73:       }
                     74:     }
                     75:     
                     76:     /* check the soft interrupts: */
                     77:     if (interreg & TME_SUN3_IREG_SOFT_INT_3) {
                     78:       ipl = TME_MAX(ipl, 3);
                     79:     }
                     80:     else if (interreg & TME_SUN3_IREG_SOFT_INT_2) {
                     81:       ipl = TME_MAX(ipl, 2);
                     82:     }
                     83:     else if (interreg & TME_SUN3_IREG_SOFT_INT_1) {
                     84:       ipl = TME_MAX(ipl, 1);
                     85:     }
                     86:   }
                     87:   
                     88:   /* possibly update the CPU: */
                     89:   if (ipl != sun3->tme_sun3_int_ipl_last) {
                     90:     sun3->tme_sun3_int_ipl_last = ipl;
                     91:     return ((*sun3->tme_sun3_m68k->tme_m68k_bus_interrupt)
                     92:            (sun3->tme_sun3_m68k, ipl));
                     93:   }
                     94:   return (TME_OK);
                     95: }
                     96: 
                     97: /* our mainbus signal handler: */
                     98: static int
                     99: _tme_sun3_bus_signal(struct tme_bus_connection *conn_bus_raiser, unsigned int signal)
                    100: {
                    101:   struct tme_sun3 *sun3;
                    102:   int signal_asserted;
                    103:   unsigned int ipl, ipl_index;
                    104:   tme_uint8_t ipl_mask;
                    105: 
                    106:   /* recover our sun3: */
                    107:   sun3 = (struct tme_sun3 *) conn_bus_raiser->tme_bus_connection.tme_connection_element->tme_element_private;
                    108: 
                    109:   /* see whether the signal is asserted or negated: */
                    110:   signal_asserted = TRUE;
                    111:   switch (signal & TME_BUS_SIGNAL_LEVEL_MASK) {
                    112:   case TME_BUS_SIGNAL_LEVEL_NEGATED:
                    113:     signal_asserted = FALSE;
                    114:   case TME_BUS_SIGNAL_LEVEL_ASSERTED:
                    115:     break;
                    116:   default:
                    117:     abort();
                    118:   }
                    119:   signal = TME_BUS_SIGNAL_WHICH(signal);
                    120: 
                    121:   /* ipl 8 doesn't really exist - it's the interrupt signal from the
                    122:      isil7170.  we must map it into either ipl 7 (NMI) or ipl 5
                    123:      (clock) depending on the state of the interrupt register: */
                    124:   if (signal == TME_BUS_SIGNAL_INT_CLOCK) {
                    125: 
                    126:     /* if the signal is being asserted: */
                    127:     if (signal_asserted) {
                    128: 
                    129:       /* map the interrupt signal: */
                    130:       if (sun3->tme_sun3_ints & TME_SUN3_IREG_CLOCK_ENAB_5) {
                    131:        signal = TME_BUS_SIGNAL_INT(5);
                    132:       }
                    133:       else if (sun3->tme_sun3_ints & TME_SUN3_IREG_CLOCK_ENAB_7) {
                    134:        signal = TME_BUS_SIGNAL_INT(7);
                    135:       }
                    136:       else {
                    137:        /* the clock interrupt isn't connected to any ipl: */
                    138:        signal = TME_BUS_SIGNAL_INT_UNSPEC;
                    139:       }
                    140: 
                    141:       /* remember the last clock interrupt signal: */
                    142:       sun3->tme_sun3_int_signal_clock_last = signal;
                    143:     }
                    144: 
                    145:     else {
                    146: 
                    147:       /* recover the last clock interrupt signal: */
                    148:       signal = sun3->tme_sun3_int_signal_clock_last;
                    149:     }
                    150: 
                    151:     /* if we're supposed to ignore this signal: */
                    152:     if (signal == TME_BUS_SIGNAL_INT_UNSPEC) {
                    153:       return (TME_OK);
                    154:     }
                    155:   }
                    156: 
                    157:   /* dispatch on the signal: */
                    158: 
                    159:   /* halt: */
                    160:   if (signal == TME_BUS_SIGNAL_HALT) {
                    161:     abort();
                    162:   }
                    163: 
                    164:   /* reset: */
                    165:   else if (signal == TME_BUS_SIGNAL_RESET) {
1.1.1.2 ! root      166: 
        !           167:     /* if this reset signal is coming from the m68k: */
        !           168:     if (conn_bus_raiser->tme_bus_connection.tme_connection_other
        !           169:        == &sun3->tme_sun3_m68k->tme_m68k_bus_connection.tme_bus_connection) {
        !           170: 
        !           171:       /* XXX FIXME - note that the do_reset code is lazy and only
        !           172:         sends reset negation edges out to the busses.  we are also
        !           173:         lazy (and also worried that sending out assertion edges might
        !           174:         break things), so we only send out reset negation edges too: */
        !           175:       if (signal_asserted) {
        !           176:        return (TME_OK);
        !           177:       }
        !           178: 
        !           179:       /* propagate this reset edge to all busses: */
        !           180:       (*sun3->tme_sun3_obio->tme_bus_signal)
        !           181:        (sun3->tme_sun3_obio,
        !           182:         TME_BUS_SIGNAL_RESET
        !           183:         | TME_BUS_SIGNAL_LEVEL_NEGATED
        !           184:         | TME_BUS_SIGNAL_EDGE);
        !           185:       (*sun3->tme_sun3_obmem->tme_bus_signal)
        !           186:        (sun3->tme_sun3_obmem,
        !           187:         TME_BUS_SIGNAL_RESET
        !           188:         | TME_BUS_SIGNAL_LEVEL_NEGATED
        !           189:         | TME_BUS_SIGNAL_EDGE);
        !           190:       (*sun3->tme_sun3_vmebus->tme_bus_signal)
        !           191:        (sun3->tme_sun3_vmebus,
        !           192:         TME_BUS_SIGNAL_RESET
        !           193:         | TME_BUS_SIGNAL_LEVEL_NEGATED
        !           194:         | TME_BUS_SIGNAL_EDGE);
        !           195:     }
1.1       root      196:   }
                    197: 
                    198:   /* an interrupt signal: */
                    199:   else if (TME_BUS_SIGNAL_IS_INT(signal)) {
                    200:     ipl = TME_BUS_SIGNAL_INDEX_INT(signal);
                    201:     if (ipl >= TME_M68K_IPL_MIN
                    202:        && ipl <= TME_M68K_IPL_MAX) {
                    203:       
                    204:       /* update this ipl in the byte array: */
                    205:       ipl_index = ipl >> 3;
                    206:       ipl_mask = TME_BIT(ipl & 7);
                    207:       sun3->tme_sun3_int_signals[ipl_index]
                    208:        = ((sun3->tme_sun3_int_signals[ipl_index]
                    209:            & ~ipl_mask)
                    210:           | (signal_asserted
                    211:              ? ipl_mask
                    212:              : 0));
                    213: 
                    214:       /* possibly update the ipl being driven to the CPU: */
                    215:       return (_tme_sun3_ipl_check(sun3));
                    216:     }
                    217:   }
                    218: 
                    219:   /* an unknown signal: */
                    220:   else {
                    221:     abort();
                    222:   }
                    223: 
                    224:   return (TME_OK);
                    225: }
                    226: 
                    227: /* this handles a CPU interrupt acknowledge: */
                    228: static int
                    229: _tme_sun3_bus_intack(struct tme_bus_connection *conn_m68k, unsigned int ipl, int *vector)
                    230: {
                    231:   struct tme_sun3 *sun3;
                    232:   tme_uint8_t interreg;
                    233:   unsigned int signal;
                    234:   int rc;
                    235: 
                    236:   /* recover our sun3: */
                    237:   sun3 = (struct tme_sun3 *) conn_m68k->tme_bus_connection.tme_connection_element->tme_element_private;
                    238: 
                    239:   /* acknowledge any soft interrupt: */
                    240:   interreg = sun3->tme_sun3_ints;
                    241:   if ((ipl == 3
                    242:        && (interreg & TME_SUN3_IREG_SOFT_INT_3))
                    243:       || (ipl == 2
                    244:          && (interreg & TME_SUN3_IREG_SOFT_INT_2))
                    245:       || (ipl == 1
                    246:          && (interreg & TME_SUN3_IREG_SOFT_INT_1))) {
                    247:     *vector = TME_BUS_INTERRUPT_VECTOR_UNDEF;
                    248:     return (TME_OK);
                    249:   }
                    250: 
                    251:   /* turn the ipl into a bus signal number: */
                    252:   signal = TME_BUS_SIGNAL_INT(ipl);
                    253: 
                    254:   /* try the acknowledge on these buses, in order: */
                    255: 
                    256:   /* obio: */
                    257:   rc = (*sun3->tme_sun3_obio->tme_bus_intack)
                    258:     (sun3->tme_sun3_obio, signal, vector);
                    259:   if (rc == ENOENT
                    260:       && signal == sun3->tme_sun3_int_signal_clock_last) {
                    261:     rc = (*sun3->tme_sun3_obio->tme_bus_intack)
                    262:       (sun3->tme_sun3_obio, TME_BUS_SIGNAL_INT_CLOCK, vector);
                    263:   }
                    264:   if (rc != ENOENT) {
                    265:     return (rc);
                    266:   }
                    267:   /* obmem: */
                    268:   rc = (*sun3->tme_sun3_obmem->tme_bus_intack)
                    269:     (sun3->tme_sun3_obmem, signal, vector);
                    270:   if (rc != ENOENT) {
                    271:     return (rc);
                    272:   }
                    273:   /* VMEbus: */
                    274:   rc = (*sun3->tme_sun3_vmebus->tme_bus_intack)
                    275:     (sun3->tme_sun3_vmebus, signal, vector);
                    276:   if (rc != ENOENT) {
                    277:     return (rc);
                    278:   }
                    279: 
                    280:   /* done: */
                    281:   return (rc);
                    282: }
                    283: 
                    284: /* our command function: */
                    285: static int
                    286: _tme_sun3_command(struct tme_element *element, const char * const * args, char **_output)
                    287: {
                    288:   struct tme_sun3 *sun3;
                    289:   int do_reset;
                    290: 
                    291:   /* recover our sun3: */
                    292:   sun3 = (struct tme_sun3 *) element->tme_element_private;
                    293: 
                    294:   /* assume no reset: */
                    295:   do_reset = FALSE;
                    296: 
                    297:   /* the "power" command: */
                    298:   if (TME_ARG_IS(args[1], "power")) {
                    299: 
                    300:     if (TME_ARG_IS(args[2], "up")
                    301:        && args[3] == NULL) {
                    302:       do_reset = TRUE;
                    303:     }
                    304: 
                    305:     else if (TME_ARG_IS(args[2], "down")
                    306:             && args[3] == NULL) {
                    307:       /* nothing */
                    308:     }
                    309: 
                    310:     /* return an error: */
                    311:     else {
                    312:       tme_output_append_error(_output,
                    313:                              "%s %s power [ up | down ]",
                    314:                              _("usage:"),
                    315:                              args[0]);
                    316:       return (EINVAL);
                    317:     }
                    318:   }
                    319: 
                    320:   /* the "diag-switch" command: */
                    321:   else if (TME_ARG_IS(args[1], "diag-switch")) {
                    322: 
                    323:     if (args[2] == NULL) {
                    324:       tme_output_append_error(_output,
                    325:                              "diag-switch %s",
                    326:                              (sun3->tme_sun3_enable & TME_SUN3_ENA_DIAG
                    327:                               ? "true"
                    328:                               : "false"));
                    329:     }
                    330: 
                    331:     else if (TME_ARG_IS(args[2], "true")
                    332:             && args[3] == NULL) {
                    333:       sun3->tme_sun3_enable |= TME_SUN3_ENA_DIAG;
                    334:     }
                    335: 
                    336:     else if (TME_ARG_IS(args[2], "false")
                    337:             && args[3] == NULL) {
                    338:       sun3->tme_sun3_enable &= ~TME_SUN3_ENA_DIAG;
                    339:     }
                    340: 
                    341:     /* return an error: */
                    342:     else {
                    343:       tme_output_append_error(_output,
                    344:                              "%s %s diag-switch [ true | false ]",
                    345:                              _("usage:"),
                    346:                              args[0]);
                    347:       return (EINVAL);
                    348:     }
                    349:   }
                    350: 
                    351:   /* any other command: */
                    352:   else {
                    353:     if (args[1] != NULL) {
                    354:       tme_output_append_error(_output,
                    355:                              "%s '%s', ",
                    356:                              _("unknown command"),
                    357:                              args[1]);
                    358:     }
                    359:     tme_output_append_error(_output,
                    360:                            _("available %s commands: %s"),
                    361:                            args[0],
                    362:                            "power");
                    363:     return (EINVAL);
                    364:   }
                    365: 
                    366:   if (do_reset) {
                    367: 
                    368:     /* reset the CPU: */
                    369:     (*sun3->tme_sun3_m68k->tme_m68k_bus_connection.tme_bus_signal)
                    370:       (&sun3->tme_sun3_m68k->tme_m68k_bus_connection,
                    371:        TME_BUS_SIGNAL_RESET
                    372:        | TME_BUS_SIGNAL_LEVEL_NEGATED
                    373:        | TME_BUS_SIGNAL_EDGE);
                    374: 
                    375:     /* reset all busses: */
                    376:     (*sun3->tme_sun3_obio->tme_bus_signal)
                    377:       (sun3->tme_sun3_obio,
                    378:        TME_BUS_SIGNAL_RESET
                    379:        | TME_BUS_SIGNAL_LEVEL_NEGATED
                    380:        | TME_BUS_SIGNAL_EDGE);
                    381:     (*sun3->tme_sun3_obmem->tme_bus_signal)
                    382:       (sun3->tme_sun3_obmem,
                    383:        TME_BUS_SIGNAL_RESET
                    384:        | TME_BUS_SIGNAL_LEVEL_NEGATED
                    385:        | TME_BUS_SIGNAL_EDGE);
                    386:     (*sun3->tme_sun3_vmebus->tme_bus_signal)
1.1.1.2 ! root      387:       (sun3->tme_sun3_vmebus,
1.1       root      388:        TME_BUS_SIGNAL_RESET
                    389:        | TME_BUS_SIGNAL_LEVEL_NEGATED
                    390:        | TME_BUS_SIGNAL_EDGE);
                    391:   }
                    392: 
                    393:   return (TME_OK);
                    394: }
                    395: 
                    396: /* the connection scorer: */
                    397: static int
                    398: _tme_sun3_connection_score(struct tme_connection *conn, unsigned int *_score)
                    399: {
                    400:   struct tme_m68k_bus_connection *conn_m68k;
                    401:   struct tme_sun3_bus_connection *conn_sun3;
                    402:   struct tme_bus_connection *conn_bus;
                    403:   struct tme_sun3 *sun3;
                    404:   unsigned int score;
                    405: 
                    406:   /* recover our sun3: */
                    407:   sun3 = (struct tme_sun3 *) conn->tme_connection_element->tme_element_private;
                    408: 
                    409:   /* assume that this connection is useless: */
                    410:   score = 0;
                    411: 
                    412:   /* dispatch on the connection type: */
                    413:   conn_m68k = (struct tme_m68k_bus_connection *) conn->tme_connection_other;
                    414:   conn_sun3 = (struct tme_sun3_bus_connection *) conn;
                    415:   conn_bus = (struct tme_bus_connection *) conn->tme_connection_other;
                    416:   switch (conn->tme_connection_type) {
                    417: 
                    418:     /* this must be an m68k chip, and not another bus: */
                    419:   case TME_CONNECTION_BUS_M68K:
                    420:     if (conn_bus->tme_bus_tlb_set_allocate == NULL
                    421:        && conn_m68k->tme_m68k_bus_tlb_fill == NULL
                    422:        && conn_m68k->tme_m68k_bus_m6888x_enable != NULL) {
                    423:       score = 10;
                    424:     }
                    425:     break;
                    426: 
                    427:     /* if this connection is not for an obio master, this must be a bus,
                    428:        and not a chip, and vice versa.  if this connection is for a bus,
                    429:        the bus must still be free: */
                    430:   case TME_CONNECTION_BUS_GENERIC:
                    431:     if (((conn_sun3->tme_sun3_bus_connection_which != TME_SUN3_CONN_OBIO_MASTER)
                    432:         == (conn_bus->tme_bus_tlb_set_allocate != NULL
                    433:             && conn_bus->tme_bus_tlb_fill != NULL))
                    434:        && (conn_sun3->tme_sun3_bus_connection_which >= TME_SUN3_CONN_BUS_COUNT
                    435:            || sun3->tme_sun3_buses[conn_sun3->tme_sun3_bus_connection_which] == NULL)) {
                    436:       score = 1;
                    437:     }
                    438:     break;
                    439: 
                    440:   default: abort();
                    441:   }
                    442: 
                    443:   *_score = score;
                    444:   return (TME_OK);
                    445: }
                    446: 
                    447: /* this makes a new connection: */
                    448: static int
                    449: _tme_sun3_connection_make(struct tme_connection *conn, unsigned int state)
                    450: {
                    451:   struct tme_sun3 *sun3;
                    452:   struct tme_m68k_bus_connection *conn_m68k;
                    453:   struct tme_sun3_bus_connection *conn_sun3;
                    454:   struct tme_bus_connection *conn_bus;
                    455:   struct tme_connection *conn_other;
                    456: 
                    457:   /* recover our sun3: */
                    458:   sun3 = (struct tme_sun3 *) conn->tme_connection_element->tme_element_private;
                    459: 
                    460:   /* dispatch on the connection type: */
                    461:   conn_other = conn->tme_connection_other;
                    462:   conn_m68k = (struct tme_m68k_bus_connection *) conn_other;
                    463:   conn_sun3 = (struct tme_sun3_bus_connection *) conn;
                    464:   conn_bus = (struct tme_bus_connection *) conn_other;
                    465:   switch (conn->tme_connection_type) {
                    466:       
                    467:   case TME_CONNECTION_BUS_M68K:
                    468:     sun3->tme_sun3_m68k = conn_m68k;
                    469:     break;
                    470:       
                    471:   case TME_CONNECTION_BUS_GENERIC:
                    472: 
                    473:     /* if this connection is for a bus: */
                    474:     if (conn_sun3->tme_sun3_bus_connection_which < TME_SUN3_CONN_BUS_COUNT) {
                    475: 
                    476:       /* remember the connection to this bus: */
                    477:       sun3->tme_sun3_buses[conn_sun3->tme_sun3_bus_connection_which] = conn_bus;
                    478:     }
                    479: 
                    480:     /* otherwise, if this connection is for the memory error register: */
                    481:     else if (conn_sun3->tme_sun3_bus_connection_which == TME_SUN3_CONN_REG_MEMERR) {
                    482: 
                    483:       /* remember the memory error register's bus connection: */
                    484:       sun3->tme_sun3_memerr_bus = conn_bus;
                    485:     }
                    486: 
                    487:     break;
                    488: 
                    489:   default: 
                    490:     assert(FALSE);
                    491:     break;
                    492:   }
                    493:   return (TME_OK);
                    494: }
                    495: 
                    496: /* this breaks a connection: */
                    497: static int 
                    498: _tme_sun3_connection_break(struct tme_connection *conn, unsigned int state)
                    499: {
                    500:   abort();
                    501: }
                    502: 
                    503: /* this makes new connection sides: */
                    504: static int
                    505: _tme_sun3_connections_new(struct tme_element *element, const char * const *args, struct tme_connection **_conns, char **_output)
                    506: {
                    507:   struct tme_m68k_bus_connection *conn_m68k;
                    508:   struct tme_sun3_bus_connection *conn_sun3;
                    509:   struct tme_bus_connection *conn_bus;
                    510:   struct tme_connection *conn;
                    511:   struct tme_sun3 *sun3;
                    512:   char *free_buses;
                    513:   int which_conn;
                    514: 
                    515:   /* recover our sun3: */
                    516:   sun3 = (struct tme_sun3 *) element->tme_element_private;
                    517: 
                    518:   /* if we have no arguments, and we don't have a CPU yet, we can take
                    519:      an m68k bus connection: */
                    520:   if (args[1] == NULL
                    521:       && sun3->tme_sun3_m68k == NULL) {
                    522: 
                    523:     /* create our side of an m68k bus connection: */
                    524:     conn_m68k = tme_new0(struct tme_m68k_bus_connection, 1);
                    525:     conn_bus = &conn_m68k->tme_m68k_bus_connection;
                    526:     conn = &conn_bus->tme_bus_connection;
                    527:     conn->tme_connection_next = *_conns;
                    528: 
                    529:     /* fill in the generic connection: */
                    530:     conn->tme_connection_type = TME_CONNECTION_BUS_M68K;
                    531:     conn->tme_connection_score = _tme_sun3_connection_score;
                    532:     conn->tme_connection_make = _tme_sun3_connection_make;
                    533:     conn->tme_connection_break = _tme_sun3_connection_break;
                    534: 
                    535:     /* fill in the generic bus connection: */
                    536:     conn_bus->tme_bus_signal = _tme_sun3_bus_signal;
                    537:     conn_bus->tme_bus_intack = _tme_sun3_bus_intack;
                    538:     conn_bus->tme_bus_tlb_set_allocate = _tme_sun3_mmu_tlb_set_allocate;
                    539: 
                    540:     /* full in the m68k bus connection: */
                    541:     conn_m68k->tme_m68k_bus_tlb_fill = _tme_sun3_m68k_tlb_fill;
                    542: 
                    543:     /* add in this connection side possibility: */
                    544:     *_conns = conn;
                    545:   }
                    546: 
                    547:   /* create our side of a generic bus connection: */
                    548:   conn_sun3 = tme_new0(struct tme_sun3_bus_connection, 1);
                    549:   conn_bus = &conn_sun3->tme_sun3_bus_connection;
                    550:   conn = &conn_bus->tme_bus_connection;
                    551:   conn->tme_connection_next = *_conns;
                    552: 
                    553:   /* fill in the generic connection: */
                    554:   conn->tme_connection_type = TME_CONNECTION_BUS_GENERIC;
                    555:   conn->tme_connection_score = _tme_sun3_connection_score;
                    556:   conn->tme_connection_make = _tme_sun3_connection_make;
                    557:   conn->tme_connection_break = _tme_sun3_connection_break;
                    558:     
                    559:   /* fill in the generic bus connection: */
                    560:   conn_bus->tme_bus_signal = _tme_sun3_bus_signal;
                    561:   conn_bus->tme_bus_intack = NULL;
                    562:   conn_bus->tme_bus_tlb_set_allocate = _tme_sun3_mmu_tlb_set_allocate;
                    563:   conn_bus->tme_bus_tlb_fill = _tme_sun3_bus_tlb_fill;
                    564: 
                    565:   /* if we have no argument: */
                    566:   if (args[1] == NULL) {
                    567: 
                    568:     /* make this connection for an obio master: */
                    569:     conn_sun3->tme_sun3_bus_connection_which = TME_SUN3_CONN_OBIO_MASTER;
                    570:   }
                    571: 
                    572:   /* otherwise, we have at least one argument: */
                    573:   else {
                    574: 
                    575:     /* we must have no other arguments: */
                    576:     if (args[2] != NULL) {
                    577:       tme_output_append_error(_output,
                    578:                              "%s %s",
                    579:                              args[2],
                    580:                              _("unexpected"));
                    581:       tme_free(conn_sun3);
                    582:       return (EINVAL);
                    583:     }
                    584: 
                    585:     /* start the list of buses that we don't have yet: */
                    586:     free_buses = NULL;
                    587: 
                    588:     /* poison the which connection: */
                    589:     which_conn = -1;
                    590: 
                    591:     /* check each bus: */
                    592: 
                    593:     /* obio: */
                    594:     if (sun3->tme_sun3_obio == NULL) {
                    595:       tme_output_append(&free_buses, " obio");
                    596:     }
                    597:     if (TME_ARG_IS(args[1], "obio")) {
                    598:       which_conn = TME_SUN3_CONN_BUS_OBIO;
                    599:     }
                    600: 
                    601:     /* obmem: */
                    602:     if (sun3->tme_sun3_obmem == NULL) {
                    603:       tme_output_append(&free_buses, " obmem");
                    604:     }
                    605:     if (TME_ARG_IS(args[1], "obmem")) {
                    606:       which_conn = TME_SUN3_CONN_BUS_OBMEM;
                    607:     }
                    608: 
                    609:     /* VMEbus: */
                    610:     if (sun3->tme_sun3_vmebus == NULL) {
                    611:       tme_output_append(&free_buses, " vme");
                    612:     }
                    613:     if (TME_ARG_IS(args[1], "vme")) {
                    614:       which_conn = TME_SUN3_CONN_BUS_VME;
                    615:       conn_bus->tme_bus_subregions.tme_bus_subregion_address_last
                    616:        = TME_SUN3_DVMA_SIZE_VME;
                    617:     }
                    618: 
                    619:     /* random connections: */
                    620:     
                    621:     if (TME_ARG_IS(args[1], "memerr")) {
                    622:       which_conn = TME_SUN3_CONN_REG_MEMERR;
                    623:       conn_bus->tme_bus_subregions.tme_bus_subregion_address_last
                    624:        = TME_SUN3_MEMERR_SIZ_REG;
                    625:     }
                    626:     else if (TME_ARG_IS(args[1], "intreg")) {
                    627:       which_conn = TME_SUN3_CONN_REG_INTREG;
                    628:       conn_bus->tme_bus_subregions.tme_bus_subregion_address_last
                    629:        = sizeof(sun3->tme_sun3_ints);
                    630:     }
                    631: 
                    632:     /* if the which connection is still poison, or if this is trying
                    633:        to connect a bus that we already have, complain: */
                    634:     if (which_conn < 0
                    635:        || (which_conn < TME_SUN3_CONN_BUS_COUNT
                    636:            && sun3->tme_sun3_buses[which_conn] != NULL)) {
                    637:       if (which_conn < 0) {
                    638:        tme_output_append_error(_output,
                    639:                                "%s %s",
                    640:                                _("unknown bus or register:"),
                    641:                                args[1]);
                    642:       }
                    643:       if (free_buses != NULL) {
                    644:        tme_output_append_error(_output, 
                    645:                                "%s %s",
                    646:                                _("remaining buses:"),
                    647:                                free_buses);
                    648:        tme_free(free_buses);
                    649:       }
                    650:       else {
                    651:        tme_output_append_error(_output, _("all buses present"));
                    652:       }
                    653:       tme_free(conn_sun3);
                    654:       return (EINVAL);
                    655:     }
                    656: 
                    657:     /* free the remaining bus list: */
                    658:     if (free_buses != NULL) {
                    659:       tme_free(free_buses);
                    660:     }
                    661: 
                    662:     /* fill in the sun3 connection: */
                    663:     conn_sun3->tme_sun3_bus_connection_which = which_conn;
                    664:   }
                    665: 
                    666:   /* add in this connection side possibility: */
                    667:   *_conns = conn;
                    668: 
                    669:   /* done: */
                    670:   return (TME_OK);
                    671: }
                    672: 
                    673: /* this creates a new sun3 element: */
                    674: TME_ELEMENT_NEW_DECL(tme_machine_sun3) {
                    675:   int usage;
                    676:   struct tme_sun3 *sun3;
                    677:   const char *idprom_filename;
                    678:   FILE *idprom_fp;
                    679:   tme_uint8_t idprom[TME_SUN_IDPROM_SIZE];
                    680:   int arg_i;
                    681: 
                    682:   arg_i = 1;
                    683:   usage = FALSE;
                    684: 
                    685:   /* our first argument is the filename to load our IDPROM contents from: */
                    686:   idprom_filename = args[arg_i++];
                    687:   if (idprom_filename == NULL) {
                    688:     usage = TRUE;
                    689:   }
                    690: 
                    691:   /* we must have no more arguments: */
                    692:   if (args[arg_i] != NULL) {
                    693:     tme_output_append_error(_output,
                    694:                            "%s %s, ",
                    695:                            args[arg_i],
                    696:                            _("unexpected"));
                    697:     usage = TRUE;
                    698:   }
                    699: 
                    700:   /* if our usage was bad: */
                    701:   if (usage) {
                    702:     tme_output_append_error(_output,
                    703:                            "%s %s IDPROM%s",
                    704:                            _("usage:"),
                    705:                            args[0],
                    706:                            _("-FILENAME"));
                    707:     return (EINVAL);
                    708:   }
                    709: 
                    710:   /* try to read in the IDPROM: */
                    711:   idprom_fp = fopen(idprom_filename, "r");
                    712:   if (idprom_fp == NULL) {
                    713:     tme_output_append_error(_output, idprom_filename);
                    714:     return (errno);
                    715:   }
                    716:   if (fread(idprom, sizeof(tme_uint8_t), sizeof(idprom), idprom_fp) != sizeof(idprom)) {
                    717:     tme_output_append_error(_output, idprom_filename);
                    718:     fclose(idprom_fp);
                    719:     return (ENOEXEC);
                    720:   }
                    721:   fclose(idprom_fp);
                    722: 
                    723:   /* allocate and initialize the new sun3: */
                    724:   sun3 = tme_new0(struct tme_sun3, 1);
                    725:   sun3->tme_sun3_element = element;
                    726: 
                    727:   /* set the IDPROM: */
                    728:   memcpy(sun3->tme_sun3_idprom_contents, idprom, sizeof(idprom));
                    729:   
                    730:   /* the context register: */
                    731:   sun3->tme_sun3_context = 0;
                    732: 
                    733:   /* the diagnostics register: */
                    734:   sun3->tme_sun3_diag = 0;
                    735: 
                    736:   /* the bus error register: */
                    737:   sun3->tme_sun3_buserr = 0;
                    738: 
                    739:   /* the enable register: */
                    740:   sun3->tme_sun3_enable = 0;
                    741: 
                    742:   /* the memory error register: */
                    743:   sun3->tme_sun3_memerr_csr = 0;
                    744:   sun3->tme_sun3_memerr_vaddr = 0;
                    745: 
                    746:   /* the interrupt register: */
                    747:   sun3->tme_sun3_ints = 0;
                    748: 
                    749:   /* the MMU: */
                    750:   _tme_sun3_mmu_new(sun3);
                    751: 
                    752:   /* the busses: */
                    753:   sun3->tme_sun3_obio = NULL;
                    754:   sun3->tme_sun3_obmem = NULL;
                    755:   sun3->tme_sun3_vmebus = NULL;
                    756: 
                    757:   /* the last clock interrupt signal: */
                    758:   sun3->tme_sun3_int_signal_clock_last = TME_BUS_SIGNAL_INT_UNSPEC;
                    759: 
                    760:   /* fill the element: */
                    761:   element->tme_element_private = sun3;
                    762:   element->tme_element_connections_new = _tme_sun3_connections_new;
                    763:   element->tme_element_command = _tme_sun3_command;
                    764: 
                    765:   return (TME_OK);
                    766: }
                    767: 
                    768: /* this creates a new Sun-3 isil7170: */
                    769: TME_ELEMENT_SUB_NEW_DECL(tme_machine_sun3,clock) {
                    770:   struct tme_isil7170_socket socket;
                    771:   const char *sub_args[4];
                    772:   int arg_i;
                    773: 
                    774:   /* create the isil7170 socket: */
                    775:   memset (&socket, 0, sizeof(socket));
                    776:   socket.tme_isil7170_socket_version = TME_ISIL7170_SOCKET_0;
                    777:   socket.tme_isil7170_socket_addr_shift = 0;
                    778:   socket.tme_isil7170_socket_port_least_lane = 3; /* D31-D24 */
                    779:   socket.tme_isil7170_socket_clock_basic = TME_ISIL7170_FREQ_32K;
                    780:   socket.tme_isil7170_socket_int_signal = TME_BUS_SIGNAL_INT_CLOCK;
                    781: 
                    782:   /* create the isil7170.  we allow at most two arguments to pass
                    783:      through, which is an awful hack: */
                    784:   sub_args[0] = "tme/ic/isil7170";
                    785:   for (arg_i = 1;; arg_i++) {
                    786:     if (arg_i == TME_ARRAY_ELS(sub_args)) {
                    787:       abort();
                    788:     }
                    789:     sub_args[arg_i] = args[arg_i];
                    790:     if (args[arg_i] == NULL) {
                    791:       break;
                    792:     }
                    793:   }
                    794:   return (tme_element_new(element, (const char * const *) sub_args, &socket, _output));
                    795: }
                    796: 
                    797: /* this creates a new Sun-3 z8530: */
                    798: TME_ELEMENT_SUB_NEW_DECL(tme_machine_sun3,zs) {
                    799:   struct tme_z8530_socket socket = TME_SUN_Z8530_SOCKET_INIT;
                    800:   char *sub_args[2];
                    801: 
                    802:   /* create the z8530: */
                    803:   sub_args[0] = "tme/ic/z8530";
                    804:   sub_args[1] = NULL;
                    805:   return (tme_element_new(element, (const char * const *) sub_args, &socket, _output));
                    806: }
                    807: 
                    808: /* this creates a new Sun-3 obie: */
                    809: TME_ELEMENT_SUB_NEW_DECL(tme_machine_sun3,obie) {
                    810:   return (tme_sun_obie(element, args, _output));
                    811: }
                    812: 
                    813: /* this creates a new Sun-3 bwtwo: */
                    814: TME_ELEMENT_SUB_NEW_DECL(tme_machine_sun3,bwtwo) {
                    815:   return (tme_sun_bwtwo(element, args, _output));
                    816: }
                    817: 
                    818: /* this creates a new Sun-3 si: */
                    819: TME_ELEMENT_SUB_NEW_DECL(tme_machine_sun3,si) {
                    820:   return (tme_sun_si(element, args, _output));
                    821: }
                    822: 
                    823: /* this creates a new Sun-3 cgtwo: */
                    824: TME_ELEMENT_SUB_NEW_DECL(tme_machine_sun3,cgtwo) {
                    825:   return (tme_sun_cgtwo(element, args, _output));
                    826: }

unix.superglobalmegacorp.com

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