Annotation of tme/generic/bus.c, revision 1.1.1.6

1.1.1.5   root        1: /* $Id: bus.c,v 1.14 2009/08/29 17:41:17 fredette Exp $ */
1.1       root        2: 
                      3: /* generic/gen-bus.c - generic bus support: */
                      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: bus.c,v 1.14 2009/08/29 17:41:17 fredette Exp $");
1.1       root       38: 
                     39: /* includes: */
                     40: #include <tme/generic/bus.h>
1.1.1.3   root       41: #include <tme/misc.h>
1.1       root       42: #include <stdlib.h>
                     43: #include <string.h>
                     44: 
1.1.1.6 ! root       45: extern int bradshow;
        !            46: 
1.1       root       47: /* this does a binary search of the addressable connections: */
                     48: int
                     49: tme_bus_address_search(struct tme_bus *bus, tme_bus_addr_t address)
                     50: {
                     51:   int left, right, pivot;
                     52:   struct tme_bus_connection_int *conn_int;
1.1.1.2   root       53:   const struct tme_bus_subregion *subregion;
1.1       root       54: 
                     55:   /* initialize for the search: */
                     56:   left = 0;
                     57:   right = bus->tme_bus_addressables_count - 1;
                     58:   
1.1.1.6 ! root       59: #if 0
        !            60:   if (bradshow)
        !            61:   {
        !            62:          extern int printf(const char *format, ...);
        !            63:          int i;
        !            64:          for (i = 0; i < bus->tme_bus_addressables_count; i++) {
        !            65: 
        !            66:                  conn_int = bus->tme_bus_addressables[i].tme_bus_addressable_connection;
        !            67:                  subregion = bus->tme_bus_addressables[i].tme_bus_addressable_subregion;
        !            68: 
        !            69:                  printf("tme_bus_address_search() %d address %x %x %x\n",
        !            70:                         i,
        !            71:                         (int)conn_int->tme_bus_connection_int_address,
        !            72:                         (int)(conn_int->tme_bus_connection_int_address + subregion->tme_bus_subregion_address_first),
        !            73:                         (int)(conn_int->tme_bus_connection_int_address + subregion->tme_bus_subregion_address_last));
        !            74: 
        !            75: //               conn_int->tme_bus_connection_int.tme_bus_connection.tme_connection_other->tme_connection_element
        !            76:          }
        !            77:   }
        !            78: #endif
        !            79: 
1.1       root       80:   /* do the search: */
                     81:   pivot = 0;
                     82:   for (; left <= right; ) {
                     83: 
                     84:     /* get the pivot: */
                     85:     pivot = (left + right) / 2;
1.1.1.2   root       86:     conn_int = bus->tme_bus_addressables[pivot].tme_bus_addressable_connection;
                     87:     subregion = bus->tme_bus_addressables[pivot].tme_bus_addressable_subregion;
1.1       root       88: 
1.1.1.6 ! root       89: #if 0
        !            90:     if (bradshow)
        !            91:     {
        !            92:            extern int printf(const char *format, ...);
        !            93:            printf("tme_bus_address_search() address %x (%x - %x)\n",
        !            94:                   (int)address,
        !            95:                   (int)(conn_int->tme_bus_connection_int_address + subregion->tme_bus_subregion_address_first),
        !            96:                   (int)(conn_int->tme_bus_connection_int_address + subregion->tme_bus_subregion_address_last));
        !            97:     }
        !            98: #endif
        !            99: 
1.1       root      100:     /* if we have to move left: */
1.1.1.2   root      101:     if (address
                    102:        < (conn_int->tme_bus_connection_int_address
                    103:           + subregion->tme_bus_subregion_address_first)) {
1.1       root      104:       /* if we're done searching, pivot is already the index of the
                    105:         first element we need to shift to the right in order to
                    106:         insert a new element: */
                    107:       right = pivot - 1;
                    108:     }
                    109: 
                    110:     /* if we have to move right: */
1.1.1.2   root      111:     else if (address
                    112:             > (conn_int->tme_bus_connection_int_address
                    113:                + subregion->tme_bus_subregion_address_last)) {
1.1       root      114:       /* if we're done searching, pivot + 1 is the index of the
                    115:         first element we need to shift to the right in order to
                    116:         insert a new element: */
                    117:       left = ++pivot;
                    118:     }
                    119: 
                    120:     /* we found the addressable: */
                    121:     else {
1.1.1.6 ! root      122: #if 0
        !           123:            if (bradshow)
        !           124:            {
        !           125:                    extern int printf(const char *format, ...);
        !           126:                    printf("tme_bus_address_search() hit, pivot %d\n", pivot);
        !           127:            }
        !           128: #endif
1.1       root      129:       return (pivot);
                    130:     }
                    131:   }
                    132: 
1.1.1.6 ! root      133: #if 0
        !           134:   if (bradshow)
        !           135:   {
        !           136:          extern int printf(const char *format, ...);
        !           137:          printf("tme_bus_address_search() miss, pivot %d\n", pivot);
        !           138:   }
        !           139: #endif
        !           140: 
1.1       root      141:   /* we failed to find an addressable that covers the address: */
                    142:   return (-1 - pivot);
                    143: }
                    144: 
                    145: /* this fills a TLB entry: */
                    146: int
                    147: tme_bus_tlb_fill(struct tme_bus *bus,
                    148:                 struct tme_bus_connection_int *conn_int_asker,
                    149:                 struct tme_bus_tlb *tlb,
                    150:                 tme_bus_addr_t address, 
                    151:                 unsigned int cycles)
                    152: {
                    153:   int pivot;
                    154:   struct tme_bus_connection_int *conn_int;
1.1.1.2   root      155:   const struct tme_bus_subregion *subregion;
1.1       root      156:   struct tme_bus_connection *conn_bus_other;
                    157:   tme_bus_addr_t sourced_address_mask, conn_address;
                    158:   tme_bus_addr_t hole_first, hole_last;
                    159:   struct tme_bus_tlb tlb_bus;
                    160:   void *cycle_fault_private;
                    161:   tme_bus_cycle_handler cycle_fault;
                    162:   int rc;
                    163: 
                    164:   /* get the sourced address mask: */
                    165:   sourced_address_mask = conn_int_asker->tme_bus_connection_int_sourced;
                    166: 
1.1.1.4   root      167:   /* get the asked address on the bus: */
                    168:   conn_address = (sourced_address_mask | address);
                    169: 
                    170:   /* start the mapping TLB entry: */
                    171:   tlb_bus.tme_bus_tlb_addr_first = 0;
                    172:   tlb_bus.tme_bus_tlb_addr_last = TME_MIN(((sourced_address_mask
                    173:                                            | (sourced_address_mask - 1))
                    174:                                           ^ sourced_address_mask),
                    175:                                          bus->tme_bus_address_mask);
                    176:   tlb_bus.tme_bus_tlb_cycles_ok = TME_BUS_CYCLE_READ | TME_BUS_CYCLE_WRITE;
                    177: 
                    178:   /* if this bus has a controller, and this request isn't coming from
                    179:      the controller: */
                    180:   conn_int = bus->tme_bus_controller;
                    181:   if (conn_int != NULL
                    182:       && conn_int != conn_int_asker) {
                    183: 
                    184:     /* get the controller's connection: */
                    185:     conn_bus_other = 
                    186:       (struct tme_bus_connection *) conn_int->tme_bus_connection_int.tme_bus_connection.tme_connection_other;
                    187: 
                    188:     /* unlock the bus: */
                    189:     tme_rwlock_unlock(&bus->tme_bus_rwlock);
                    190: 
                    191:     /* call the controller's TLB fill function: */
                    192:     rc = (*conn_bus_other->tme_bus_tlb_fill)(conn_bus_other, tlb,
                    193:                                             conn_address, cycles);
                    194: 
                    195:     /* relock the bus: */
                    196:     /* XXX FIXME - we assume that this succeeds: */
                    197:     (void) tme_rwlock_timedrdlock(&bus->tme_bus_rwlock, TME_THREAD_TIMEDLOCK);
                    198: 
                    199:     /* if the TLB fill succeeded: */
                    200:     if (rc == TME_OK) {
                    201: 
                    202:       /* map the filled TLB entry: */
                    203:       tme_bus_tlb_map(tlb, conn_address, &tlb_bus, address);
                    204:     }
                    205: 
                    206:     return (rc);
                    207:   }
                    208: 
1.1       root      209:   /* search for this address on the bus: */
1.1.1.4   root      210:   pivot = tme_bus_address_search(bus, conn_address);
1.1       root      211: 
1.1.1.6 ! root      212: #if 0
        !           213:   if (bradshow)
        !           214:   {
        !           215:          extern int printf(const char *format, ...);
        !           216:          printf("tme_bus_tlb_fill() address %x %x pivot %d\n", (int)address, (int)conn_address, pivot);
        !           217:   }
        !           218: #endif
        !           219: 
1.1       root      220:   /* if this address doesn't exist: */
                    221:   if (pivot < 0) {
                    222: 
                    223:     /* save the bus' fault cycle handler: */
                    224:     cycle_fault_private = tlb->tme_bus_tlb_cycle_private;
                    225:     cycle_fault = tlb->tme_bus_tlb_cycle;
                    226: 
                    227:     /* initialize the TLB entry: */
                    228:     tme_bus_tlb_initialize(tlb);
                    229: 
1.1.1.4   root      230:     /* this TLB entry can cover the entire hole in the address space: */
1.1       root      231:     pivot = -1 - pivot;
                    232:     hole_first = (pivot == 0
                    233:                  ? 0
1.1.1.2   root      234:                  : ((bus->tme_bus_addressables[pivot - 1]
                    235:                      .tme_bus_addressable_connection->tme_bus_connection_int_address)
                    236:                     + (bus->tme_bus_addressables[pivot - 1]
                    237:                        .tme_bus_addressable_subregion->tme_bus_subregion_address_last)
1.1       root      238:                     + 1));
                    239:     hole_last = (pivot == bus->tme_bus_addressables_count
                    240:                 ? bus->tme_bus_address_mask
1.1.1.2   root      241:                 : ((bus->tme_bus_addressables[pivot]
                    242:                     .tme_bus_addressable_connection->tme_bus_connection_int_address)
                    243:                    - 1));
1.1.1.4   root      244:     tlb->tme_bus_tlb_addr_first = hole_first;
                    245:     tlb->tme_bus_tlb_addr_last = hole_last;
1.1       root      246: 
                    247:     /* reads and writes are allowed: */
                    248:     tlb->tme_bus_tlb_cycles_ok = TME_BUS_CYCLE_READ | TME_BUS_CYCLE_WRITE;
                    249: 
                    250:     /* reads and writes in this region always fault: */
                    251:     tlb->tme_bus_tlb_cycle_private = cycle_fault_private;
                    252:     tlb->tme_bus_tlb_cycle = cycle_fault;
                    253:     rc = TME_OK;
                    254:   }
                    255: 
                    256:   /* otherwise, this address does exist: */
                    257:   else {
1.1.1.2   root      258:     conn_int = bus->tme_bus_addressables[pivot].tme_bus_addressable_connection;
                    259:     subregion = bus->tme_bus_addressables[pivot].tme_bus_addressable_subregion;
1.1       root      260:     conn_bus_other = 
                    261:       (struct tme_bus_connection *) conn_int->tme_bus_connection_int.tme_bus_connection.tme_connection_other;
                    262: 
                    263:     /* call the TLB fill function for the connection: */
1.1.1.4   root      264:     conn_address -= conn_int->tme_bus_connection_int_address;
1.1       root      265:     rc = (*conn_bus_other->tme_bus_tlb_fill)(conn_bus_other, tlb,
                    266:                                             conn_address, cycles);
                    267: 
                    268:     /* if that succeeded: */
                    269:     if (rc == TME_OK) {
                    270:       
                    271:       /* create the mapping TLB entry: */
1.1.1.4   root      272:       tlb_bus.tme_bus_tlb_addr_first =
                    273:        (TME_MAX((conn_int->tme_bus_connection_int_address
                    274:                  + subregion->tme_bus_subregion_address_first),
                    275:                 (sourced_address_mask
                    276:                  | tlb_bus.tme_bus_tlb_addr_first))
                    277:         - sourced_address_mask);
                    278:       tlb_bus.tme_bus_tlb_addr_last = 
                    279:        (TME_MIN((conn_int->tme_bus_connection_int_address
                    280:                  + subregion->tme_bus_subregion_address_last),
                    281:                 (sourced_address_mask
                    282:                  | tlb_bus.tme_bus_tlb_addr_last))
                    283:         - sourced_address_mask);
1.1       root      284:     }
                    285:   }
                    286: 
1.1.1.4   root      287:   /* if the TLB fill succeeded: */
                    288:   if (rc == TME_OK) {
                    289: 
                    290:     /* map the filled TLB entry: */
                    291:     tme_bus_tlb_map(tlb, conn_address, &tlb_bus, address);
                    292:   }
                    293: 
1.1       root      294:   /* done: */
                    295:   return (rc);
                    296: }
                    297: 
