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

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

unix.superglobalmegacorp.com

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