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

1.1.1.2 ! root        1: /* $Id: sun4-mainbus.c,v 1.6 2009/08/30 14:03:11 fredette Exp $ */
1.1       root        2: 
                      3: /* machine/sun4/sun4-mainbus.c - implementation of Sun 4 emulation: */
                      4: 
                      5: /*
                      6:  * Copyright (c) 2003, 2004, 2006 Matt Fredette
                      7:  * All rights reserved.
                      8:  *
                      9:  * Redistribution and use in source and binary forms, with or without
                     10:  * modification, are permitted provided that the following conditions
                     11:  * are met:
                     12:  * 1. Redistributions of source code must retain the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer.
                     14:  * 2. Redistributions in binary form must reproduce the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer in the
                     16:  *    documentation and/or other materials provided with the distribution.
                     17:  * 3. All advertising materials mentioning features or use of this software
                     18:  *    must display the following acknowledgement:
                     19:  *      This product includes software developed by Matt Fredette.
                     20:  * 4. The name of the author may not be used to endorse or promote products
                     21:  *    derived from this software without specific prior written permission.
                     22:  *
                     23:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     24:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
                     25:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
                     26:  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
                     27:  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
                     28:  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
                     29:  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     30:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
                     31:  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
                     32:  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     33:  * POSSIBILITY OF SUCH DAMAGE.
                     34:  */
                     35: 
                     36: #include <tme/common.h>