1.1.1.5   root      298: /* this adds a new TLB set: */
1.1       root      299: int
1.1.1.5   root      300: tme_bus_tlb_set_add(struct tme_bus *bus,
                    301:                    struct tme_bus_connection_int *conn_int_asker,
                    302:                    struct tme_bus_tlb_set_info *tlb_set_info)
1.1       root      303: {
                    304:   struct tme_bus_connection *conn_bus_other, *conn_bus_dma;
                    305:   int conn_int_i;
                    306:   int rc;
                    307: 
                    308:   /* at most one of our addressable connections may provide a TLB set
1.1.1.5   root      309:      add function.  generally, this means that connection is a
1.1       root      310:      DMA-controller-like connection to the bus, where it may need to
                    311:      invalidate at any later time the TLBs it fills out, due to sudden
                    312:      changes in how the DMA region on the bus is mapped: */
                    313:   conn_bus_dma = NULL;
                    314:   for (conn_int_i = 0;
                    315:        conn_int_i < bus->tme_bus_addressables_count;
                    316:        conn_int_i++) {
                    317:     conn_bus_other = 
1.1.1.2   root      318:       ((struct tme_bus_connection *)
                    319:        bus->tme_bus_addressables[conn_int_i].tme_bus_addressable_connection
                    320:        ->tme_bus_connection_int.tme_bus_connection.tme_connection_other);
1.1       root      321: 
1.1.1.5   root      322:     /* if this bus connection offers a TLB set add function, it is
1.1       root      323:        a DMA-controller-like connection to the bus: */
1.1.1.5   root      324:     if (conn_bus_other->tme_bus_tlb_set_add != NULL) {
1.1       root      325: 
                    326:       /* if there is more than one of these, it is likely a
                    327:         configuration error.  if we had some way of specifying which
                    328:         of several DMA regions a given connection will always use, we
                    329:         could avoid this: */
                    330:       if (conn_bus_dma != NULL) {
                    331:        abort();
                    332:       }
                    333: 
                    334:       conn_bus_dma = conn_bus_other;
                    335:     }
                    336:   }
                    337: 
                    338:   /* if there is a DMA-controller-like connection to the bus, 
1.1.1.5   root      339:      let it add the TLB set: */
1.1       root      340:   if (conn_bus_dma != NULL) {
1.1.1.5   root      341:     rc = (*conn_bus_dma->tme_bus_tlb_set_add)
                    342:       (conn_bus_dma, tlb_set_info);
1.1       root      343:   }
                    344: 
1.1.1.5   root      345:   /* otherwise, handle the add ourselves: */
1.1       root      346:   else {
1.1.1.5   root      347:     
                    348:     /* if this TLB set provides a bus context register: */
                    349:     if (tlb_set_info->tme_bus_tlb_set_info_bus_context != NULL) {
                    350: 
                    351:       /* this bus only has one context: */
                    352:       (*tlb_set_info->tme_bus_tlb_set_info_bus_context) = 0;
                    353:       tlb_set_info->tme_bus_tlb_set_info_bus_context_max = 0;
1.1       root      354:     }
                    355:     rc = TME_OK;
                    356:   }
                    357:       
                    358:   /* done: */
                    359:   return (rc);
                    360: }
                    361: 
