Annotation of tme/machine/sun3/sun3-mainbus.c, revision 1.1.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.