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

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

unix.superglobalmegacorp.com

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