1.1.1.5   root      362: /* this invalidates a TLB set: */
                    363: void
                    364: tme_bus_tlb_set_invalidate(const struct tme_bus_tlb_set_info *tlb_set_info)
                    365: {
                    366:   struct tme_token *token;
                    367:   unsigned long token_count;
                    368: 
                    369:   /* invalidate the tokens in the TLB set: */
                    370:   token = tlb_set_info->tme_bus_tlb_set_info_token0;
                    371:   token_count = tlb_set_info->tme_bus_tlb_set_info_token_count;
                    372:   do {
                    373:     tme_token_invalidate(token);
                    374:     token = (struct tme_token *) (((tme_uint8_t *) token) + tlb_set_info->tme_bus_tlb_set_info_token_stride);
                    375:   } while (--token_count > 0);
                    376: }
                    377: 
1.1       root      378: /* this returns nonzero if the connection's address space is available: */
                    379: int
                    380: tme_bus_connection_ok(struct tme_bus *bus,
                    381:                      struct tme_bus_connection_int *conn_int)
                    382: {
1.1.1.2   root      383:   const struct tme_bus_subregion *subregion;
                    384:   const struct tme_bus_connection *conn_bus_other;
1.1       root      385:   int pivot_start, pivot_end;
                    386: 
                    387:   /* if this connection isn't addressable, it's always OK: */
1.1.1.4   root      388:   if (!(conn_int->tme_bus_connection_int_flags
                    389:        & TME_BUS_CONNECTION_INT_FLAG_ADDRESSABLE)) {
1.1       root      390:     return (TRUE);
                    391:   }
                    392: 
1.1.1.2   root      393:   /* all subregions of this connection must fit on the bus,
                    394:      and they must not overlap with any other subregion on 
                    395:      any other existing connection: */
                    396:   /* XXX we should also check that the connection's subregions don't
                    397:      overlap with each other: */
                    398:   conn_bus_other
                    399:     = ((struct tme_bus_connection *)
                    400:        conn_int->tme_bus_connection_int.tme_bus_connection.tme_connection_other);
                    401:   for (subregion = &conn_bus_other->tme_bus_subregions;
                    402:        subregion != NULL;
                    403:        subregion = subregion->tme_bus_subregion_next) {
                    404: 
                    405:     /* the subregion's last address cannot be less than
                    406:        the first address: */
                    407:     if (subregion->tme_bus_subregion_address_last
                    408:        < subregion->tme_bus_subregion_address_first) {
                    409:       return (FALSE);
                    410:     }
                    411:     
                    412:     /* this subregion must fit on the bus: */
                    413:     if (subregion->tme_bus_subregion_address_last >
                    414:        (bus->tme_bus_address_mask
                    415:         - conn_int->tme_bus_connection_int_address)) {
                    416:       return (FALSE);
                    417:     }
                    418: 
                    419:     /* search for anything covering the start or end of the new
                    420:        addressable subregion: */
                    421:     pivot_start = 
                    422:       tme_bus_address_search(bus, 
                    423:                             (conn_int->tme_bus_connection_int_address
                    424:                              + subregion->tme_bus_subregion_address_first));
                    425:     pivot_end =
                    426:       tme_bus_address_search(bus,
                    427:                             (conn_int->tme_bus_connection_int_address
                    428:                              + subregion->tme_bus_subregion_address_last));
                    429: 
                    430:     /* both searches must have failed, and they must have stopped at the
                    431:        same point in the sorted addressables, further indicating that no
                    432:        addressable exists anywhere *between* the start and end of the
                    433:        new addressable, either.  otherwise, this connection fails: */
                    434:     if (pivot_start >= 0
                    435:        || pivot_end >= 0
                    436:        || pivot_start != pivot_end) {
                    437:       return (FALSE);
                    438:     }
1.1       root      439:   }
                    440: 
                    441:   /* this connection's address space is available: */
                    442:   return (TRUE);
                    443: }
                    444: 
1.1.1.6 ! root      445: void bradstop(void)
        !           446: {
        !           447:        volatile int x = 0;
        !           448:        x++;
        !           449: }
        !           450: 
