Annotation of tme/generic/bus-el.c, revision 1.1

1.1     ! root        1: /* $Id: bus-el.c,v 1.7 2003/05/16 21:48:08 fredette Exp $ */
        !             2: 
        !             3: /* generic/gen-bus-el.c - a real generic bus element: */
        !             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: bus-el.c,v 1.7 2003/05/16 21:48:08 fredette Exp $");
        !            38: 
        !            39: /* includes: */
        !            40: #include <tme/generic/bus.h>
        !            41: #include <stdlib.h>
        !            42: #include <string.h>
        !            43: 
        !            44: /* macros: */
        !            45: 
        !            46: /* structures: */
        !            47: 
        !            48: /* this handles a bus connection signal edge: */
        !            49: static int
        !            50: _tme_bus_signal(struct tme_bus_connection *conn_bus_edger, unsigned int signal)
        !            51: {
        !            52:   struct tme_bus *bus;
        !            53:   struct tme_bus_connection_int *conn_bus_int_edger;
        !            54:   struct tme_bus_connection_int *conn_bus_int;
        !            55:   unsigned int level_edge;
        !            56:   struct tme_bus_connection *conn_bus;
        !            57:   struct tme_bus_connection *conn_bus_other;
        !            58:   int signal_asserted, need_propagate;
        !            59:   unsigned int signal_index;
        !            60:   tme_uint8_t signal_mask;
        !            61:   int rc;
        !            62:   int deadlocked;
        !            63: 
        !            64:   /* recover our bus: */
        !            65:   bus = conn_bus_edger->tme_bus_connection.tme_connection_element->tme_element_private;
        !            66:   conn_bus_int_edger = (struct tme_bus_connection_int *) conn_bus_edger;
        !            67: 
        !            68:   /* take out the level and edge: */
        !            69:   level_edge = signal & (TME_BUS_SIGNAL_LEVEL_MASK
        !            70:                         | TME_BUS_SIGNAL_EDGE);
        !            71:   signal &= ~(TME_BUS_SIGNAL_LEVEL_MASK
        !            72:              | TME_BUS_SIGNAL_EDGE);
        !            73: 
        !            74:   /* lock the bus for writing: */
        !            75:   rc = tme_rwlock_timedwrlock(&bus->tme_bus_rwlock, TME_THREAD_TIMEDLOCK);
        !            76:   if (TME_THREADS_ERRNO(rc) != TME_OK) {
        !            77:     return (TME_THREADS_ERRNO(rc));
        !            78:   }
        !            79:   
        !            80:   /* if this device doesn't know its interrupt signal, fix it: */
        !            81:   if (signal == TME_BUS_SIGNAL_INT_UNSPEC) {
        !            82:     signal = conn_bus_int_edger->tme_bus_connection_int_signal_int;
        !            83:     if (signal == TME_BUS_SIGNAL_INT_UNSPEC) {
        !            84:       /* this bus connection is misconfigured: */
        !            85:       if (!conn_bus_int_edger->tme_bus_connection_int_logged_int) {
        !            86:        conn_bus_int_edger->tme_bus_connection_int_logged_int = TRUE;
        !            87:        /* XXX diagnostic */
        !            88:        abort();
        !            89:       }
        !            90:       tme_rwlock_unlock(&bus->tme_bus_rwlock);
        !            91:       return (TME_OK);
        !            92:     }
        !            93:   }
        !            94: 
        !            95:   /* assume we don't need to propagate this signal across the bus: */
        !            96:   need_propagate = FALSE;
        !            97: 
        !            98:   /* if this is a random bus-specific signal, just propagate it: */
        !            99:   if (TME_BUS_SIGNAL_IS_X(signal)) {
        !           100:     need_propagate = TRUE;
        !           101:   }
        !           102: 
        !           103:   /* otherwise, this is a generic bus signal: */
        !           104:   else {
        !           105:     
        !           106:     /* decide whether the device is asserting or negating this signal: */
        !           107:     /* XXX we currently assume that for all bus signals handled by this
        !           108:        function, low implies assertion, and signals are always ORed
        !           109:        together.  this could be configurable, possibly even per-signal: */
        !           110:     signal_asserted = TRUE;
        !           111:     switch (level_edge & TME_BUS_SIGNAL_LEVEL_MASK) {
        !           112:     case TME_BUS_SIGNAL_LEVEL_LOW: 
        !           113:     case TME_BUS_SIGNAL_LEVEL_ASSERTED:
        !           114:       break;
        !           115:     case TME_BUS_SIGNAL_LEVEL_HIGH: 
        !           116:     case TME_BUS_SIGNAL_LEVEL_NEGATED:
        !           117:       signal_asserted = FALSE;
        !           118:       break;
        !           119:     }
        !           120:     level_edge = ((level_edge & TME_BUS_SIGNAL_EDGE)
        !           121:                  | (signal_asserted
        !           122:                     ? TME_BUS_SIGNAL_LEVEL_ASSERTED
        !           123:                     : TME_BUS_SIGNAL_LEVEL_NEGATED));
        !           124: 
        !           125:     /* get the index and mask of this signal in signal byte arrays: */
        !           126:     signal_index = TME_BUS_SIGNAL_BIT_INDEX(signal);
        !           127:     signal_mask = TME_BUS_SIGNAL_BIT_MASK(signal);
        !           128: 
        !           129:     /* if this signal is being asserted: */
        !           130:     if (signal_asserted) {
        !           131: 
        !           132:       /* if this device wasn't already asserting this signal: */
        !           133:       if (!(conn_bus_int_edger->tme_bus_connection_int_signals[signal_index]
        !           134:            & signal_mask)) {
        !           135: 
        !           136:        /* it is now asserting this signal: */
        !           137:        conn_bus_int_edger->tme_bus_connection_int_signals[signal_index]
        !           138:          |= signal_mask;
        !           139:        bus->tme_bus_signal_asserts[TME_BUS_SIGNAL_WHICH(signal)]++;
        !           140: 
        !           141:        /* if this is the only device asserting this signal,
        !           142:           propagate the change across the bus: */
        !           143:        if (bus->tme_bus_signal_asserts[TME_BUS_SIGNAL_WHICH(signal)] == 1) {
        !           144:          need_propagate = TRUE;
        !           145:        }
        !           146:       }
        !           147: 
        !           148:       /* otherwise, this device was already asserting this signal: */
        !           149:       else {
        !           150:        assert(bus->tme_bus_signal_asserts[TME_BUS_SIGNAL_WHICH(signal)] > 0);
        !           151:       }
        !           152:     }
        !           153: 
        !           154:     /* otherwise, this signal is being negated: */
        !           155:     else {
        !           156: 
        !           157:       /* if this device was asserting this signal: */
        !           158:       if (conn_bus_int_edger->tme_bus_connection_int_signals[signal_index]
        !           159:          & signal_mask) {
        !           160: 
        !           161:        /* it is no longer asserting this signal: */
        !           162:        conn_bus_int_edger->tme_bus_connection_int_signals[signal_index]
        !           163:          &= ~signal_mask;
        !           164:        assert(bus->tme_bus_signal_asserts[TME_BUS_SIGNAL_WHICH(signal)] > 0);
        !           165:        bus->tme_bus_signal_asserts[TME_BUS_SIGNAL_WHICH(signal)]--;
        !           166:       }
        !           167: 
        !           168:       /* we always propagate across the bus a signal that some device
        !           169:         has negated, because often code will lazily only send
        !           170:         negating edges, or other devices might still be asserting it,
        !           171:         we assume these signals are always ORed together, and it
        !           172:         kicks (even though this signal isn't edging) emulated
        !           173:         circuitry that is meant to do things like interrupt
        !           174:         arbitration, etc.: */
        !           175:       if (bus->tme_bus_signal_asserts[TME_BUS_SIGNAL_WHICH(signal)] > 0) {
        !           176:        level_edge = TME_BUS_SIGNAL_LEVEL_ASSERTED;
        !           177:       }
        !           178:       need_propagate = TRUE;
        !           179:     }
        !           180:   }
        !           181: 
        !           182:   /* if we're propagating this signal across the bus: */
        !           183:   rc = TME_OK;
        !           184:   if (need_propagate) {
        !           185: 
        !           186:     /* put the level and edge back in: */
        !           187:     signal |= level_edge;
        !           188: 
        !           189:     /* assume that we won't deadlock: */
        !           190:     deadlocked = FALSE;
        !           191: 
        !           192:     /* propagate the signal to each connection to the bus: */
        !           193:     for (conn_bus_int = bus->tme_bus_connections;
        !           194:         conn_bus_int != NULL;
        !           195:         conn_bus_int =
        !           196:           (struct tme_bus_connection_int *) 
        !           197:           conn_bus_int->tme_bus_connection_int
        !           198:           .tme_bus_connection
        !           199:           .tme_connection_next) {
        !           200:       conn_bus = &conn_bus_int->tme_bus_connection_int;
        !           201:       conn_bus_other = 
        !           202:        (struct tme_bus_connection *) 
        !           203:        conn_bus->tme_bus_connection.tme_connection_other;
        !           204:       
        !           205:       /* skip this device if it edged the line to begin with: */
        !           206:       if (conn_bus == conn_bus_edger) {
        !           207:        continue;
        !           208:       }
        !           209: 
        !           210:       /* skip this device if it doesn't care about bus signals: */
        !           211:       if (conn_bus_other->tme_bus_signal == NULL) {
        !           212:        continue;
        !           213:       }
        !           214: 
        !           215:       /* give the edge to this connection: */
        !           216:       rc =  (*conn_bus_other->tme_bus_signal)(conn_bus_other, signal);
        !           217: 
        !           218:       /* if we deadlocked, remember to tell the caller: */
        !           219:       if (rc == TME_EDEADLK) {
        !           220:        deadlocked = TRUE;
        !           221:       }
        !           222:     }
        !           223:     rc = (deadlocked ? TME_EDEADLK : TME_OK);
        !           224:   }
        !           225: 
        !           226:   /* unlock the bus: */
        !           227:   tme_rwlock_unlock(&bus->tme_bus_rwlock);
        !           228: 
        !           229:   /* done: */
        !           230:   return (rc);
        !           231: }
        !           232:                              
        !           233: /* this handles a bus interrupt acknowledge: */
        !           234: static int
        !           235: _tme_bus_intack(struct tme_bus_connection *conn_bus_acker, unsigned int signal, int *vector)
        !           236: {
        !           237:   struct tme_bus *bus;
        !           238:   struct tme_bus_connection_int *conn_bus_int;
        !           239:   struct tme_bus_connection *conn_bus;
        !           240:   struct tme_bus_connection *conn_bus_other;
        !           241:   unsigned int signal_index;
        !           242:   tme_uint8_t signal_mask;
        !           243:   int rc;
        !           244: 
        !           245:   /* recover our bus: */
        !           246:   bus = conn_bus_acker->tme_bus_connection.tme_connection_element->tme_element_private;
        !           247: 
        !           248:   /* get rid of any level and edge: */
        !           249:   signal &= ~(TME_BUS_SIGNAL_LEVEL_MASK
        !           250:              | TME_BUS_SIGNAL_EDGE);
        !           251: 
        !           252:   /* this must be an interrupt signal: */
        !           253:   assert(TME_BUS_SIGNAL_IS_INT(signal));
        !           254: 
        !           255:   /* lock the bus for writing: */
        !           256:   rc = tme_rwlock_timedwrlock(&bus->tme_bus_rwlock, TME_THREAD_TIMEDLOCK);
        !           257:   if (TME_THREADS_ERRNO(rc) != TME_OK) {
        !           258:     return (TME_THREADS_ERRNO(rc));
        !           259:   }
        !           260:   
        !           261:   /* get the index and mask of this signal in signal byte arrays: */
        !           262:   signal_index = TME_BUS_SIGNAL_BIT_INDEX(signal);
        !           263:   signal_mask = TME_BUS_SIGNAL_BIT_MASK(signal);
        !           264: 
        !           265:   /* find the first connection to the bus that is asserting this
        !           266:      interrupt signal.  if no connection is asserting the signal,
        !           267:      return ENOENT: */
        !           268:   rc = ENOENT;
        !           269:   for (conn_bus_int = bus->tme_bus_connections;
        !           270:        conn_bus_int != NULL;
        !           271:        conn_bus_int =
        !           272:         (struct tme_bus_connection_int *) 
        !           273:         conn_bus_int->tme_bus_connection_int
        !           274:         .tme_bus_connection
        !           275:         .tme_connection_next) {
        !           276:     conn_bus = &conn_bus_int->tme_bus_connection_int;
        !           277:     conn_bus_other = 
        !           278:       (struct tme_bus_connection *) 
        !           279:       conn_bus->tme_bus_connection.tme_connection_other;
        !           280:     
        !           281:     /* if this device is asserting this interrupt signal: */
        !           282:     if (conn_bus_int->tme_bus_connection_int_signals[signal_index]
        !           283:        & signal_mask) {
        !           284: 
        !           285:       /* if this device doesn't acknowledge interrupts, 
        !           286:         return an undefined vector: */
        !           287:       if (conn_bus_other->tme_bus_intack == NULL) {
        !           288:        *vector = TME_BUS_INTERRUPT_VECTOR_UNDEF;
        !           289:        rc = TME_OK;
        !           290:       }
        !           291: 
        !           292:       /* otherwise, run the interrupt acknowledge with this connection: */
        !           293:       else {
        !           294:        rc = (*conn_bus_other->tme_bus_intack)(conn_bus_other, signal, vector);
        !           295:       }
        !           296: 
        !           297:       /* stop: */
        !           298:       break;
        !           299:     }
        !           300:   }
        !           301: 
        !           302:   /* unlock the bus: */
        !           303:   tme_rwlock_unlock(&bus->tme_bus_rwlock);
        !           304: 
        !           305:   /* done: */
        !           306:   return (rc);
        !           307: }
        !           308: 
        !           309: static int
        !           310: _tme_bus_fault(void *junk0, struct tme_bus_cycle *junk1)
        !           311: {
        !           312:   return (ENOENT);
        !           313: }
        !           314: 
        !           315: /* this fills a TLB entry: */
        !           316: static int
        !           317: _tme_bus_tlb_fill(struct tme_bus_connection *conn_bus_asker, 
        !           318:                  struct tme_bus_tlb *tlb,
        !           319:                  tme_bus_addr_t address, 
        !           320:                  unsigned int cycles)
        !           321: {
        !           322:   struct tme_bus *bus;
        !           323:   struct tme_bus_connection_int *conn_int;
        !           324:   int rc;
        !           325: 
        !           326:   /* recover our bus and our connection to the asker: */
        !           327:   bus = conn_bus_asker->tme_bus_connection.tme_connection_element->tme_element_private;
        !           328:   conn_int = (struct tme_bus_connection_int *) conn_bus_asker;
        !           329: 
        !           330:   /* put our fault handler in the TLB entry: */
        !           331:   tlb->tme_bus_tlb_cycle_private = NULL;
        !           332:   tlb->tme_bus_tlb_cycle = _tme_bus_fault;
        !           333: 
        !           334:   /* lock the bus for reading: */
        !           335:   rc = tme_rwlock_timedrdlock(&bus->tme_bus_rwlock, TME_THREAD_TIMEDLOCK);
        !           336:   if (TME_THREADS_ERRNO(rc) != TME_OK) {
        !           337:     return (TME_THREADS_ERRNO(rc));
        !           338:   }
        !           339: 
        !           340:   /* call the generic bus support function: */
        !           341:   rc = tme_bus_tlb_fill(bus,
        !           342:                        conn_int,
        !           343:                        tlb, address, cycles);
        !           344: 
        !           345:   /* unlock the bus: */
        !           346:   tme_rwlock_unlock(&bus->tme_bus_rwlock);
        !           347: 
        !           348:   /* done: */
        !           349:   return (rc);
        !           350: }
        !           351: 
        !           352: /* this allocates a new TLB set: */
        !           353: static int
        !           354: _tme_bus_tlb_set_allocate(struct tme_bus_connection *conn_bus_asker,
        !           355:                          unsigned int count, unsigned int sizeof_one, 
        !           356:                          TME_ATOMIC_POINTER_TYPE(struct tme_bus_tlb **) _tlbs)
        !           357: {
        !           358:   struct tme_bus *bus;
        !           359:   struct tme_bus_connection_int *conn_int;
        !           360:   int rc;
        !           361: 
        !           362:   /* recover our bus and our connection to the asker: */
        !           363:   bus = conn_bus_asker->tme_bus_connection.tme_connection_element->tme_element_private;
        !           364:   conn_int = (struct tme_bus_connection_int *) conn_bus_asker;
        !           365: 
        !           366:   /* lock the bus for reading: */
        !           367:   rc = tme_rwlock_timedrdlock(&bus->tme_bus_rwlock, TME_THREAD_TIMEDLOCK);
        !           368:   if (TME_THREADS_ERRNO(rc) != TME_OK) {
        !           369:     return (TME_THREADS_ERRNO(rc));
        !           370:   }
        !           371: 
        !           372:   /* call the generic bus support function: */
        !           373:   rc = tme_bus_tlb_set_allocate(bus,
        !           374:                                conn_int,
        !           375:                                count, sizeof_one, 
        !           376:                                _tlbs);
        !           377: 
        !           378:   /* unlock the bus: */
        !           379:   tme_rwlock_unlock(&bus->tme_bus_rwlock);
        !           380: 
        !           381:   /* done: */
        !           382:   return (rc);
        !           383: }
        !           384: 
        !           385: /* this scores a new connection: */
        !           386: static int
        !           387: _tme_bus_connection_score(struct tme_connection *conn, unsigned int *_score)
        !           388: {
        !           389:   struct tme_bus *bus;
        !           390:   struct tme_bus_connection_int *conn_int;
        !           391:   int rc, ok;
        !           392: 
        !           393:   /* both sides must be generic bus connections: */
        !           394:   assert(conn->tme_connection_type == TME_CONNECTION_BUS_GENERIC);
        !           395:   assert(conn->tme_connection_other->tme_connection_type == TME_CONNECTION_BUS_GENERIC);
        !           396: 
        !           397:   /* recover our bus and our internal connection side: */
        !           398:   bus = conn->tme_connection_element->tme_element_private;
        !           399:   conn_int = (struct tme_bus_connection_int *) conn;
        !           400: 
        !           401:   /* get the address mask from the other side: */
        !           402:   conn_int->tme_bus_connection_int_address_last = 
        !           403:     ((struct tme_bus_connection *) conn->tme_connection_other)->tme_bus_address_last;
        !           404: 
        !           405:   /* lock the bus for reading: */
        !           406:   rc = tme_rwlock_timedrdlock(&bus->tme_bus_rwlock, TME_THREAD_TIMEDLOCK);
        !           407:   if (TME_THREADS_ERRNO(rc) != TME_OK) {
        !           408:     return (TME_THREADS_ERRNO(rc));
        !           409:   }
        !           410:   
        !           411:   /* call the generic bus support function: */
        !           412:   ok = tme_bus_connection_ok(bus,
        !           413:                             conn_int);
        !           414: 
        !           415:   /* unlock the bus: */
        !           416:   tme_rwlock_unlock(&bus->tme_bus_rwlock);
        !           417: 
        !           418:   /* return the score: */
        !           419:   *_score = (ok ? 1 : 0);
        !           420:   return (TME_OK);
        !           421: }
        !           422: 
        !           423: /* this makes a new connection: */
        !           424: static int
        !           425: _tme_bus_connection_make(struct tme_connection *conn, unsigned int state)
        !           426: {
        !           427:   struct tme_bus *bus;
        !           428:   struct tme_bus_connection_int *conn_int;
        !           429:   int rc;
        !           430: 
        !           431:   /* both sides must be generic bus connections: */
        !           432:   assert(conn->tme_connection_type == TME_CONNECTION_BUS_GENERIC);
        !           433:   assert(conn->tme_connection_other->tme_connection_type == TME_CONNECTION_BUS_GENERIC);
        !           434: 
        !           435:   /* recover our bus and our internal connection side: */
        !           436:   bus = conn->tme_connection_element->tme_element_private;
        !           437:   conn_int = (struct tme_bus_connection_int *) conn;
        !           438:   
        !           439:   /* lock the bus for writing: */
        !           440:   rc = tme_rwlock_timedwrlock(&bus->tme_bus_rwlock, TME_THREAD_TIMEDLOCK);
        !           441:   if (TME_THREADS_ERRNO(rc) != TME_OK) {
        !           442:     return (TME_THREADS_ERRNO(rc));
        !           443:   }
        !           444: 
        !           445:   /* call the generic bus support function: */
        !           446:   rc = tme_bus_connection_make(bus,
        !           447:                               conn_int,
        !           448:                               state);
        !           449: 
        !           450:   /* unlock the bus: */
        !           451:   tme_rwlock_unlock(&bus->tme_bus_rwlock);
        !           452: 
        !           453:   return (rc);
        !           454: }
        !           455: 
        !           456: /* this breaks a connection: */
        !           457: static int 
        !           458: _tme_bus_connection_break(struct tme_connection *conn, unsigned int state)
        !           459: {
        !           460:   abort();
        !           461: }
        !           462: 
        !           463: /* this returns the new connections possible: */
        !           464: static int
        !           465: _tme_bus_connections_new(struct tme_element *element,
        !           466:                         const char * const *args,
        !           467:                         struct tme_connection **_conns,
        !           468:                         char **_output)
        !           469: {
        !           470:   const struct tme_bus *bus;
        !           471:   struct tme_bus_connection_int *conn_int;
        !           472:   struct tme_bus_connection *conn_bus;
        !           473:   struct tme_connection *conn;
        !           474:   int ipl;
        !           475:   int arg_i;
        !           476:   int usage;
        !           477: 
        !           478:   /* recover our bus.  we only read the address mask, so we don't lock
        !           479:      the rwlock: */
        !           480:   bus = element->tme_element_private;
        !           481: 
        !           482:   /* allocate the new connection side: */
        !           483:   conn_int = tme_new0(struct tme_bus_connection_int, 1);
        !           484:   conn_bus = &conn_int->tme_bus_connection_int;
        !           485:   conn = &conn_bus->tme_bus_connection;
        !           486: 
        !           487:   /* loop reading our arguments: */
        !           488:   usage = FALSE;
        !           489:   arg_i = 1;
        !           490:   for (;;) {
        !           491: 
        !           492:     /* the address of this connection: */
        !           493:     if (TME_ARG_IS(args[arg_i + 0], "addr")) {
        !           494:       conn_int->tme_bus_connection_int_addressable = TRUE;
        !           495:       conn_int->tme_bus_connection_int_address = tme_bus_addr_parse_any(args[arg_i + 1], &usage);
        !           496:       if (usage
        !           497:          || (conn_int->tme_bus_connection_int_address
        !           498:              > bus->tme_bus_address_mask)) {
        !           499:        usage = TRUE;
        !           500:        break;
        !           501:       }
        !           502:       arg_i += 2;
        !           503:     }
        !           504: 
        !           505:     /* the interrupt signal for this connection: */
        !           506:     else if (TME_ARG_IS(args[arg_i + 0], "ipl")
        !           507:             && args[arg_i + 1] != NULL
        !           508:             && (ipl = atoi(args[arg_i + 1])) > 0) {
        !           509:       conn_int->tme_bus_connection_int_signal_int = TME_BUS_SIGNAL_INT(ipl);
        !           510:       arg_i += 2;
        !           511:     }
        !           512: 
        !           513:     /* if we've run out of arguments: */
        !           514:     else if (args[arg_i + 0] == NULL) {
        !           515:       break;
        !           516:     }
        !           517: 
        !           518:     /* this is a bad argument: */
        !           519:     else {
        !           520:       tme_output_append_error(_output,
        !           521:                              "%s %s, ",
        !           522:                              args[arg_i],
        !           523:                              _("unexpected"));
        !           524:       usage = TRUE;
        !           525:       break;
        !           526:     }
        !           527:   }
        !           528: 
        !           529:   if (usage) {
        !           530:     tme_output_append_error(_output, 
        !           531:                            "%s %s [ addr %s ] [ ipl %s ]",
        !           532:                            _("usage:"),
        !           533:                            args[0],
        !           534:                            _("BUS-ADDRESS"),
        !           535:                            _("INTERRUPT-LEVEL"));
        !           536:     tme_free(conn_int);
        !           537:     return (EINVAL);
        !           538:   }
        !           539: 
        !           540:   /* fill in the bus connection: */
        !           541:   conn_bus->tme_bus_address_last = bus->tme_bus_address_mask;
        !           542:   conn_bus->tme_bus_signal = _tme_bus_signal;
        !           543:   conn_bus->tme_bus_intack = _tme_bus_intack;
        !           544:   conn_bus->tme_bus_tlb_set_allocate = _tme_bus_tlb_set_allocate;
        !           545:   conn_bus->tme_bus_tlb_fill = _tme_bus_tlb_fill;
        !           546: 
        !           547:   /* fill in the generic connection: */
        !           548:   conn->tme_connection_next = *_conns;
        !           549:   conn->tme_connection_type = TME_CONNECTION_BUS_GENERIC;
        !           550:   conn->tme_connection_score = _tme_bus_connection_score;
        !           551:   conn->tme_connection_make = _tme_bus_connection_make;
        !           552:   conn->tme_connection_break = _tme_bus_connection_break;
        !           553:   
        !           554:   /* return the new connection side: */
        !           555:   *_conns = conn;
        !           556:   return (TME_OK);
        !           557: }
        !           558: 
        !           559: /* this creates a new bus element: */
        !           560: TME_ELEMENT_SUB_NEW_DECL(tme_generic,bus) {
        !           561:   struct tme_bus *bus;
        !           562:   tme_bus_addr_t bus_size;
        !           563:   int failed;
        !           564: 
        !           565:   /* our arguments must include the bus size, and the
        !           566:      bus size must be a power of two: */
        !           567:   failed = TRUE;
        !           568:   bus_size = 0;
        !           569:   if (TME_ARG_IS(args[1], "size")) {
        !           570:     bus_size = tme_bus_addr_parse_any(args[2], &failed);
        !           571:     if (bus_size & (bus_size - 1)) {
        !           572:       failed = TRUE;
        !           573:     }
        !           574:   }
        !           575:   if (failed) {
        !           576:     tme_output_append_error(_output,
        !           577:                            "%s %s size %s",
        !           578:                            _("usage:"),
        !           579:                            args[0],
        !           580:                            _("SIZE"));
        !           581:     return (EINVAL);
        !           582:   }
        !           583: 
        !           584:   /* allocate and initialize the new bus: */
        !           585:   bus = tme_new0(struct tme_bus, 1);
        !           586:   tme_rwlock_init(&bus->tme_bus_rwlock);
        !           587:   bus->tme_bus_address_mask = bus_size - 1;
        !           588:   bus->tme_bus_addressables_count = 0;
        !           589:   bus->tme_bus_addressables_size = 1;
        !           590:   bus->tme_bus_addressables = tme_new(struct tme_bus_connection_int *,
        !           591:                                      bus->tme_bus_addressables_size);
        !           592: 
        !           593:   /* fill the element: */
        !           594:   element->tme_element_private = bus;
        !           595:   element->tme_element_connections_new = _tme_bus_connections_new;
        !           596: 
        !           597:   return (TME_OK);
        !           598: }

unix.superglobalmegacorp.com

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