1.1.1.2 ! root       37: _TME_RCSID("$Id: sun4-mainbus.c,v 1.6 2009/08/30 14:03:11 fredette Exp $");
1.1       root       38: 
                     39: /* includes: */
                     40: #include "sun4-impl.h"
                     41: #include <tme/ic/z8530.h>
                     42: #include <tme/ic/isil7170.h>
                     43: #include <tme/ic/mk48txx.h>
                     44: #include <stdio.h>
                     45: 
                     46: /* this possibly updates that the interrupt priority level driven to the CPU: */
                     47: int
                     48: _tme_sun4_ipl_check(struct tme_sun4 *sun4)
                     49: {
                     50:   unsigned int ipl;
                     51:   unsigned int ipl_index;
                     52:   tme_uint8_t ipl_mask;
                     53:   tme_uint32_t interreg;
                     54:   int rc;
                     55: 
                     56:   /* find the highest ipl now asserted on the buses, that is enabled
                     57:      to the CPU: */
                     58:   ipl = TME_SPARC_IPL_MAX;
                     59:   ipl_index = ipl / 8;
                     60:   ipl_mask = TME_BIT(ipl % 8);
                     61:   do {
                     62: 
                     63:     /* if this ipl is asserted: */
                     64:     if ((sun4->tme_sun4_int_signals[ipl_index] & ipl_mask) != 0) {
                     65: 
                     66:       /* if this ipl is not disabled: */
                     67:       if (TME_SUN4_IS_SUN44C(sun4)
                     68:          ? ((sun4->tme_sun44c_ints & TME_SUN44C_IREG_INTS_ENAB)
                     69:             && (ipl != 10 || (sun4->tme_sun44c_ints & TME_SUN44C_IREG_COUNTER_L10))
                     70:             && (ipl != 14 || (sun4->tme_sun44c_ints & TME_SUN44C_IREG_COUNTER_L14)))
                     71:          : TRUE) {
                     72: 
                     73:        /* stop now: */
                     74:        break;
                     75:       }
                     76:     }
                     77: 
                     78:     /* advance to the next ipl: */
                     79:     ipl--;
                     80:     ipl_mask >>= 1;
                     81:     if (ipl_mask == 0) {
                     82:       ipl_mask = 0x80;
                     83:       ipl_index--;
                     84:     }
                     85:   } while (ipl != TME_SPARC_IPL_NONE);
                     86: 
                     87:   /* if this is a sun4 or sun4c: */
                     88:   if (TME_SUN4_IS_SUN44C(sun4)) {
                     89:     
                     90:     /* get the sun4/4c interrupt register: */
                     91:     interreg = sun4->tme_sun44c_ints;
                     92: 
                     93:     /* if interrupts are enabled: */
                     94:     if (interreg & TME_SUN44C_IREG_INTS_ENAB) {
                     95: 
                     96:       /* check the soft interrupts: */
                     97:       if (interreg & TME_SUN44C_IREG_SOFT_INT_L6) {
                     98:        ipl = TME_MAX(ipl, 6);
                     99:       }
                    100:       else if (interreg & TME_SUN44C_IREG_SOFT_INT_L4) {
                    101:        ipl = TME_MAX(ipl, 4);
                    102:       }
                    103:       else if (interreg & TME_SUN44C_IREG_SOFT_INT_L1) {
                    104:        ipl = TME_MAX(ipl, 1);
                    105:       }
                    106:     }
                    107:   }
                    108: 
                    109:   /* possibly update the CPU: */
                    110:   if (ipl != sun4->tme_sun4_int_ipl_last) {
                    111:     sun4->tme_sun4_int_ipl_last = ipl;
                    112:     rc = ((*sun4->tme_sun4_sparc->tme_sparc_bus_interrupt)
                    113:          (sun4->tme_sun4_sparc, ipl));
                    114:     assert (rc == TME_OK);
                    115:   }
                    116: 
                    117:   /* return nonzero if any interrupt is pending: */
                    118:   return (ipl != TME_SPARC_IPL_NONE);
                    119: }
                    120: 
                    121: /* our mainbus signal handler: */
                    122: static int
                    123: _tme_sun4_bus_signal(struct tme_bus_connection *conn_bus_raiser, unsigned int signal)
                    124: {
                    125:   struct tme_sun4 *sun4;
                    126:   int signal_asserted;
                    127:   unsigned int ipl, ipl_index;
                    128:   tme_uint8_t ipl_mask;
                    129: 
                    130:   /* recover our sun4: */
                    131:   sun4 = (struct tme_sun4 *) conn_bus_raiser->tme_bus_connection.tme_connection_element->tme_element_private;
                    132: 
                    133:   /* see whether the signal is asserted or negated: */
                    134:   signal_asserted = TRUE;
                    135:   switch (signal & TME_BUS_SIGNAL_LEVEL_MASK) {
                    136:   case TME_BUS_SIGNAL_LEVEL_NEGATED:
                    137:     signal_asserted = FALSE;
                    138:   case TME_BUS_SIGNAL_LEVEL_ASSERTED:
                    139:     break;
                    140:   default:
                    141:     abort();
                    142:   }
                    143:   signal = TME_BUS_SIGNAL_WHICH(signal);
                    144: 
                    145:   /* dispatch on the signal: */
                    146: 
                    147:   /* halt: */
                    148:   if (signal == TME_BUS_SIGNAL_HALT) {
                    149:     abort();
                    150:   }
                    151: 
                    152:   /* reset: */
                    153:   else if (signal == TME_BUS_SIGNAL_RESET) {
                    154:     /* XXX reset is just ignored for now: */
                    155:   }
                    156: 
                    157:   /* an interrupt signal: */
                    158:   else if (TME_BUS_SIGNAL_IS_INT(signal)) {
                    159:     ipl = TME_BUS_SIGNAL_INDEX_INT(signal);
                    160:     if (ipl >= TME_SPARC_IPL_MIN
                    161:        && ipl <= TME_SPARC_IPL_MAX) {
                    162:       
                    163:       /* update this ipl in the byte array: */
                    164:       ipl_index = ipl / 8;
                    165:       ipl_mask = TME_BIT(ipl % 8);
                    166:       sun4->tme_sun4_int_signals[ipl_index]
                    167:        = ((sun4->tme_sun4_int_signals[ipl_index]
                    168:            & ~ipl_mask)
                    169:           | (signal_asserted
                    170:              ? ipl_mask
                    171:              : 0));
                    172: 
                    173:       /* possibly update the ipl being driven to the CPU: */
                    174:       _tme_sun4_ipl_check(sun4);
                    175:       return (TME_OK);
                    176:     }
                    177:   }
                    178: 
                    179:   /* an unknown signal: */
                    180:   else {
                    181:     abort();
                    182:   }
                    183: 
                    184:   return (TME_OK);
                    185: }
                    186: 
                    187: /* this handles a CPU interrupt acknowledge: */
                    188: static int
                    189: _tme_sun4_bus_intack(struct tme_bus_connection *conn_sparc, unsigned int ipl, int *vector)
                    190: {
                    191:   struct tme_sun4 *sun4;
                    192:   tme_uint32_t interreg;
                    193:   unsigned int signal;
                    194:   int rc;
                    195: 
                    196:   /* recover our sun4: */
                    197:   sun4 = (struct tme_sun4 *) conn_sparc->tme_bus_connection.tme_connection_element->tme_element_private;
                    198: 
                    199:   /* acknowledge any soft interrupt: */
                    200:   if (TME_SUN4_IS_SUN44C(sun4)) {
                    201:     interreg = sun4->tme_sun44c_ints;
                    202:     if ((ipl == 6
                    203:         && (interreg & TME_SUN44C_IREG_SOFT_INT_L6))
                    204:        || (ipl == 4
                    205:            && (interreg & TME_SUN44C_IREG_SOFT_INT_L4))
                    206:        || (ipl == 1
                    207:            && (interreg & TME_SUN44C_IREG_SOFT_INT_L1))) {
                    208:       *vector = TME_BUS_INTERRUPT_VECTOR_UNDEF;
                    209:       return (TME_OK);
                    210:     }
                    211:   }
                    212: 
                    213:   /* turn the ipl into a bus signal number: */
                    214:   signal = TME_BUS_SIGNAL_INT(ipl);
                    215: 
                    216:   /* try the acknowledge on these buses, in order: */
                    217: 
                    218:   /* obio: */
                    219:   rc = (*sun4->tme_sun4_32_obio->tme_bus_intack)
                    220:     (sun4->tme_sun4_32_obio, signal, vector);
                    221:   if (rc != ENOENT) {
                    222:     return (rc);
                    223:   }
                    224:   /* obmem: */
                    225:   if (!TME_SUN4_IS_SUN4C(sun4)) {
                    226:     rc = (*sun4->tme_sun4_32_obmem->tme_bus_intack)
                    227:       (sun4->tme_sun4_32_obmem, signal, vector);
                    228:     if (rc != ENOENT) {
                    229:       return (rc);
                    230:     }
                    231:   }
                    232:   /* VMEbus: */
                    233:   if (TME_SUN4_IS_SUN4(sun4)) {
                    234:     rc = (*sun4->tme_sun4_vmebus->tme_bus_intack)
                    235:       (sun4->tme_sun4_vmebus, signal, vector);
                    236:     if (rc != ENOENT) {
                    237:       return (rc);
                    238:     }
                    239:   }
                    240: 
                    241:   /* done: */
                    242:   return (rc);
                    243: }
                    244: 
                    245: /* this resets the board: */
                    246: int
                    247: _tme_sun4_reset(struct tme_sun4 *sun4, int soft)
                    248: {
                    249: 
                    250:   /* clear the sun4/4c enable register: */
                    251:   sun4->tme_sun44c_enable = 0;
                    252:   
                    253:   /* clear the sun4/4c interrupt register: */
                    254:   sun4->tme_sun44c_ints = 0;
                    255: 
                    256:   /* clear any NMI: */
                    257:   sun4->tme_sun4_int_signals[TME_SPARC_IPL_NMI / 8] &= ~TME_BIT(TME_SPARC_IPL_NMI % 8);
                    258: 
                    259:   /* reset the CPU: */
                    260:   (*sun4->tme_sun4_sparc->tme_sparc_bus_connection.tme_bus_signal)
                    261:     (&sun4->tme_sun4_sparc->tme_sparc_bus_connection,
                    262:      TME_BUS_SIGNAL_RESET
                    263:      | TME_BUS_SIGNAL_LEVEL_NEGATED
                    264:      | TME_BUS_SIGNAL_EDGE);
                    265: 
                    266:   /* reset all busses: */
                    267:   (*sun4->tme_sun4_32_obio->tme_bus_signal)
                    268:     (sun4->tme_sun4_32_obio,
                    269:      TME_BUS_SIGNAL_RESET
                    270:      | TME_BUS_SIGNAL_LEVEL_NEGATED
                    271:      | TME_BUS_SIGNAL_EDGE);
                    272:   if (!TME_SUN4_IS_SUN4C(sun4)) {
                    273:     (*sun4->tme_sun4_32_obmem->tme_bus_signal)
                    274:       (sun4->tme_sun4_32_obmem,
                    275:        TME_BUS_SIGNAL_RESET
                    276:        | TME_BUS_SIGNAL_LEVEL_NEGATED
                    277:        | TME_BUS_SIGNAL_EDGE);
                    278:   }
                    279:   if (TME_SUN4_IS_SUN4(sun4)) {
                    280:     (*sun4->tme_sun4_vmebus->tme_bus_signal)
                    281:       (sun4->tme_sun4_vmebus,
                    282:        TME_BUS_SIGNAL_RESET
                    283:        | TME_BUS_SIGNAL_LEVEL_NEGATED
                    284:        | TME_BUS_SIGNAL_EDGE);
                    285:   }
                    286: 
                    287:   /* in case this reset was caused by a bus cycle, be sure to tell the
                    288:      initiator to check for a synchronous event: */
                    289:   return (TME_BUS_CYCLE_SYNCHRONOUS_EVENT);
                    290: }
                    291: 
                    292: /* our command function: */
                    293: static int
                    294: _tme_sun4_command(struct tme_element *element, const char * const * args, char **_output)
                    295: {
                    296:   struct tme_sun4 *sun4;
                    297:   int do_reset;
                    298: 
                    299:   /* recover our sun4: */
                    300:   sun4 = (struct tme_sun4 *) element->tme_element_private;
                    301: 
                    302:   /* assume no reset: */
                    303:   do_reset = FALSE;
                    304: 
                    305:   /* the "power" command: */
                    306:   if (TME_ARG_IS(args[1], "power")) {
                    307: 
                    308:     if (TME_ARG_IS(args[2], "up")
                    309:        && args[3] == NULL) {
                    310:       do_reset = TRUE;
                    311:     }
                    312: 
                    313:     else if (TME_ARG_IS(args[2], "down")
                    314:             && args[3] == NULL) {
                    315:       /* nothing */
                    316:     }
                    317: 
                    318:     /* return an error: */
                    319:     else {
                    320:       tme_output_append_error(_output,
                    321:                              "%s %s power [ up | down ]",
                    322:                              _("usage:"),
                    323:                              args[0]);
                    324:       return (EINVAL);
                    325:     }
                    326:   }
                    327: 
                    328:   /* the "diag-switch" command: */
                    329:   else if (TME_SUN4_IS_SUN4(sun4)
                    330:           && TME_ARG_IS(args[1], "diag-switch")) {
                    331: 
                    332:     if (args[2] == NULL) {
                    333:       tme_output_append_error(_output,
                    334:                              "diag-switch %s",
                    335:                              (sun4->tme_sun44c_enable & TME_SUN4_ENA_DIAG
                    336:                               ? "true"
                    337:                               : "false"));
                    338:     }
                    339: 
                    340:     else if (TME_ARG_IS(args[2], "true")
                    341:             && args[3] == NULL) {
                    342:       sun4->tme_sun44c_enable |= TME_SUN4_ENA_DIAG;
                    343:     }
                    344: 
                    345:     else if (TME_ARG_IS(args[2], "false")
                    346:             && args[3] == NULL) {
                    347:       sun4->tme_sun44c_enable &= ~TME_SUN4_ENA_DIAG;
                    348:     }
                    349: 
                    350:     /* return an error: */
                    351:     else {
                    352:       tme_output_append_error(_output,
                    353:                              "%s %s diag-switch [ true | false ]",
                    354:                              _("usage:"),
                    355:                              args[0]);
                    356:       return (EINVAL);
                    357:     }
                    358:   }
                    359: 
                    360:   /* any other command: */
                    361:   else {
                    362:     if (args[1] != NULL) {
                    363:       tme_output_append_error(_output,
                    364:                              "%s '%s', ",
                    365:                              _("unknown command"),
                    366:                              args[1]);
                    367:     }
                    368:     tme_output_append_error(_output,
                    369:                            _("available %s commands: %s%s"),
                    370:                            args[0],
                    371:                            "power",
                    372:                            (TME_SUN4_IS_SUN4(sun4)
                    373:                             ? "diag-switch"
                    374:                             : ""));
                    375:     return (EINVAL);
                    376:   }
                    377: 
                    378:   if (do_reset) {
                    379:     _tme_sun4_reset(sun4, FALSE);
                    380:   }
                    381: 
                    382:   return (TME_OK);
                    383: }
                    384: 
                    385: /* the connection scorer: */
                    386: static int
                    387: _tme_sun4_connection_score(struct tme_connection *conn, unsigned int *_score)
                    388: {
                    389:   struct tme_sparc_bus_connection *conn_sparc;
                    390:   struct tme_sun4_bus_connection *conn_sun4;
                    391:   struct tme_bus_connection *conn_bus;
                    392:   struct tme_sun4 *sun4;
                    393:   unsigned int score;
                    394: 
                    395:   /* recover our sun4: */
                    396:   sun4 = (struct tme_sun4 *) conn->tme_connection_element->tme_element_private;
                    397: 
                    398:   /* assume that this connection is useless: */
                    399:   score = 0;
                    400: 
                    401:   /* dispatch on the connection type: */
                    402:   conn_sparc = (struct tme_sparc_bus_connection *) conn->tme_connection_other;
                    403:   conn_sun4 = (struct tme_sun4_bus_connection *) conn;
                    404:   conn_bus = (struct tme_bus_connection *) conn->tme_connection_other;
                    405:   switch (conn->tme_connection_type) {
                    406: 
                    407:     /* this must be an SPARC chip, and not another bus: */
                    408:   case TME_CONNECTION_BUS_SPARC:
1.1.1.2 ! root      409:     if (conn_bus->tme_bus_tlb_set_add == NULL
1.1       root      410:        && conn_sparc->tme_sparc_bus_tlb_fill == NULL
                    411:        && conn_sparc->tme_sparc_bus_fpu_strict != NULL) {
                    412:       score = 10;
                    413:     }
                    414:     break;
                    415: 
                    416:     /* this must be a bus, and not a chip, and the bus must still be
                    417:        free: */
                    418:   case TME_CONNECTION_BUS_GENERIC:
1.1.1.2 ! root      419:     if ((conn_bus->tme_bus_tlb_set_add != NULL
1.1       root      420:         && conn_bus->tme_bus_tlb_fill != NULL)
                    421:        && (conn_sun4->tme_sun4_bus_connection_which >= TME_SUN4_32_CONN_BUS_COUNT
                    422:            || sun4->tme_sun4_buses[conn_sun4->tme_sun4_bus_connection_which] == NULL)) {
                    423:       score = 1;
                    424:     }
                    425:     break;
                    426: 
                    427:   default: abort();
                    428:   }
                    429: 
                    430:   *_score = score;
                    431:   return (TME_OK);
                    432: }
                    433: 
                    434: /* this makes a new connection: */
                    435: static int
                    436: _tme_sun4_connection_make(struct tme_connection *conn, unsigned int state)
                    437: {
                    438:   struct tme_sun4 *sun4;
                    439:   struct tme_sparc_bus_connection *conn_sparc;
                    440:   struct tme_sun4_bus_connection *conn_sun4;
                    441:   struct tme_bus_connection *conn_bus;
                    442:   struct tme_connection *conn_other;
                    443: 
                    444:   /* recover our sun4: */
                    445:   sun4 = (struct tme_sun4 *) conn->tme_connection_element->tme_element_private;
                    446: 
                    447:   /* dispatch on the connection type: */
                    448:   conn_other = conn->tme_connection_other;
                    449:   conn_sparc = (struct tme_sparc_bus_connection *) conn_other;
                    450:   conn_sun4 = (struct tme_sun4_bus_connection *) conn;
                    451:   conn_bus = (struct tme_bus_connection *) conn_other;
                    452:   switch (conn->tme_connection_type) {
                    453:       
                    454:   case TME_CONNECTION_BUS_SPARC:
                    455:     sun4->tme_sun4_sparc = conn_sparc;
                    456:     break;
                    457:       
                    458:   case TME_CONNECTION_BUS_GENERIC:
                    459: 
                    460:     /* remember the connection to this bus: */
                    461:     if (state == TME_CONNECTION_FULL) {
                    462:       assert (sun4->tme_sun4_buses[conn_sun4->tme_sun4_bus_connection_which] == NULL);
                    463:       sun4->tme_sun4_buses[conn_sun4->tme_sun4_bus_connection_which] = conn_bus;
                    464:     }
                    465:     break;
                    466: 
                    467:   default: 
                    468:     assert(FALSE);
                    469:     break;
                    470:   }
                    471:   return (TME_OK);
                    472: }
                    473: 
                    474: /* this breaks a connection: */
                    475: static int 
                    476: _tme_sun4_connection_break(struct tme_connection *conn, unsigned int state)
                    477: {
                    478:   abort();
                    479: }
                    480: 
                    481: /* this makes new connection sides: */
                    482: static int
                    483: _tme_sun4_connections_new(struct tme_element *element, const char * const *args, struct tme_connection **_conns, char **_output)
                    484: {
                    485:   struct tme_sparc_bus_connection *conn_sparc;
                    486:   struct tme_sun4_bus_connection *conn_sun4;
                    487:   struct tme_bus_connection *conn_bus;
                    488:   struct tme_connection *conn;
                    489:   struct tme_sun4 *sun4;
                    490:   char *free_buses;
                    491:   int which_conn;
                    492: 
                    493:   /* recover our sun4: */
                    494:   sun4 = (struct tme_sun4 *) element->tme_element_private;
                    495: 
                    496:   /* if we have no arguments, and we don't have a CPU yet, we can take
                    497:      a SPARC bus connection: */
                    498:   if (args[1] == NULL
                    499:       && sun4->tme_sun4_sparc == NULL) {
                    500: 
                    501:     /* create our side of a SPARC bus connection: */
                    502:     conn_sparc = tme_new0(struct tme_sparc_bus_connection, 1);
                    503:     conn_bus = &conn_sparc->tme_sparc_bus_connection;
                    504:     conn = &conn_bus->tme_bus_connection;
                    505:     conn->tme_connection_next = *_conns;
                    506: 
                    507:     /* fill in the generic connection: */
                    508:     conn->tme_connection_type = TME_CONNECTION_BUS_SPARC;
                    509:     conn->tme_connection_score = _tme_sun4_connection_score;
                    510:     conn->tme_connection_make = _tme_sun4_connection_make;
                    511:     conn->tme_connection_break = _tme_sun4_connection_break;
                    512: 
                    513:     /* fill in the generic bus connection: */
                    514:     conn_bus->tme_bus_signal = _tme_sun4_bus_signal;
                    515:     conn_bus->tme_bus_intack = _tme_sun4_bus_intack;
1.1.1.2 ! root      516:     conn_bus->tme_bus_tlb_set_add
1.1       root      517:       = (TME_SUN4_IS_SUN44C(sun4)
1.1.1.2 ! root      518:         ? _tme_sun44c_mmu_tlb_set_add
1.1       root      519:         : NULL);
                    520: 
                    521:     /* full in the SPARC bus connection: */
                    522:     conn_sparc->tme_sparc_bus_tlb_fill
                    523:       = (TME_SUN4_IS_SUN44C(sun4)
                    524:         ? _tme_sun44c_tlb_fill_sparc
                    525:         : NULL);
                    526: 
                    527:     /* add in this connection side possibility: */
                    528:     *_conns = conn;
                    529:   }
                    530: 
                    531:   /* create our side of a generic bus connection: */
                    532:   conn_sun4 = tme_new0(struct tme_sun4_bus_connection, 1);
                    533:   conn_bus = &conn_sun4->tme_sun4_bus_connection;
                    534:   conn = &conn_bus->tme_bus_connection;
                    535:   conn->tme_connection_next = *_conns;
                    536: 
                    537:   /* fill in the generic connection: */
                    538:   conn->tme_connection_type = TME_CONNECTION_BUS_GENERIC;
                    539:   conn->tme_connection_score = _tme_sun4_connection_score;
                    540:   conn->tme_connection_make = _tme_sun4_connection_make;
                    541:   conn->tme_connection_break = _tme_sun4_connection_break;
                    542:     
                    543:   /* fill in the generic bus connection: */
                    544:   conn_bus->tme_bus_signal = _tme_sun4_bus_signal;
                    545:   conn_bus->tme_bus_intack = NULL;
                    546:   if (TME_SUN4_IS_SUN44C(sun4)) {
                    547:     conn_bus->tme_bus_tlb_fill = _tme_sun44c_tlb_fill_bus;
                    548:   }
                    549:   else {
                    550:     abort();
                    551:   }
                    552: 
                    553:   /* if we have no argument: */
                    554:   if (args[1] == NULL) {
                    555: 
                    556:     /* return no more connections: */
                    557:     tme_free(conn_sun4);
                    558:     return (TME_OK);
                    559:   }
                    560: 
                    561:   /* otherwise, we have at least one argument: */
                    562:   else {
                    563: 
                    564:     /* we must have no other arguments: */
                    565:     if (args[2] != NULL) {
                    566:       tme_output_append_error(_output,
                    567:                              "%s %s",
                    568:                              args[2],
                    569:                              _("unexpected"));
                    570:       tme_free(conn_sun4);
                    571:       return (EINVAL);
                    572:     }
                    573: 
                    574:     /* start the list of buses that we don't have yet: */
                    575:     free_buses = NULL;
                    576: 
                    577:     /* poison the which connection: */
                    578:     which_conn = -1;
                    579: 
                    580:     /* check each bus: */
                    581: 
                    582:     /* obio: */
                    583:     if (sun4->tme_sun4_32_obio == NULL) {
                    584:       tme_output_append(&free_buses, 
                    585:                        (TME_SUN4_IS_SUN4C(sun4)
                    586:                         ? " sbus"
                    587:                         : " obio"));
                    588:     }
                    589:     if (TME_ARG_IS(args[1],
                    590:                   (TME_SUN4_IS_SUN4C(sun4)
                    591:                    ? "sbus"
                    592:                    : "obio"))) {
                    593:       which_conn = TME_SUN4_32_CONN_BUS_OBIO;
                    594:     }
                    595: 
                    596:     /* obmem: */
                    597:     if (!TME_SUN4_IS_SUN4C(sun4)) {
                    598:       if (sun4->tme_sun4_32_obmem == NULL) {
                    599:        tme_output_append(&free_buses, " obmem");
                    600:       }
                    601:       if (TME_ARG_IS(args[1], "obmem")) {
                    602:        which_conn = TME_SUN4_32_CONN_BUS_OBMEM;
                    603:       }
                    604:     }
                    605: 
                    606:     /* VMEbus: */
                    607:     if (TME_SUN4_IS_SUN4(sun4)) {
                    608:       if (sun4->tme_sun4_vmebus == NULL) {
                    609:        tme_output_append(&free_buses, " vme");
                    610:       }
                    611:       if (TME_ARG_IS(args[1], "vme")) {
                    612:        which_conn = TME_SUN4_CONN_BUS_VME;
                    613:        conn_bus->tme_bus_subregions.tme_bus_subregion_address_last
                    614:          = TME_SUN4_DVMA_SIZE_VME;
                    615:       }
                    616:     }
                    617: 
                    618:     /* random connections: */
                    619:     
                    620:     if (TME_ARG_IS(args[1], "timer")) {
                    621:       which_conn = TME_SUN4_32_CONN_REG_TIMER;
                    622:       conn_bus->tme_bus_subregions.tme_bus_subregion_address_last
                    623:        = TME_SUN44C_TIMER_SIZ_REG * 2;
                    624:     }
                    625:     else if (TME_ARG_IS(args[1], "memerr")) {
                    626:       which_conn = TME_SUN4_32_CONN_REG_MEMERR;
                    627:       conn_bus->tme_bus_subregions.tme_bus_subregion_address_last
                    628:        = (TME_SUN4_IS_MODEL(sun4, TME_SUN_IDPROM_TYPE_CODE_CALVIN)
                    629:           ? (TME_SUN44C_MEMERR_SIZ_REG * 2)
                    630:           : TME_SUN44C_MEMERR_SIZ_REG);
                    631:     }
                    632:     else if (TME_ARG_IS(args[1], "intreg")) {
                    633:       which_conn = TME_SUN4_32_CONN_REG_INTREG;
                    634:       conn_bus->tme_bus_subregions.tme_bus_subregion_address_last
                    635:        = sizeof(sun4->tme_sun44c_ints);
                    636:     }
                    637:     else if (TME_SUN4_IS_SUN4C4M(sun4)
                    638:             && TME_ARG_IS(args[1], "auxreg")) {
                    639:       which_conn = TME_SUN4C4M_CONN_REG_AUXREG;
                    640:       conn_bus->tme_bus_subregions.tme_bus_subregion_address_last
                    641:        = sizeof(sun4->tme_sun4c4m_aux);
                    642:     }
                    643: 
                    644:     /* if the which connection is still poison, or if this is trying
                    645:        to connect a bus that we already have, complain: */
                    646:     if (which_conn < 0
                    647:        || (which_conn < TME_SUN4_32_CONN_BUS_COUNT
                    648:            && sun4->tme_sun4_buses[which_conn] != NULL)) {
                    649:       if (which_conn < 0) {
                    650:        tme_output_append_error(_output,
                    651:                                "%s %s ",
                    652:                                _("unknown bus or register:"),
                    653:                                args[1]);
                    654:       }
                    655:       if (free_buses != NULL) {
                    656:        tme_output_append_error(_output, 
                    657:                                "%s %s",
                    658:                                _("remaining buses:"),
                    659:                                free_buses);
                    660:        tme_free(free_buses);
                    661:       }
                    662:       else {
                    663:        tme_output_append_error(_output, _("all buses present"));
                    664:       }
                    665:       tme_free(conn_sun4);
                    666:       return (EINVAL);
                    667:     }
                    668: 
                    669:     /* free the remaining bus list: */
                    670:     if (free_buses != NULL) {
                    671:       tme_free(free_buses);
                    672:     }
                    673: 
                    674:     /* fill in the sun4 connection: */
                    675:     conn_sun4->tme_sun4_bus_connection_which = which_conn;
                    676:     
                    677:     /* fill in the generic bus connection for a bus: */
                    678:     if (which_conn < TME_SUN4_32_CONN_BUS_COUNT) {
1.1.1.2 ! root      679:       conn_bus->tme_bus_tlb_set_add = _tme_sun44c_mmu_tlb_set_add;
1.1       root      680:     }
                    681:   }
                    682: 
                    683:   /* add in this connection side possibility: */
                    684:   *_conns = conn;
                    685: 
                    686:   /* done: */
                    687:   return (TME_OK);
                    688: }
                    689: 
                    690: /* this creates a new sun4 element: */
                    691: TME_ELEMENT_NEW_DECL(tme_machine_sun4) {
                    692:   int usage;
                    693:   struct tme_sun4 *sun4;
                    694:   const char *idprom_filename;
                    695:   FILE *idprom_fp;
                    696:   tme_uint8_t idprom[TME_SUN_IDPROM_SIZE];
                    697:   int arg_i;
                    698: 
                    699:   arg_i = 1;
                    700:   usage = FALSE;
                    701: 
                    702:   /* if we've been given an IDPROM filename: */
                    703:   idprom_filename = NULL;
                    704:   if (TME_ARG_IS(args[arg_i], "idprom")) {
                    705:     arg_i++;
                    706:     idprom_filename = args[arg_i];
                    707:     if (idprom_filename == NULL) {
                    708:       usage = TRUE;
                    709:     }
                    710:     else {
                    711:       arg_i++;
                    712:     }
                    713:   }
                    714: 
                    715:   /* otherwise, if we've been given a board name: */
                    716:   else if (TME_ARG_IS(args[arg_i], "name")) {
                    717:     arg_i++;
                    718:     if (TME_ARG_IS(args[arg_i], "Calvin")) {
                    719:       idprom[TME_SUN_IDPROM_OFF_MACHTYPE] = TME_SUN_IDPROM_TYPE_CODE_CALVIN;
                    720:       arg_i++;
                    721:     }
                    722:     else if (args[arg_i] != NULL) {
                    723:       tme_output_append_error(_output,
                    724:                              "%s %s, ",
                    725:                              _("unknown name"),
                    726:                              args[arg_i]);
                    727:       usage = TRUE;
                    728:     }
                    729:     else {
                    730:       tme_output_append_error(_output,
                    731:                              "%s, ",
                    732:                              _("missing name"));
                    733:       usage = TRUE;
                    734:     }
                    735:   }
                    736: 
                    737:   /* we must have no more arguments: */
                    738:   if (args[arg_i] != NULL) {
                    739:     tme_output_append_error(_output,
                    740:                            "%s %s, ",
                    741:                            args[arg_i],
                    742:                            _("unexpected"));
                    743:     usage = TRUE;
                    744:   }
                    745: 
                    746:   /* if our usage was bad: */
                    747:   if (usage) {
                    748:     tme_output_append_error(_output,
                    749:                            "%s %s { idprom IDPROM%s | name { Calvin } } ",
                    750:                            _("usage:"),
                    751:                            args[0],
                    752:                            _("-FILENAME"));
                    753:     return (EINVAL);
                    754:   }
                    755: 
                    756:   /* if we've been given an IDPROM filename, try to read it in: */
                    757:   if (idprom_filename != NULL) {
                    758:     idprom_fp = fopen(idprom_filename, "r");
                    759:     if (idprom_fp == NULL) {
                    760:       tme_output_append_error(_output, idprom_filename);
                    761:       return (errno);
                    762:     }
                    763:     if (fread(idprom, sizeof(tme_uint8_t), sizeof(idprom), idprom_fp) != sizeof(idprom)) {
                    764:       tme_output_append_error(_output, idprom_filename);
                    765:       fclose(idprom_fp);
                    766:       return (ENOEXEC);
                    767:     }
                    768:     fclose(idprom_fp);
                    769:   }
                    770: 
                    771:   /* allocate and initialize the new sun4: */
                    772:   sun4 = tme_new0(struct tme_sun4, 1);
                    773:   sun4->tme_sun4_element = element;
                    774:   tme_mutex_init(&sun4->tme_sun4_mutex);
                    775: 
                    776:   /* set the IDPROM: */
                    777:   memcpy(sun4->tme_sun4_idprom_contents, idprom, sizeof(idprom));
                    778:   
                    779:   /* the MMU: */
                    780:   if (TME_SUN4_IS_SUN44C(sun4)) {
                    781:     _tme_sun44c_mmu_new(sun4);
                    782:     sun4->tme_sun4_tlb_fill = _tme_sun44c_tlb_fill_mmu;
                    783:   }
                    784:   else {
                    785:     abort();
                    786:   }
                    787: 
                    788:   /* the cache: */
                    789:   if (TME_SUN4_IS_SUN44C(sun4)) {
                    790:     _tme_sun44c_cache_new(sun4);
                    791:   }
                    792:   else {
                    793:     abort();
                    794:   }
                    795: 
                    796:   /* the control ASIs: */
                    797:   sun4->tme_sun4_asis[TME_SUN4_32_ASI_CONTROL].tme_sun4_asi_sun4 = sun4;
                    798:   if (TME_SUN4_IS_SUN44C(sun4)) {
                    799:     sun4->tme_sun4_asis[TME_SUN44C_ASI_SEGMAP].tme_sun4_asi_sun4 = sun4;
                    800:     sun4->tme_sun4_asis[TME_SUN44C_ASI_PGMAP].tme_sun4_asi_sun4 = sun4;
                    801:     sun4->tme_sun4_asis[TME_SUN4C_ASI_HW_FLUSH_SEG /* TME_SUN4_ASI_COPY */].tme_sun4_asi_sun4 = sun4;
                    802:     sun4->tme_sun4_asis[TME_SUN4C_ASI_HW_FLUSH_PG /* TME_SUN4_ASI_REGMAP */].tme_sun4_asi_sun4 = sun4;
                    803:     sun4->tme_sun4_asis[TME_SUN4C_ASI_HW_FLUSH_CONTEXT /* TME_SUN4_ASI_FLUSH_REG */].tme_sun4_asi_sun4 = sun4;
                    804:     sun4->tme_sun4_asis[TME_SUN44C_ASI_FLUSH_SEG].tme_sun4_asi_sun4 = sun4;
                    805:     sun4->tme_sun4_asis[TME_SUN44C_ASI_FLUSH_PG].tme_sun4_asi_sun4 = sun4;
                    806:     sun4->tme_sun4_asis[TME_SUN44C_ASI_FLUSH_CONTEXT].tme_sun4_asi_sun4 = sun4;
                    807:     sun4->tme_sun4_asis[TME_SUN4C_ASI_HW_FLUSH_ALL /* TME_SUN4_ASI_FLUSH_USER */].tme_sun4_asi_sun4 = sun4;
                    808:   }
                    809:   else {
                    810:     abort();
                    811:   }
                    812: 
                    813:   /* the timers: */
                    814:   _tme_sun4_timer_new(sun4);
                    815: 
                    816:   /* fill the element: */
                    817:   element->tme_element_private = sun4;
                    818:   element->tme_element_connections_new = _tme_sun4_connections_new;
                    819:   element->tme_element_command = _tme_sun4_command;
                    820: 
                    821:   return (TME_OK);
                    822: }
                    823: 
                    824: /* this creates a new Sun-4 isil7170: */
                    825: TME_ELEMENT_SUB_NEW_DECL(tme_machine_sun4,oclock) {
                    826:   struct tme_isil7170_socket socket;
                    827:   const char *sub_args[4];
                    828:   int arg_i;
                    829: 
                    830:   /* create the isil7170 socket: */
                    831:   memset (&socket, 0, sizeof(socket));
                    832:   socket.tme_isil7170_socket_version = TME_ISIL7170_SOCKET_0;
                    833:   socket.tme_isil7170_socket_addr_shift = 0;
                    834:   socket.tme_isil7170_socket_port_least_lane = 3; /* D31-D24 */
                    835:   socket.tme_isil7170_socket_clock_basic = TME_ISIL7170_FREQ_32K;
                    836:   socket.tme_isil7170_socket_int_signal = TME_BUS_SIGNAL_INT_UNSPEC;
                    837: 
                    838:   /* create the isil7170.  we allow at most two arguments to pass
                    839:      through, which is an awful hack: */
                    840:   sub_args[0] = "tme/ic/isil7170";
                    841:   for (arg_i = 1;; arg_i++) {
                    842:     if (arg_i == TME_ARRAY_ELS(sub_args)) {
                    843:       abort();
                    844:     }
                    845:     sub_args[arg_i] = args[arg_i];
                    846:     if (args[arg_i] == NULL) {
                    847:       break;
                    848:     }
                    849:   }
                    850:   return (tme_element_new(element, (const char * const *) sub_args, &socket, _output));
                    851: }
                    852: 
                    853: /* this creates a new Sun-4 mk48txx: */
                    854: TME_ELEMENT_SUB_NEW_DECL(tme_machine_sun4,clock) {
                    855:   struct tme_mk48txx_socket socket;
                    856: 
                    857:   /* create the mk48txx socket: */
                    858:   memset (&socket, 0, sizeof(socket));
                    859:   socket.tme_mk48txx_socket_version = TME_MK48TXX_SOCKET_0;
                    860:   socket.tme_mk48txx_socket_addr_shift = 0;
                    861:   socket.tme_mk48txx_socket_port_least_lane = 3; /* D31-D24 */
                    862:   socket.tme_mk48txx_socket_year_zero = 1968;
                    863: 
                    864:   if (!TME_ARG_IS(args[1], "type")
                    865:       || args[2] == NULL) {
                    866:     tme_output_append_error(_output,
                    867:                            "%s %s type CLOCK-%s",
                    868:                            _("usage:"),
                    869:                            args[0],
                    870:                            _("TYPE"));
                    871:     return (EINVAL);
                    872:   }
                    873: 
                    874:   return (tme_element_new(element, args + 2, &socket, _output));
                    875: }
                    876: 
                    877: /* this creates a new Sun-4 z8530: */
                    878: TME_ELEMENT_SUB_NEW_DECL(tme_machine_sun4,zs) {
                    879:   struct tme_z8530_socket socket = TME_SUN_Z8530_SOCKET_INIT;
                    880:   char *sub_args[2];
                    881: 
                    882:   /* create the z8530: */
                    883:   sub_args[0] = "tme/ic/z8530";
                    884:   sub_args[1] = NULL;
                    885:   return (tme_element_new(element, (const char * const *) sub_args, &socket, _output));
                    886: }

unix.superglobalmegacorp.com

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