1.1       root      451: /* this makes a new connection: */
                    452: int
                    453: tme_bus_connection_make(struct tme_bus *bus,
                    454:                        struct tme_bus_connection_int *conn_int,
                    455:                        unsigned int state)
                    456: {
1.1.1.2   root      457:   const struct tme_bus_connection *conn_bus_other;
                    458:   const struct tme_bus_subregion *subregion;
1.1       root      459:   int pivot;
                    460: 
                    461:   /* if this connection is not full, return now: */
                    462:   if (state == TME_CONNECTION_HALF) {
                    463:     return (TME_OK);
                    464:   }
                    465: 
1.1.1.4   root      466:   /* if this connection is to a bus controller: */
                    467:   if (conn_int->tme_bus_connection_int_flags
                    468:       & TME_BUS_CONNECTION_INT_FLAG_CONTROLLER) {
                    469: 
                    470:     /* if this bus already has a controller: */
                    471:     if (bus->tme_bus_controller != NULL) {
                    472: 
                    473:       /* we can't make this connection: */
                    474:       return (EEXIST);
                    475:     }
                    476: 
                    477:     /* this connection is to the bus controller: */
                    478:     bus->tme_bus_controller = conn_int;
                    479:   }
                    480: 
1.1       root      481:   /* add this connection to our list: */
                    482:   conn_int->tme_bus_connection_int.tme_bus_connection.tme_connection_next
                    483:     = (struct tme_connection *) bus->tme_bus_connections;
                    484:   bus->tme_bus_connections = conn_int;
                    485: 
                    486:   /* if this connection is addressable, and this is connection is now
                    487:      fully made, add it to our list of addressables: */
1.1.1.4   root      488:   if ((conn_int->tme_bus_connection_int_flags
                    489:        & TME_BUS_CONNECTION_INT_FLAG_ADDRESSABLE)
1.1       root      490:       && state == TME_CONNECTION_FULL) {
                    491:     
1.1.1.2   root      492:     /* add all subregions of this connection as addressables: */
                    493:     conn_int->tme_bus_connection_int_address_last = 0;
                    494:     conn_bus_other
                    495:       = ((struct tme_bus_connection *)
                    496:         conn_int->tme_bus_connection_int.tme_bus_connection.tme_connection_other);
                    497:     for (subregion = &conn_bus_other->tme_bus_subregions;
                    498:         subregion != NULL;
                    499:         subregion = subregion->tme_bus_subregion_next) {
                    500: 
                    501:       /* search for the place to insert this new addressable: */
                    502:       pivot = tme_bus_address_search(bus, 
                    503:                                     (conn_int->tme_bus_connection_int_address
                    504:                                      + subregion->tme_bus_subregion_address_first));
                    505:       assert(pivot < 0);
                    506:       pivot = -1 - pivot;
1.1       root      507:     
1.1.1.2   root      508:       /* if we have to, grow the addressable array: */
                    509:       if (bus->tme_bus_addressables_count
                    510:          == bus->tme_bus_addressables_size) {
                    511:        bus->tme_bus_addressables_size += (bus->tme_bus_addressables_size >> 1) + 1;
                    512:        bus->tme_bus_addressables = tme_renew(struct tme_bus_addressable,
                    513:                                              bus->tme_bus_addressables,
                    514:                                              bus->tme_bus_addressables_size);
                    515:       }
                    516: 
                    517:       /* move all of the later addressables down: */
                    518:       memmove(&bus->tme_bus_addressables[pivot + 1],
                    519:              &bus->tme_bus_addressables[pivot],
                    520:              sizeof(bus->tme_bus_addressables[pivot])
                    521:              * (bus->tme_bus_addressables_count
                    522:                 - pivot));
                    523: 
1.1.1.6 ! root      524: #if 0
        !           525:   {
        !           526:          extern int printf(const char *format, ...);
        !           527:          printf("tme_bus_connection_make() @%d %x %x\n",
        !           528:                 pivot,
        !           529:                 (int)(conn_int->tme_bus_connection_int_address + subregion->tme_bus_subregion_address_first),
        !           530:                 (int)(conn_int->tme_bus_connection_int_address + subregion->tme_bus_subregion_address_last));
        !           531:   }
        !           532: 
        !           533:   if ((int)(conn_int->tme_bus_connection_int_address + subregion->tme_bus_subregion_address_first) == 0 &&
        !           534:       (int)(conn_int->tme_bus_connection_int_address + subregion->tme_bus_subregion_address_last) == 0x40000) {
        !           535:          void bradstop(void);
        !           536:          bradstop();
        !           537:          return TME_OK;
        !           538:   }
        !           539: #endif
        !           540: 
1.1.1.2   root      541:       /* insert this new addressable: */
                    542:       bus->tme_bus_addressables[pivot].tme_bus_addressable_connection = conn_int;
                    543:       bus->tme_bus_addressables[pivot].tme_bus_addressable_subregion = subregion;
                    544:       bus->tme_bus_addressables_count++;
                    545: 
                    546:       /* update the last address on this connection.  NB that the
                    547:         subregion information should be used almost always.
                    548:         currently this value is only used as the width of the
                    549:         connection for the purposes of determining TLB entry limits
                    550:         when the connection itself asks to fill a TLB entry: */
                    551:       conn_int->tme_bus_connection_int_address_last
                    552:        = TME_MAX(conn_int->tme_bus_connection_int_address_last,
                    553:                  subregion->tme_bus_subregion_address_last);
                    554:     }
1.1       root      555:   }
                    556: 
                    557:   return (TME_OK);
                    558: }
                    559: 
                    560: /* this breaks a connection: */
                    561: int
                    562: tme_bus_connection_break(struct tme_bus *bus,
                    563:                         struct tme_bus_connection_int *conn_int,
                    564:                         unsigned int state)
                    565: {
                    566:   abort();
                    567: }
                    568: 
                    569: /* this map the first bus TLB entry to be valid on another bus, according to
                    570:    the information in the second bus TLB entry: */
                    571: void
                    572: tme_bus_tlb_map(struct tme_bus_tlb *tlb0, tme_bus_addr_t addr0, 
                    573:                const struct tme_bus_tlb *tlb1, tme_bus_addr_t addr1)
                    574: {
                    575:   tme_bus_addr_t extra_before0, extra_after0;
                    576:   tme_bus_addr_t extra_before1, extra_after1;
1.1.1.5   root      577:   tme_bus_addr_t addr_offset;
1.1       root      578:   unsigned int cycles_ok;
                    579: 
1.1.1.6 ! root      580: #if 0
        !           581:   if (bradshow)
        !           582:   {
        !           583:          extern int printf(const char *format, ...);
        !           584:          printf("tme_bus_tlb_map() %x %x\n", (int)addr0, (int)addr1);
        !           585:   }
        !           586: #endif
        !           587: 
1.1       root      588:   /* get the address offset: */
1.1.1.4   root      589:   addr_offset = addr1;
                    590:   addr_offset -= addr0;
1.1       root      591: 
                    592:   /* intersect the amount of bus address space covered: */
1.1.1.4   root      593:   extra_before0 = addr0 - tlb0->tme_bus_tlb_addr_first;
                    594:   extra_after0 = tlb0->tme_bus_tlb_addr_last - addr0;
                    595:   extra_before1 = addr1 - tlb1->tme_bus_tlb_addr_first;
                    596:   extra_after1 = tlb1->tme_bus_tlb_addr_last - addr1;
                    597:   tlb0->tme_bus_tlb_addr_first = addr1 - TME_MIN(extra_before0, extra_before1);
                    598:   tlb0->tme_bus_tlb_addr_last = addr1 + TME_MIN(extra_after0, extra_after1);
1.1       root      599: 
                    600:   /* intersect the kinds of bus cycles allowed: */
                    601:   cycles_ok = (tlb0->tme_bus_tlb_cycles_ok &= tlb1->tme_bus_tlb_cycles_ok);
                    602:   if (!(cycles_ok & TME_BUS_CYCLE_READ)) {
                    603:     tlb0->tme_bus_tlb_emulator_off_read = TME_EMULATOR_OFF_UNDEF;
                    604:   }
                    605:   else if (tlb0->tme_bus_tlb_emulator_off_read != TME_EMULATOR_OFF_UNDEF) {
                    606:     tlb0->tme_bus_tlb_emulator_off_read -= addr_offset;
                    607:   }
                    608:   if (!(cycles_ok & TME_BUS_CYCLE_WRITE)) {
                    609:     tlb0->tme_bus_tlb_emulator_off_write = TME_EMULATOR_OFF_UNDEF;
                    610:   }
                    611:   else if (tlb0->tme_bus_tlb_emulator_off_write != TME_EMULATOR_OFF_UNDEF) {
                    612:     tlb0->tme_bus_tlb_emulator_off_write -= addr_offset;
                    613:   }
                    614: 
                    615:   /* update the address shift for the cycle handler: */
                    616:   tlb0->tme_bus_tlb_addr_offset -= addr_offset;
                    617: }
                    618: 
                    619: /* this initializes a bus TLB entry: */
                    620: void
                    621: tme_bus_tlb_initialize(struct tme_bus_tlb *tlb)
                    622: {
                    623:   
                    624:   /* make the first address covered all-bits-one: */
1.1.1.4   root      625:   tlb->tme_bus_tlb_addr_first = (((tme_bus_addr_t) 0) - 1);
1.1       root      626:   
                    627:   /* make the last address covered all-bits-zero: */
1.1.1.4   root      628:   tlb->tme_bus_tlb_addr_last = 0;
1.1       root      629: 
                    630:   /* no fast (memory) transfers allowed: */
                    631:   tlb->tme_bus_tlb_emulator_off_read = TME_EMULATOR_OFF_UNDEF;
                    632:   tlb->tme_bus_tlb_emulator_off_write = TME_EMULATOR_OFF_UNDEF;
                    633:   tlb->tme_bus_tlb_rwlock = NULL;
                    634: 
                    635:   /* no bus cycles allowed: */
                    636:   tlb->tme_bus_tlb_cycles_ok = TME_BUS_CYCLE_UNDEF;
                    637: 
                    638:   /* no address offset or shift: */
                    639:   tlb->tme_bus_tlb_addr_offset = 0;
                    640:   tlb->tme_bus_tlb_addr_shift = 0;
                    641: 
1.1.1.5   root      642:   /* not cacheable: */
                    643:   tlb->tme_bus_tlb_cacheable = NULL;
                    644: 
1.1       root      645:   /* no bus cycle handler: */
                    646:   tlb->tme_bus_tlb_cycle_private = NULL;
                    647:   tlb->tme_bus_tlb_cycle = NULL;
                    648: 
                    649:   /* no bus fault handlers: */
                    650:   tlb->tme_bus_tlb_fault_handler_count = 0;
                    651: }
                    652: 
                    653: /* this calls a TLB entry's fault handlers: */
                    654: int
                    655: tme_bus_tlb_fault(struct tme_bus_tlb *tlb, struct tme_bus_cycle *cycle, int rc)
                    656: {
                    657:   unsigned int i;
                    658: 
                    659:   /* call all of the fault handlers: */
                    660:   for (i = 0; i < tlb->tme_bus_tlb_fault_handler_count; i++) {
                    661:     rc = ((*tlb->tme_bus_tlb_fault_handlers[i].tme_bus_tlb_fault_handler)
                    662:          (tlb->tme_bus_tlb_fault_handlers[i].tme_bus_tlb_fault_handler_private,
                    663:           tlb, cycle, rc));
                    664:   }
                    665: 
                    666:   return (rc);
                    667: }
                    668: 
                    669: /* this parses any bus address: */
                    670: tme_bus_addr_t
                    671: tme_bus_addr_parse_any(const char *address_string, int *_failed)
                    672: {
1.1.1.3   root      673:   return (tme_misc_unumber_parse_any(address_string, _failed));
1.1       root      674: }
                    675: 
                    676: /* this parses a bus address that has a restricted range: */
                    677: tme_bus_addr_t
                    678: tme_bus_addr_parse(const char *address_string, tme_bus_addr_t failure_value)
                    679: {
                    680:   int failed;
                    681:   tme_bus_addr_t address;
                    682:   address = tme_bus_addr_parse_any(address_string, &failed);
                    683:   return (failed ? failure_value : address);
                    684: }
                    685: 
                    686: /* this transfers bytes between the two participants in a bus cycle: */
                    687: void
                    688: tme_bus_cycle_xfer(struct tme_bus_cycle *cycle_init, struct tme_bus_cycle *cycle_resp)
                    689: {
                    690:   struct tme_bus_cycle *cycle_reader, *cycle_writer;
                    691:   int buffer_increment_mask_reader, buffer_increment_mask_writer;
                    692:   int port_size_reader, port_size_writer;
                    693:   int port_overlap_lane_least, port_overlap_size, port_overlap_size_lg2;
                    694:   int lane, lane_end;
                    695:   int lane_reader, lane_writer;
                    696:   int lane_in_reader, lane_in_writer;
                    697:   int lane_routing_offset_reader, lane_routing_offset_writer;
                    698:   tme_bus_lane_t lane_routing_reader, lane_routing_writer;
                    699:   tme_uint8_t lane_value;
                    700:   int warn_on_lane;
                    701:   unsigned int cycle_size_reader, cycle_size_writer;
                    702: 
1.1.1.6 ! root      703: #if 1
        !           704:   {
        !           705:          struct tme_bus_cycle *c = 0;
        !           706:          int which = 0;
        !           707:          if (cycle_resp->tme_bus_cycle_type == TME_BUS_CYCLE_WRITE) {
        !           708:                  c = cycle_resp;
        !           709:                  which = 1;
        !           710:          }
        !           711:          if (cycle_init->tme_bus_cycle_type == TME_BUS_CYCLE_WRITE) {
        !           712:                  c = cycle_init;
        !           713:                  which = 2;
        !           714:          }
        !           715:          
        !           716:          if (c) {
        !           717:                  extern int get_sunbw2_copy(void);
        !           718:                  extern int get_sunbw2_copy_addr(void);
        !           719:                  int printf(const char *format, ...);
        !           720: 
        !           721:                  if (0)
        !           722:                  if (c->tme_bus_cycle_address > 0x1000)
        !           723:                  printf("bus write %x %x %d @ %x, %d\n",
        !           724:                         (unsigned int)get_sunbw2_copy(),
        !           725:                         (unsigned int)get_sunbw2_copy_addr(),
        !           726:                         which,
        !           727:                         (unsigned int)c->tme_bus_cycle_address,
        !           728:                         (unsigned int)c->tme_bus_cycle_size);
        !           729: 
        !           730:                  if (get_sunbw2_copy()) {
        !           731:                          if ((c->tme_bus_cycle_address & 0x007e0000) == get_sunbw2_copy_addr()) {
        !           732:                                  printf("hit!\n");
        !           733:                                  //abort();
        !           734:                          }
        !           735:                  }
        !           736:          }
        !           737:   }
        !           738: #endif
        !           739: 
1.1       root      740:   /* sort the initiator and responder into bus reader and bus writer: */
                    741:   if (cycle_init->tme_bus_cycle_type == TME_BUS_CYCLE_READ) {
                    742:     assert(cycle_resp->tme_bus_cycle_type == TME_BUS_CYCLE_WRITE);
                    743:     cycle_reader = cycle_init;
                    744:     cycle_writer = cycle_resp;
                    745:   }
                    746:   else {
                    747:     assert(cycle_init->tme_bus_cycle_type == TME_BUS_CYCLE_WRITE);
                    748:     assert(cycle_resp->tme_bus_cycle_type == TME_BUS_CYCLE_READ);
                    749:     cycle_reader = cycle_resp;
                    750:     cycle_writer = cycle_init;
                    751:   }
                    752: 
                    753:   /* get the increment masks for the reader and writer.  since
                    754:      tme_bus_cycle_buffer_increment is always 1 or -1, this mask is
                    755:      used to negate values without multiplication: */
                    756:   if (cycle_reader->tme_bus_cycle_buffer_increment == -1) {
                    757:     buffer_increment_mask_reader = -1;
                    758:   }
                    759:   else {
                    760:     assert(cycle_reader->tme_bus_cycle_buffer_increment == 1);
                    761:     buffer_increment_mask_reader = 0;
                    762:   }
                    763:   if (cycle_writer->tme_bus_cycle_buffer_increment == -1) {
                    764:     buffer_increment_mask_writer = -1;
                    765:   }
                    766:   else {
                    767:     assert(cycle_writer->tme_bus_cycle_buffer_increment == 1);
                    768:     buffer_increment_mask_writer = 0;
                    769:   }
                    770: #define _TME_BUS_CYCLE_BUFFER_MULTIPLY(value, mask) \
                    771:   (((value) ^ (mask)) + ((mask) & 1))
                    772: 
                    773:   /* get the sizes, in bytes, of the reader and writer ports: */
                    774:   port_size_reader = (1 << TME_BUS_CYCLE_PORT_SIZE_LG2(cycle_reader->tme_bus_cycle_port));
                    775:   port_size_writer = (1 << TME_BUS_CYCLE_PORT_SIZE_LG2(cycle_writer->tme_bus_cycle_port));
                    776: 
                    777:   /* determine how the writer's port and the reader's port overlap: */
                    778:   port_overlap_size = port_size_writer;
                    779:   port_overlap_lane_least = TME_BUS_CYCLE_PORT_LANE_LEAST(cycle_writer->tme_bus_cycle_port);
                    780:   lane = TME_BUS_CYCLE_PORT_LANE_LEAST(cycle_reader->tme_bus_cycle_port);
                    781:   if (port_overlap_lane_least < lane) {
                    782:     port_overlap_size -= (lane - port_overlap_lane_least);
                    783:     port_overlap_lane_least = lane;
                    784:   }
                    785:   lane += port_size_reader;
                    786:   if ((port_overlap_lane_least + port_overlap_size) > lane) {
                    787:     port_overlap_size -= (lane - (port_overlap_lane_least + port_overlap_size));
                    788:   }
                    789:   assert(port_overlap_size > 0);
                    790:   for (port_overlap_size_lg2 = 0;
                    791:        (port_overlap_size >>= 1) != 0;
                    792:        port_overlap_size_lg2++);
                    793: 
                    794:   /* select the reader's lane routing: */
                    795:   lane_routing_offset_reader =
                    796:     TME_BUS_ROUTER_INDEX(TME_BUS_CYCLE_PORT_SIZE_LG2(cycle_reader->tme_bus_cycle_port),
                    797:                         port_overlap_size_lg2,
                    798:                         port_overlap_lane_least
                    799:                         - TME_BUS_CYCLE_PORT_LANE_LEAST(cycle_reader->tme_bus_cycle_port));
                    800: 
                    801:   /* select the writer's lane routing: */
                    802:   lane_routing_offset_writer =
                    803:     TME_BUS_ROUTER_INDEX(TME_BUS_CYCLE_PORT_SIZE_LG2(cycle_writer->tme_bus_cycle_port),
                    804:                         port_overlap_size_lg2,
                    805:                         port_overlap_lane_least
                    806:                         - TME_BUS_CYCLE_PORT_LANE_LEAST(cycle_writer->tme_bus_cycle_port));
                    807: 
                    808:   /* loop over all byte lanes in one or both ports: */
                    809:   lane = TME_MIN(TME_BUS_CYCLE_PORT_LANE_LEAST(cycle_reader->tme_bus_cycle_port),
                    810:                 TME_BUS_CYCLE_PORT_LANE_LEAST(cycle_writer->tme_bus_cycle_port));
                    811:   lane_end = TME_MAX(TME_BUS_CYCLE_PORT_LANE_LEAST(cycle_reader->tme_bus_cycle_port) + port_size_reader,
                    812:                     TME_BUS_CYCLE_PORT_LANE_LEAST(cycle_writer->tme_bus_cycle_port) + port_size_writer);
                    813:   cycle_size_reader = cycle_size_writer = 0;
                    814:   for (; lane < lane_end; lane++) {
                    815: 
                    816:     /* assume that we won't have to warn on this lane: */
                    817:     warn_on_lane = FALSE;
                    818: 
                    819:     /* see if this lane falls in the reader or writer's port: */
                    820:     lane_reader = lane - TME_BUS_CYCLE_PORT_LANE_LEAST(cycle_reader->tme_bus_cycle_port);
                    821:     lane_writer = lane - TME_BUS_CYCLE_PORT_LANE_LEAST(cycle_writer->tme_bus_cycle_port);
                    822:     lane_in_reader = (lane_reader >= 0 && lane_reader < port_size_reader);
                    823:     lane_in_writer = (lane_writer >= 0 && lane_writer < port_size_writer);
                    824: 
                    825:     /* get the value being written to this byte lane.  assume a
                    826:        garbage value: */
                    827:     lane_value = 0xd2;
                    828: 
                    829:     /* if this lane is in the writer's port, it may supply a real
                    830:        lane value: */
                    831:     if (lane_in_writer) {
                    832: 
                    833:       /* get the routing for the writer: */
                    834:       lane_routing_writer = 
                    835:        cycle_writer->tme_bus_cycle_lane_routing[lane_routing_offset_writer + lane_writer];
                    836: 
                    837:       /* if the writer doesn't expect this lane to be connected to the
                    838:         reader, we will issue a warning on this lane: */
                    839:       if ((lane_routing_writer & TME_BUS_LANE_WARN)
                    840:          && lane_in_reader) {
                    841:        warn_on_lane = TRUE;
                    842:       }
                    843:       lane_routing_writer &= ~TME_BUS_LANE_WARN;
                    844: 
                    845:       /* dispatch on the routing to get the lane value: */
                    846:       if (lane_routing_writer == TME_BUS_LANE_ABORT) {
                    847:        abort();
                    848:       }
                    849:       else if (lane_routing_writer != TME_BUS_LANE_UNDEF) {
                    850:        if (!(lane_routing_writer & TME_BUS_LANE_ROUTE_WRITE_IGNORE)
                    851:            && lane_routing_writer >= cycle_size_writer) {
                    852:          cycle_size_writer = lane_routing_writer + 1;
                    853:        }
                    854:        lane_routing_writer &= ~TME_BUS_LANE_ROUTE_WRITE_IGNORE;
                    855: 
                    856:        /* if the writer is the responder, make sure that only bytes
                    857:           in the given register are ever referenced.  given the
                    858:           writer's port size, we could warp the reference index as
                    859:           needed, but hopefully we'll never have to: */
                    860:        assert(!(cycle_writer == cycle_resp
                    861:                 && (((cycle_writer->tme_bus_cycle_address + lane_routing_writer)
                    862:                      ^  cycle_writer->tme_bus_cycle_address)
                    863:                     & ~(port_size_writer - 1)) != 0));
                    864: 
                    865:        lane_value =
                    866:          *(cycle_writer->tme_bus_cycle_buffer
                    867:            + _TME_BUS_CYCLE_BUFFER_MULTIPLY(lane_routing_writer,
                    868:                                             buffer_increment_mask_writer));
                    869:       }
                    870:     }
                    871: 
                    872:     /* if this lane is in the reader's port, it may take the lane
                    873:        value: */
                    874:     if (lane_in_reader) {
                    875: 
                    876:       /* get the routing for the reader: */
                    877:       lane_routing_reader =
                    878:        cycle_reader->tme_bus_cycle_lane_routing[lane_routing_offset_reader + lane_reader];
                    879: 
                    880:       /* if the reader doesn't expect this lane to be connected to the
                    881:         writer, we will issue a warning on this lane: */
                    882:       if ((lane_routing_reader & TME_BUS_LANE_WARN)
                    883:          && lane_in_writer) {
                    884:        warn_on_lane = TRUE;
                    885:       }
                    886:       lane_routing_reader &= ~TME_BUS_LANE_WARN;
                    887: 
                    888:       /* dispatch on the routing to take the lane value: */
                    889:       if (lane_routing_reader == TME_BUS_LANE_ABORT) {
                    890:        abort();
                    891:       }
                    892:       else if (lane_routing_reader != TME_BUS_LANE_UNDEF
                    893:               && !(lane_routing_reader & TME_BUS_LANE_ROUTE_WRITE_IGNORE)) {
                    894:        if (lane_routing_reader >= cycle_size_reader) {
                    895:          cycle_size_reader = lane_routing_reader + 1;
                    896:        }
                    897: 
                    898:        /* if the reader is the responder, make sure that only bytes
                    899:           in the given register are ever referenced.  given the
                    900:           reader's port size, we could warp the reference index as
                    901:           needed, but hopefully we'll never have to: */
                    902:        assert(!(cycle_reader == cycle_resp
                    903:                 && (((cycle_reader->tme_bus_cycle_address + lane_routing_reader)
                    904:                      ^  cycle_reader->tme_bus_cycle_address)
                    905:                     & ~(port_size_reader - 1)) != 0));
                    906: 
                    907:        *(cycle_reader->tme_bus_cycle_buffer
                    908:          + _TME_BUS_CYCLE_BUFFER_MULTIPLY(lane_routing_reader,
                    909:                                           buffer_increment_mask_reader)) =
                    910:          lane_value;
                    911:       }
                    912:     }
                    913: 
                    914:     /* if we need to issue a warning on this lane: */
                    915:     if (warn_on_lane) {
                    916:       /* XXX TBD: */
                    917:       abort();
                    918:     }
                    919:   }
                    920: 
                    921:   /* give the reader feedback: */
                    922:   cycle_reader->tme_bus_cycle_size = cycle_size_reader;
                    923:   cycle_reader->tme_bus_cycle_address += cycle_size_reader;
                    924:   cycle_reader->tme_bus_cycle_buffer += 
                    925:     _TME_BUS_CYCLE_BUFFER_MULTIPLY(cycle_size_reader,
                    926:                                   buffer_increment_mask_reader);
                    927:   cycle_reader->tme_bus_cycle_lane_routing += lane_routing_offset_reader;
                    928:   cycle_reader->tme_bus_cycle_port = 
                    929:     TME_BUS_CYCLE_PORT(port_overlap_lane_least, port_overlap_size_lg2);
                    930:   
                    931:   /* give the writer feedback: */
                    932:   cycle_writer->tme_bus_cycle_size = cycle_size_writer;
                    933:   cycle_writer->tme_bus_cycle_address += cycle_size_writer;
                    934:   cycle_writer->tme_bus_cycle_buffer += 
                    935:     _TME_BUS_CYCLE_BUFFER_MULTIPLY(cycle_size_writer,
                    936:                                   buffer_increment_mask_writer);
                    937:   cycle_writer->tme_bus_cycle_lane_routing += lane_routing_offset_writer;
                    938:   cycle_writer->tme_bus_cycle_port = 
                    939:     TME_BUS_CYCLE_PORT(port_overlap_lane_least, port_overlap_size_lg2);
                    940: }
                    941: 
                    942: /* this handles a bus cycle for a memory-like device: */
                    943: void
                    944: tme_bus_cycle_xfer_memory(struct tme_bus_cycle *cycle_init, tme_uint8_t *memory, tme_bus_addr_t address_last)
                    945: {
                    946:   tme_uint8_t memory_junk[sizeof(tme_bus_addr_t)];
                    947:   struct tme_bus_cycle cycle_resp;
                    948: 
                    949:   /* check the starting address: */
                    950:   assert(cycle_init->tme_bus_cycle_address <= address_last);
                    951: 
                    952:   /* get the start of the buffer for this starting address: */
                    953:   if (memory != NULL) {
                    954:     memory += cycle_init->tme_bus_cycle_address;
                    955:   }
                    956:   else {
                    957:     assert(sizeof(memory_junk)
1.1.1.2   root      958:           >= ((unsigned int) 1 << TME_BUS_CYCLE_PORT_SIZE_LG2(cycle_init->tme_bus_cycle_port)));
1.1       root      959:     memory = memory_junk;
                    960:   }
                    961: 
1.1.1.6 ! root      962: 
1.1       root      963:   /* create the responder cycle: */
                    964:   cycle_resp.tme_bus_cycle_buffer = memory;
                    965:   cycle_resp.tme_bus_cycle_buffer_increment = 1;
                    966:   cycle_resp.tme_bus_cycle_lane_routing = cycle_init->tme_bus_cycle_lane_routing;
                    967:   cycle_resp.tme_bus_cycle_address = cycle_init->tme_bus_cycle_address;
                    968:   cycle_resp.tme_bus_cycle_type = (cycle_init->tme_bus_cycle_type
                    969:                                   ^ (TME_BUS_CYCLE_WRITE
                    970:                                      | TME_BUS_CYCLE_READ));
                    971:   cycle_resp.tme_bus_cycle_port = cycle_init->tme_bus_cycle_port;
                    972: 
                    973:   /* run the cycle: */
                    974:   tme_bus_cycle_xfer(cycle_init, &cycle_resp);
                    975: 
                    976:   /* check the finishing address: */
                    977:   assert((cycle_init->tme_bus_cycle_address - 1) <= address_last);
                    978: }
                    979:   
1.1.1.3   root      980: /* given an initiator's cycle and a responder's port size, assuming
                    981:    that the responder's port fits completely within the initiator's
                    982:    port, this internal function returns the "correct" least lane for
                    983:    the responder's port, relative to the least lane of the initiator's
                    984:    port.  this requires that the initiator's lane routing use either
                    985:    TME_BUS_LANE_ABORT or TME_BUS_LANE_WARN on routings for incorrect
                    986:    lanes: */
                    987: static unsigned int
                    988: _tme_bus_cycle_xfer_resp_least_lane(const struct tme_bus_cycle *cycle_init, 
                    989:                                    unsigned int port_size_log2_resp)
                    990: {
                    991:   unsigned int port_size_resp;
                    992:   unsigned int port_lane_least_max_resp;
                    993:   unsigned int port_lane_least_resp;
                    994:   const tme_bus_lane_t *lane_routing_init;
                    995:   unsigned int lane;
                    996:   int lane_routing;
                    997: 
                    998:   /* get the responder's port size: */
                    999:   port_size_resp = (1 << port_size_log2_resp);
                   1000: 
                   1001:   /* calculate the maximum possible least lane for the responder.  we
                   1002:      require that the responder's port fit completely within the
                   1003:      initiator's port: */
                   1004:   port_lane_least_max_resp = (1 << TME_BUS_CYCLE_PORT_SIZE_LG2(cycle_init->tme_bus_cycle_port));
                   1005:   if (__tme_predict_false(port_size_resp > port_lane_least_max_resp)) {
                   1006:     abort();
                   1007:   }
                   1008:   port_lane_least_max_resp -= port_size_resp;
                   1009: 
                   1010:   /* assume that the responder will have the same least lane as the
                   1011:      initiator, and get the initiator's lane routing for that
                   1012:      responder least lane: */
                   1013:   port_lane_least_resp = 0;
                   1014:   lane_routing_init
                   1015:     = (cycle_init->tme_bus_cycle_lane_routing
                   1016:        + TME_BUS_ROUTER_INDEX(TME_BUS_CYCLE_PORT_SIZE_LG2(cycle_init->tme_bus_cycle_port),
                   1017:                              port_size_log2_resp,
                   1018:                              port_lane_least_resp));
                   1019: 
                   1020:   /* loop over all of the possible least lanes for the responder: */
                   1021:   for (;
                   1022:        port_lane_least_resp <= port_lane_least_max_resp;
                   1023:        port_lane_least_resp++) {
                   1024: 
                   1025:     /* check the routing for all of the lanes in the responder's port, starting
                   1026:        from the highest numbered lane and working down: */
                   1027:     lane = port_lane_least_resp + port_size_resp;
                   1028:     for (;;) {
                   1029:       lane = lane - 1;
                   1030:       lane_routing = lane_routing_init[lane];
                   1031: 
                   1032:       /* if this lane gets a warning or an abort, this is not the
                   1033:         correct least lane for the responder: */
                   1034:       if ((lane_routing & TME_BUS_LANE_WARN) 
                   1035:          || lane_routing == TME_BUS_LANE_ABORT) {
                   1036:        break;
                   1037:       }
                   1038: 
                   1039:       /* if we have now checked all of the lanes in the overlap between
                   1040:         initiator and responder, we've found the correct least lane for
                   1041:         the responder: */
                   1042:       if (lane == port_lane_least_resp) {
                   1043:        return (port_lane_least_resp);
                   1044:       }
                   1045:     }
                   1046: 
                   1047:     /* advance the offset into the initiator's lane routing: */
                   1048:     lane_routing_init += (1 << TME_BUS_CYCLE_PORT_SIZE_LG2(cycle_init->tme_bus_cycle_port));
                   1049:   }
                   1050: 
                   1051:   /* if we get here, the initiator doesn't allow responders of the
                   1052:      given port size: */
                   1053:   abort();
                   1054: }
                   1055:          
                   1056: /* this handles a bus cycle for a simple register device: */
                   1057: void
                   1058: tme_bus_cycle_xfer_reg(struct tme_bus_cycle *cycle_init, 
                   1059:                       void *resp_reg,
                   1060:                       unsigned int port_size_log2_resp)
                   1061: {
                   1062:   unsigned int port_lane_least_resp;
                   1063:   const tme_bus_lane_t *lane_routing_init;
                   1064:   unsigned int lane_count;
                   1065:   unsigned int lane;
                   1066:   tme_uint8_t *buffer_init;
                   1067:   tme_uint8_t *buffer_resp;
                   1068:   int lane_routing;
                   1069:   int cycle_size_init;
                   1070:   int buffer_increment_mask_init;
                   1071:   int writer_init;
                   1072: 
                   1073:   /* see if the initiator is writing: */
                   1074:   writer_init = (cycle_init->tme_bus_cycle_type == TME_BUS_CYCLE_WRITE);
                   1075:   assert (writer_init || cycle_init->tme_bus_cycle_type == TME_BUS_CYCLE_READ);
                   1076: 
                   1077:   /* get the increment mask for the initiator.  since
                   1078:      tme_bus_cycle_buffer_increment is always 1 or -1, this mask is
                   1079:      used to negate values without multiplication: */
                   1080:   if (cycle_init->tme_bus_cycle_buffer_increment == -1) {
                   1081:     buffer_increment_mask_init = -1;
                   1082:   }
                   1083:   else {
                   1084:     assert(cycle_init->tme_bus_cycle_buffer_increment == 1);
                   1085:     buffer_increment_mask_init = 0;
                   1086:   }
                   1087: 
                   1088:   /* get the least lane for the responder's port relative to the
                   1089:      initiator port's least lane, assuming that the responder's port
                   1090:      fits completely within the initiator's port and starts at the
                   1091:      "correct" least lane: */
                   1092:   port_lane_least_resp = _tme_bus_cycle_xfer_resp_least_lane(cycle_init,
                   1093:                                                             port_size_log2_resp);
                   1094: 
                   1095:   /* get the initiator's lane routing: */
                   1096:   lane_routing_init
                   1097:     = (cycle_init->tme_bus_cycle_lane_routing
                   1098:        + TME_BUS_ROUTER_INDEX(TME_BUS_CYCLE_PORT_SIZE_LG2(cycle_init->tme_bus_cycle_port),
                   1099:                              port_size_log2_resp,
                   1100:                              port_lane_least_resp));
                   1101: 
                   1102:   /* return some things to the initiator: */
                   1103:   cycle_init->tme_bus_cycle_lane_routing = lane_routing_init;
                   1104:   cycle_init->tme_bus_cycle_port = 
                   1105:     TME_BUS_CYCLE_PORT((TME_BUS_CYCLE_PORT_LANE_LEAST(cycle_init->tme_bus_cycle_port)
                   1106:                        + port_lane_least_resp),
                   1107:                       port_size_log2_resp);
                   1108: 
                   1109:   /* advance the initiator's lane routing to the first lane in the
                   1110:      responder's port: */
                   1111:   lane_routing_init += port_lane_least_resp;
                   1112: 
                   1113:   /* get the lane count: */
                   1114:   lane_count = (1 << port_size_log2_resp);
                   1115: 
                   1116:   /* get the initial pointer into the responder's register buffer.  we
                   1117:      move from lower-numbered lanes (with data of lesser significance)
                   1118:      to higher-numbered lanes (with data of more significance).  we
                   1119:      are always called with pointers to registers in host native byte
                   1120:      order, so if the host is little-endian, we start from the given
                   1121:      pointer, else we start from the other end of the register
                   1122:      buffer: */
                   1123:   buffer_resp = (((tme_uint8_t *) resp_reg)
                   1124:                 + (TME_ENDIAN_NATIVE == TME_ENDIAN_BIG
                   1125:                    ? (lane_count - 1)
                   1126:                    : 0));
                   1127: 
                   1128:   /* loop over the lanes: */
                   1129:   lane = 0;
                   1130:   cycle_size_init = 0;
                   1131:   do {
                   1132: 
                   1133:     /* get the routing for this lane: */
                   1134:     lane_routing = *(lane_routing_init++);
                   1135: 
                   1136:     /* this cannot be a TME_BUS_LANE_WARN, or a TME_BUS_LANE_ABORT, or
                   1137:        an enabled byte lane with an undefined value: */
                   1138:     assert (!(lane_routing & TME_BUS_LANE_WARN)
                   1139:            && lane_routing != TME_BUS_LANE_ABORT
                   1140:            && lane_routing != TME_BUS_LANE_UNDEF);
                   1141: 
                   1142:     /* if this is an enabled byte lane: */
                   1143:     if (__tme_predict_true(!(lane_routing & TME_BUS_LANE_ROUTE_WRITE_IGNORE))) {
                   1144: 
                   1145:       /* get a pointer into the initiator's buffer for this lane: */
                   1146:       buffer_init
                   1147:        = (cycle_init->tme_bus_cycle_buffer
                   1148:           + _TME_BUS_CYCLE_BUFFER_MULTIPLY(lane_routing,
                   1149:                                            buffer_increment_mask_init));
                   1150: 
                   1151:       /* transfer the byte: */
                   1152:       if (writer_init) {
                   1153:        *buffer_resp = *buffer_init;
                   1154:       }
                   1155:       else {
                   1156:        *buffer_init = *buffer_resp;
                   1157:       }
                   1158: 
                   1159:       /* update the cycle size for the initiator: */
                   1160:       if (lane_routing >= cycle_size_init) {
                   1161:        cycle_size_init = lane_routing + 1;
                   1162:       }
                   1163:     }
                   1164: 
                   1165:     /* update the pointer into the responder's buffer for the next lane: */
                   1166:     buffer_resp += (TME_ENDIAN_NATIVE == TME_ENDIAN_BIG ? -1 : 1);
                   1167: 
                   1168:   } while (--lane_count > 0);
                   1169: 
                   1170:   /* give the initiator feedback: */
                   1171:   cycle_init->tme_bus_cycle_size = cycle_size_init;
                   1172:   cycle_init->tme_bus_cycle_address += cycle_size_init;
                   1173:   cycle_init->tme_bus_cycle_buffer += 
                   1174:     _TME_BUS_CYCLE_BUFFER_MULTIPLY(cycle_size_init,
                   1175:                                   buffer_increment_mask_init);
                   1176: }

unix.superglobalmegacorp.com

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