Annotation of tme/ic/stp22xx/stp222x-main.c, revision 1.1.1.1

1.1       root        1: /* $Id: stp222x-main.c,v 1.4 2009/09/07 15:41:07 fredette Exp $ */
                      2: 
                      3: /* ic/stp222x-main.c - main emulation of the UPA to SBus interface
                      4:    controller (STP2220) and the UPA to PCI interface controller
                      5:    (STP2222): */
                      6: 
                      7: /*
                      8:  * Copyright (c) 2009 Matt Fredette
                      9:  * All rights reserved.
                     10:  *
                     11:  * Redistribution and use in source and binary forms, with or without
                     12:  * modification, are permitted provided that the following conditions
                     13:  * are met:
                     14:  * 1. Redistributions of source code must retain the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer.
                     16:  * 2. Redistributions in binary form must reproduce the above copyright
                     17:  *    notice, this list of conditions and the following disclaimer in the
                     18:  *    documentation and/or other materials provided with the distribution.
                     19:  * 3. All advertising materials mentioning features or use of this software
                     20:  *    must display the following acknowledgement:
                     21:  *      This product includes software developed by Matt Fredette.
                     22:  * 4. The name of the author may not be used to endorse or promote products
                     23:  *    derived from this software without specific prior written permission.
                     24:  *
                     25:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     26:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
                     27:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
                     28:  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
                     29:  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
                     30:  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
                     31:  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     32:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
                     33:  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
                     34:  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     35:  * POSSIBILITY OF SUCH DAMAGE.
                     36:  */
                     37: 
                     38: #include <tme/common.h>
                     39: _TME_RCSID("$Id: stp222x-main.c,v 1.4 2009/09/07 15:41:07 fredette Exp $");
                     40: 
                     41: /* includes: */
                     42: #include <tme/generic/bus-device.h>
                     43: #include "stp222x-impl.h"
                     44: 
                     45: /* macros: */
                     46: 
                     47: /* common register offsets: */
                     48: #define TME_STP222X_REG00_UPA_PORT_ID          (0x0000)
                     49: #define TME_STP222X_REG00_UPA_PORT_CONFIG      (0x0008)
                     50: #define TME_STP222X_REG00_CSR                  (0x0010)
                     51:                                                /* 0x0018 unused */
                     52: #define TME_STP222X_REG00_ECC_CONTROL          (0x0020)
                     53:                                                /* 0x0028 unused */
                     54: #define TME_STP222X_REG00_UE_AFSR              (0x0030)
                     55: #define TME_STP222X_REG00_UE_AFAR              (0x0038)
                     56: #define TME_STP222X_REG00_CE_AFSR              (0x0040)
                     57: #define TME_STP222X_REG00_CE_AFAR              (0x0048)
                     58: #define TME_STP222X_REG01_PM_CR                        (0x0100)
                     59: #define TME_STP222X_REG01_PM_COUNT             (0x0108)
                     60: 
                     61: /* the control/status register: */
                     62: #define TME_STP222X_CSR_IMPL                   ((((tme_uint64_t) 2) << 63) - (((tme_uint64_t) 1) << 60))
                     63: #define TME_STP222X_CSR_VER                    ((((tme_uint64_t) 2) << 59) - (((tme_uint64_t) 1) << 56))
                     64: #define TME_STP222X_CSR_MID                    ((((tme_uint64_t) 2) << 55) - (((tme_uint64_t) 1) << 51))
                     65: #define TME_STP222X_CSR_IGN                    ((((tme_uint64_t) 2) << 50) - (((tme_uint64_t) 1) << 46))
                     66: #define TME_STP222X_CSR_APCKEN                 (1 << 3)
                     67: #define TME_STP222X_CSR_APERR                  (1 << 2)
                     68: #define TME_STP222X_CSR_IAP                    (1 << 1)
                     69: #define TME_STP222X_CSR_MODE                   (1 << 0)
                     70: 
                     71: /* stp2220-specific registers: */
                     72: #define TME_STP2220_REG20_SBUS_CSR             (0x2000)
                     73:                                                /* 0x2028 unused */
                     74: #define TME_STP2220_REG20_SBUS_AFSR            (0x2010)
                     75: #define TME_STP2220_REG20_SBUS_AFAR            (0x2018)
                     76: #define TME_STP2220_REG20_SBUS_CONFIG(n)       (0x2020 + (TME_STP222X_REG_SIZE * (n)))
                     77: 
                     78: /* the stp2220 slot size: */
                     79: #define TME_STP2220_SLOT_SIZE                  (256 * 1024 * 1024)
                     80: 
                     81: /* this gives the raw stp2220 address for a slot and offset: */
                     82: #define TME_STP2220_SBUS_ADDRESS(slot, offset) (((slot) * TME_STP2220_SLOT_SIZE) + (offset))
                     83: 
                     84: /* reset states: */
                     85: #define TME_STP222X_RESET_STATE_NEGATED                (0)
                     86: #define TME_STP222X_RESET_STATE_NEGATING       (TME_STP222X_RESET_STATE_NEGATED + TME_STP222X_CONN_NULL)
                     87: #define TME_STP222X_RESET_STATE_ASSERTED       (TME_STP222X_RESET_STATE_NEGATING + 1)
                     88: #define TME_STP222X_RESET_STATE_ASSERTING      (TME_STP222X_RESET_STATE_ASSERTED + TME_STP222X_CONN_NULL)
                     89: 
                     90: /* globals: */
                     91: 
                     92: /* the simple 64-bit register bus router: */
                     93: static const tme_bus_lane_t _tme_stp222x_bus_router_regs[sizeof(tme_uint64_t)] = {
                     94:   TME_BUS_LANE_ROUTE(0),
                     95:   TME_BUS_LANE_ROUTE(1),
                     96:   TME_BUS_LANE_ROUTE(2),
                     97:   TME_BUS_LANE_ROUTE(3),
                     98:   TME_BUS_LANE_ROUTE(4),
                     99:   TME_BUS_LANE_ROUTE(5),
                    100:   TME_BUS_LANE_ROUTE(6),
                    101:   TME_BUS_LANE_ROUTE(7)
                    102: };
                    103: 
                    104: /* the STP2220 mapping from obio slot and offset to IDI: */
                    105: static const struct {
                    106:   tme_uint32_t _tme_stp2220_obio_slot;
                    107:   tme_uint32_t _tme_stp2220_obio_offset;
                    108:   tme_uint32_t _tme_stp2220_obio_idi;
                    109: } _tme_stp2220_obios[] = {
                    110:   { TME_STP2220_SLOT_AUDIO,    0x0000000, TME_STP2220_IDI_AUDIO, },
                    111:   { TME_STP2220_SLOT_MACIO,    0x8800000, TME_STP222X_IDI_SCSI },
                    112:   { TME_STP2220_SLOT_MACIO,    0x8c00000, TME_STP222X_IDI_ETHER },
                    113:   { TME_STP2220_SLOT_MACIO,    0xc800000, TME_STP222X_IDI_BPP },
                    114:   { TME_STP2220_SLOT_SLAVIO,   0x1100000, TME_STP2220_IDI_ZS0_ZS1 },
                    115:   { TME_STP2220_SLOT_SLAVIO,   0x1000000, TME_STP2220_IDI_ZS0_ZS1 },
                    116:   { TME_STP2220_SLOT_SLAVIO,   0x1400000, TME_STP2220_IDI_FD },
                    117: };
                    118: 
                    119: /* this converts an I/O connection into a connection index: */
                    120: static tme_uint32_t
                    121: _tme_stp222x_io_conn_index(const struct tme_stp222x *stp222x,
                    122:                           const struct tme_bus_connection *io_conn_bus)
                    123: {
                    124:   tme_uint32_t connid;
                    125:   tme_uint32_t conn_index;
                    126: 
                    127:   /* this must be an I/O connection: */
                    128:   assert (io_conn_bus
                    129:          != stp222x->tme_stp222x.tme_stp22xx_conns[TME_STP222X_CONN_UPA].tme_stp22xx_conn_bus);
                    130: 
                    131:   /* get the connection id: */
                    132:   connid = io_conn_bus->tme_bus_connection.tme_connection_id;
                    133: 
                    134:   /* if this is a card connection: */
                    135:   if ((connid
                    136:        & TME_STP222X_CONNID_TYPE)
                    137:       == TME_STP222X_CONNID_TYPE_CARD) {
                    138: 
                    139:     /* if this is an stp2220: */
                    140:     if (TME_STP222X_IS_2220(stp222x)) {
                    141: 
                    142:       /* assume that this is the first master connection for this
                    143:         card, which uses the card's primary master connection
                    144:         index: */
                    145:       conn_index = TME_FIELD_MASK_EXTRACTU(connid, TME_STP2220_CONNID_CARD_WHICH);
                    146: 
                    147:       /* if this is an alternate connection for the card: */
                    148:       if (connid & TME_STP2220_CONNID_CARD_ALTERNATE) {
                    149: 
                    150:        /* starting from the first alternate master connection index
                    151:           for this card and moving forward, search all remaining
                    152:           connection indices: */
                    153:        conn_index
                    154:          = (TME_STP2220_SLOTS_CARD
                    155:             + (connid & TME_STP2220_CONNID_CARD_WHICH));
                    156:        for (; stp222x->tme_stp222x.tme_stp22xx_conns[conn_index].tme_stp22xx_conn_bus != io_conn_bus; ) {
                    157:          conn_index++;
                    158:          assert (conn_index < stp222x->tme_stp222x_slave_conn_index_next);
                    159:        }
                    160:       }
                    161:     }
                    162: 
                    163:     /* otherwise, this is an stp2222: */
                    164:     else {
                    165:       abort();
                    166:     }
                    167:   }
                    168: 
                    169:   /* otherwise, this is an obio connection id: */
                    170:   else {
                    171: 
                    172:     /* assume that this is an obio short connection id, and get the
                    173:        connection index: */
                    174:     conn_index = TME_FIELD_MASK_EXTRACTU(connid, TME_STP222X_CONNID_OBIO_SHORT_CONN_WHICH);
                    175: 
                    176:     /* if this is an obio long connection id: */
                    177:     if ((connid
                    178:         & TME_STP222X_CONNID_OBIO_TYPE)
                    179:        == TME_STP222X_CONNID_OBIO_TYPE_LONG) {
                    180: 
                    181:       /* search all connection indices: */
                    182:       conn_index = 0;
                    183:       for (; stp222x->tme_stp222x.tme_stp22xx_conns[conn_index].tme_stp22xx_conn_bus != io_conn_bus; ) {
                    184:        conn_index++;
                    185:        assert (conn_index < stp222x->tme_stp222x_slave_conn_index_next);
                    186:       }
                    187:     }
                    188:   }
                    189: 
                    190:   assert (stp222x->tme_stp222x.tme_stp22xx_conns[conn_index].tme_stp22xx_conn_bus == io_conn_bus);
                    191:   return (conn_index);
                    192: }
                    193: 
                    194: /* this converts an I/O connection and interrupt signal into an
                    195:    IDI: */
                    196: static tme_uint32_t
                    197: _tme_stp222x_io_idi(const struct tme_stp222x *stp222x,
                    198:                    const struct tme_bus_connection *io_conn_bus,
                    199:                    unsigned int signal_int)
                    200: {
                    201:   tme_uint32_t connid;
                    202:   tme_uint32_t idi;
                    203:   tme_uint32_t idi_addend;
                    204: 
                    205:   /* this must be an I/O connection: */
                    206:   assert (io_conn_bus
                    207:          != stp222x->tme_stp222x.tme_stp22xx_conns[TME_STP222X_CONN_UPA].tme_stp22xx_conn_bus);
                    208: 
                    209:   /* get the connection id: */
                    210:   connid = io_conn_bus->tme_bus_connection.tme_connection_id;
                    211: 
                    212:   /* if this is a card connection: */
                    213:   if ((connid
                    214:        & TME_STP222X_CONNID_TYPE)
                    215:       == TME_STP222X_CONNID_TYPE_CARD) {
                    216: 
                    217:     /* if this is an stp2220, bits 1..2 of a card connection id are
                    218:        the card (slot) number, which are bits 3..4 of the connection's
                    219:        base IDI.  otherwise, this is an stp2222, and bits 1..3 of a
                    220:        card connection id are the bus and slot number, which are bits
                    221:        2..4 of the connection's base IDI.  we take advantage of this
                    222:        to quickly make the base IDI: */
                    223: #if TME_STP222X_CONNID_TYPE != (0x1 << 0)
                    224: #error "TME_STP222X_CONNID_TYPE changed"
                    225: #endif
                    226: #if TME_STP222X_CONNID_TYPE_CARD != 0
                    227: #error "TME_STP222X_CONNID_TYPE_CARD changed"
                    228: #endif
                    229: #if (TME_STP2222_CONNID_BUS_WHICH + TME_STP2222_CONNID_DEVICE_WHICH) != (0x7 << 1)
                    230: #error "TME_STP2222_CONNID_BUS_WHICH or TME_STP2222_CONNID_DEVICE_WHICH changed"
                    231: #endif
                    232: #if TME_STP2220_CONNID_CARD_WHICH != (0x3 << 1)
                    233: #error "TME_STP2220_CONN_CARD_WHICH changed"
                    234: #endif
                    235:     idi = connid << 1;
                    236:     if (TME_STP222X_IS_2220(stp222x)) {
                    237:       idi <<= 1;
                    238:     }
                    239:     idi %= TME_STP222X_IDI0_OBIO;
                    240: 
                    241:     /* the interrupt signal can't be unspecified: */
                    242:     assert (signal_int != TME_BUS_SIGNAL_INT_UNSPEC);
                    243: 
                    244:     /* convert the interrupt signal into an IDI addend: */
                    245:     idi_addend = TME_BUS_SIGNAL_INDEX_INT(signal_int);
                    246: 
                    247:     /* the IDI addend must be within range: */
                    248:     assert (idi_addend
                    249:            < (TME_STP222X_IS_2220(stp222x)
                    250:               ? TME_SBUS_SLOT_INTS
                    251:               : TME_PCI_SLOT_INTS));
                    252:     
                    253:     /* add in the IDI addend: */
                    254:     idi += idi_addend;
                    255:   }
                    256: 
                    257:   /* otherwise, this is an obio connection: */
                    258:   else {
                    259: 
                    260:     /* this must be a obio short connection id: */
                    261:     assert ((connid
                    262:             & TME_STP222X_CONNID_OBIO_TYPE)
                    263:            == TME_STP222X_CONNID_OBIO_TYPE_SHORT);
                    264: 
                    265:     /* get the connection's base IDI: */
                    266:     idi = TME_FIELD_MASK_EXTRACTU(connid, TME_STP222X_CONNID_OBIO_SHORT_IDI);
                    267: 
                    268:     /* if the interrupt signal is specified: */
                    269:     if (signal_int != TME_BUS_SIGNAL_INT_UNSPEC) {
                    270: 
                    271:       /* the audio connection is the only obio connection allowed to
                    272:         specify its interrupt signal - zero is used for record, one
                    273:         for playback: */
                    274:       assert (signal_int == TME_BUS_SIGNAL_INT(0)
                    275:              || signal_int == TME_BUS_SIGNAL_INT(1));
                    276:       if (!TME_STP222X_IS_2220(stp222x)) {
                    277:        assert (idi == TME_STP2220_IDI_AUDIO);
                    278: 
                    279:        /* nothing to do */
                    280:       }
                    281:       else {
                    282: #if TME_STP2222_IDI_AUDIO_PLAYBACK != (TME_STP2222_IDI_AUDIO_RECORD + 1)
                    283: #error "TME_STP2222_IDI_AUDIO_ values changed"
                    284: #endif
                    285:        assert (idi == TME_STP2222_IDI_AUDIO_RECORD);
                    286:        idi += TME_BUS_SIGNAL_INDEX_INT(signal_int);
                    287:       }
                    288:     }
                    289:   }
                    290: 
                    291:   return (idi);
                    292: }
                    293: 
                    294: /* this converts an address into an address space: */
                    295: static tme_uint32_t
                    296: _tme_stp222x_lookup_address(const struct tme_stp222x *stp222x,
                    297:                            tme_bus_addr64_t address,
                    298:                            tme_bus_addr32_t *_region_size_m1)
                    299: {
                    300:   tme_bus_addr32_t region_size_m1;
                    301:   unsigned int aspace_i;
                    302:   tme_uint32_t address_16_47;
                    303: 
                    304:   /* if this is an stp2220: */
                    305:   if (TME_STP222X_IS_2220(stp222x)) {
                    306: 
                    307:     /* only the upper half of our UPA address space is mapped to the
                    308:        SBus address space: */
                    309:     region_size_m1 = 0xffffffff;
                    310:     aspace_i
                    311:       = (address <= region_size_m1
                    312:         ? TME_STP222X_ASPACE_NULL
                    313:         : TME_STP2220_ASPACE_SBUS);
                    314:   }
                    315: 
                    316:   /* otherwise, this is an stp2222: */
                    317:   else {
                    318: 
                    319:     /* get bits 16..47 of the UPA address: */
                    320:     address_16_47 = (address >> 16);
                    321:     assert (address_16_47 == (address >> 16));
                    322: 
                    323:     /* if this is a PCI bus memory space: */
                    324:     if (address_16_47 >= 0x10000) {
                    325:       assert (address_16_47 <= 0x1ffff);
                    326:       region_size_m1 = 0x7fffffff;
                    327:       aspace_i
                    328:        = TME_STP2222_ASPACE_PCI_MEMORY(((address_16_47 & 0x8000) == 0)
                    329:                                        == !TME_STP2222_BOOT_BUS(stp222x));
                    330:     }
                    331: 
                    332:     /* otherwise, if this is a PCI bus I/O space: */
                    333:     else if ((address_16_47 | 1) == 0x00201) {
                    334:       region_size_m1 = 0xffff;
                    335:       aspace_i = TME_STP2222_ASPACE_PCI_IO(address_16_47 & 1);
                    336:     }
                    337: 
                    338:     /* otherwise, if this is PCI configuration space: */
                    339:     else if (address_16_47 == 0x00100) {
                    340:       region_size_m1 = 0xffffff;
                    341:       aspace_i = TME_STP2222_ASPACE_PCI_CONFIGURATION;
                    342:     }
                    343: 
                    344:     /* otherwise, this address is in the register space: */
                    345:     else {
                    346:       region_size_m1 = 0xffff;
                    347:       aspace_i = TME_STP222X_ASPACE_NULL;
                    348:     }
                    349:   }
                    350: 
                    351:   /* return the region size and address space: */
                    352:   *_region_size_m1 = region_size_m1;
                    353:   return (aspace_i);
                    354: }
                    355: 
                    356: /* the 0x00 register group register handler: */
                    357: static void
                    358: _tme_stp222x_reg00_regs(struct tme_stp222x *stp222x,
                    359:                        struct tme_stp222x_reg *reg)
                    360: {
                    361:   
                    362:   /* if this is a write: */
                    363:   if (reg->tme_stp222x_reg_write) {
                    364:     
                    365:     /* dispatch on the register: */
                    366:     switch (TME_STP222X_REGGROUP_INDEX(reg->tme_stp222x_reg_address)) {
                    367:     case TME_STP222X_REGGROUP_INDEX(TME_STP222X_REG00_UPA_PORT_CONFIG):
                    368:       stp222x->tme_stp222x_upa_port_config
                    369:        = (reg->tme_stp222x_reg_value
                    370:           & TME_UPA_PORT_CONFIG_SCIQ0);
                    371:       break;
                    372:     case TME_STP222X_REGGROUP_INDEX(TME_STP222X_REG00_CSR):
                    373:       stp222x->tme_stp222x_csr
                    374:        = ((stp222x->tme_stp222x_csr | ~TME_STP222X_CSR_APCKEN)
                    375:           & (reg->tme_stp222x_reg_value ^ TME_STP222X_CSR_APCKEN));
                    376:       tme_stp222x_mdu_ign_update(stp222x,
                    377:                                 TME_FIELD_MASK_EXTRACTU(stp222x->tme_stp222x_csr,
                    378:                                                         TME_STP222X_CSR_IGN));
                    379:       break;
                    380:     case TME_STP222X_REGGROUP_INDEX(TME_STP222X_REG00_ECC_CONTROL):
                    381:       stp222x->tme_stp222x_ecc_control = (reg->tme_stp222x_reg_value >> 61);
                    382:       break;
                    383:     case TME_STP222X_REGGROUP_INDEX(TME_STP222X_REG00_UPA_PORT_ID):
                    384:     case TME_STP222X_REGGROUP_INDEX(TME_STP222X_REG00_UE_AFSR):
                    385:     case TME_STP222X_REGGROUP_INDEX(TME_STP222X_REG00_UE_AFAR):
                    386:     case TME_STP222X_REGGROUP_INDEX(TME_STP222X_REG00_CE_AFSR):
                    387:     case TME_STP222X_REGGROUP_INDEX(TME_STP222X_REG00_CE_AFAR):
                    388:       break;
                    389:     default:
                    390:       return;
                    391:     }
                    392:   }
                    393: 
                    394:   /* otherwise, this is a read: */
                    395:   else {
                    396: 
                    397:     /* dispatch on the register: */
                    398:     switch (TME_STP222X_REGGROUP_INDEX(reg->tme_stp222x_reg_address)) {
                    399:     case TME_STP222X_REGGROUP_INDEX(TME_STP222X_REG00_UPA_PORT_ID):
                    400:       reg->tme_stp222x_reg_value
                    401:        = (TME_UPA_PORT_ID_COOKIE
                    402:           + !TME_UPA_PORT_ID_ECC_NOT_VALID
                    403:           + !TME_UPA_PORT_ID_ONEREAD
                    404:           + !TME_UPA_PORT_ID_PINT_RDQ
                    405:           + (8 * _TME_FIELD_MASK_FACTOR(TME_UPA_PORT_ID_PREQ_DQ))
                    406:           + (2 * _TME_FIELD_MASK_FACTOR(TME_UPA_PORT_ID_PREQ_RQ))
                    407:           + ((TME_UPA_UPACAP_MASTER
                    408:               + !TME_UPA_UPACAP_CACHEMASTER
                    409:               + !TME_UPA_UPACAP_SLAVE_INT_L
                    410:               + TME_UPA_UPACAP_INTERRUPTMASTER
                    411:               + !TME_UPA_UPACAP_HANDLERSLAVE)
                    412:              * _TME_FIELD_MASK_FACTOR(TME_UPA_PORT_ID_UPACAP))
                    413:           + ((TME_STP222X_IS_2220(stp222x)
                    414:               ? 0xef07
                    415:               : 0x1954)
                    416:              * _TME_FIELD_MASK_FACTOR(TME_UPA_PORT_ID_ID)));
                    417:       break;
                    418:     case TME_STP222X_REGGROUP_INDEX(TME_STP222X_REG00_UPA_PORT_CONFIG):
                    419:       reg->tme_stp222x_reg_value = stp222x->tme_stp222x_upa_port_config;
                    420:       break;
                    421:     case TME_STP222X_REGGROUP_INDEX(TME_STP222X_REG00_CSR):
                    422:       reg->tme_stp222x_reg_value
                    423:        = ((stp222x->tme_stp222x_csr
                    424:            & (TME_STP222X_CSR_MID
                    425:               | TME_STP222X_CSR_IGN
                    426:               | TME_STP222X_CSR_APCKEN
                    427:               | TME_STP222X_CSR_APERR
                    428:               | TME_STP222X_CSR_IAP
                    429:               | TME_STP222X_CSR_MODE))
                    430:           + (TME_STP222X_IS_2220(stp222x)
                    431:              ? ((0x0 * _TME_FIELD_MASK_FACTOR(TME_STP222X_CSR_IMPL))
                    432:                 + (0x1 * _TME_FIELD_MASK_FACTOR(TME_STP222X_CSR_VER)))
                    433:              : ((0x0 * _TME_FIELD_MASK_FACTOR(TME_STP222X_CSR_IMPL))
                    434:                 + (0x0 * _TME_FIELD_MASK_FACTOR(TME_STP222X_CSR_VER)))));
                    435:       break;
                    436:     case TME_STP222X_REGGROUP_INDEX(TME_STP222X_REG00_ECC_CONTROL):
                    437:       reg->tme_stp222x_reg_value
                    438:        = (((tme_uint64_t) stp222x->tme_stp222x_ecc_control)
                    439:           << 61);
                    440:       break;
                    441:     case TME_STP222X_REGGROUP_INDEX(TME_STP222X_REG00_UE_AFSR):
                    442:     case TME_STP222X_REGGROUP_INDEX(TME_STP222X_REG00_UE_AFAR):
                    443:     case TME_STP222X_REGGROUP_INDEX(TME_STP222X_REG00_CE_AFSR):
                    444:     case TME_STP222X_REGGROUP_INDEX(TME_STP222X_REG00_CE_AFAR):
                    445:       reg->tme_stp222x_reg_value = 0;
                    446:       break;
                    447:     default:
                    448:       return;
                    449:     }
                    450:   }
                    451: 
                    452:   /* this register access has been completed: */
                    453:   reg->tme_stp222x_reg_completed = TRUE;
                    454: }
                    455: 
                    456: /* the stp2220 SBus register handler: */
                    457: static void
                    458: _tme_stp2220_sbus_regs(struct tme_stp222x *stp222x,
                    459:                       struct tme_stp222x_reg *reg)
                    460: {
                    461:   tme_uint64_t mask_w;
                    462:   tme_uint64_t mask_ro;
                    463:   tme_uint64_t zero;
                    464:   tme_uint64_t *_value;
                    465: 
                    466:   /* assume that all bits of the register are writable: */
                    467:   mask_w = 0 - (tme_uint64_t) 1;
                    468: 
                    469:   /* assume that all read-only bits of the register are zero: */
                    470:   mask_ro = 0;
                    471: 
                    472:   /* make a dummy zero register: */
                    473:   zero = 0;
                    474: 
                    475:   /* if this is the SBus control/status register: */
                    476:   if (reg->tme_stp222x_reg_address == TME_STP2220_REG20_SBUS_CSR) {
                    477:     _value = &stp222x->tme_stp2220_sbus_csr;
                    478:     mask_w
                    479:       = (TME_BIT(10)           /* shortens PIO access latency */
                    480:         + TME_BIT(8)           /* enables interrupts for SBus errors */
                    481:         + TME_BIT(5)           /* enables DVMA for slot 15 */
                    482:         + TME_BIT(4)           /* enables DVMA for slot 14 */
                    483:         + 0xf);                /* enables DVMA for slots 0..3 */
                    484:   }
                    485: 
                    486:   /* otherwise, if this is the SBus AFSR or AFAR: */
                    487:   else if (reg->tme_stp222x_reg_address == TME_STP2220_REG20_SBUS_AFSR
                    488:           || reg->tme_stp222x_reg_address == TME_STP2220_REG20_SBUS_AFAR) {
                    489:     _value = &zero;
                    490:   }
                    491: 
                    492:   /* otherwise, if this is an SBus slot configuration register: */
                    493:   else if ((reg->tme_stp222x_reg_address
                    494:            >= TME_STP2220_REG20_SBUS_CONFIG(0))
                    495:           && (reg->tme_stp222x_reg_address
                    496:               <= TME_STP2220_REG20_SBUS_CONFIG(TME_STP2220_SLOTS_CARD + TME_STP2220_SLOTS_OBIO - 1))) {
                    497:     _value
                    498:       = (&stp222x->tme_stp2220_sbus_config_card
                    499:         [(reg->tme_stp222x_reg_address
                    500:           - TME_STP2220_REG20_SBUS_CONFIG(0))
                    501:          / TME_STP222X_REG_SIZE]);
                    502:     mask_w
                    503:       = (TME_BIT(14)           /* enables extended transfers */
                    504:         + TME_BIT(4)           /* enables 64-byte bursts */
                    505:         + TME_BIT(3)           /* enables 32-byte bursts */
                    506:         + TME_BIT(2)           /* enables 16-byte bursts */
                    507:         + TME_BIT(1)           /* enables 8-byte bursts */
                    508:         );
                    509:   }
                    510: 
                    511:   /* otherwise, this is an unknown register: */
                    512:   else {
                    513:     return;
                    514:   }
                    515: 
                    516:   /* if this is a write: */
                    517:   if (reg->tme_stp222x_reg_write) {
                    518:     *_value = reg->tme_stp222x_reg_value & mask_w;
                    519:   }
                    520:   
                    521:   /* otherwise, this is a read: */
                    522:   else {
                    523:     reg->tme_stp222x_reg_value = *_value | mask_ro;
                    524:   }
                    525: 
                    526:   /* this register access has been completed: */
                    527:   reg->tme_stp222x_reg_completed = TRUE;
                    528: }
                    529: 
                    530: /* this completes a bus operation between master and slave: */
                    531: #define _tme_stp222x_complete_master tme_stp22xx_complete_master
                    532: 
                    533: /* this completes a reset assertion or negation: */
                    534: static void
                    535: _tme_stp222x_complete_reset(struct tme_stp22xx *stp22xx,
                    536:                            struct tme_completion *completion,
                    537:                            void *arg)
                    538: {
                    539:   struct tme_stp222x *stp222x;
                    540:   tme_uint32_t reset_state;
                    541: 
                    542:   /* recover our data structure: */
                    543:   stp222x = (struct tme_stp222x *) stp22xx;
                    544: 
                    545:   /* get the next reset state: */
                    546:   reset_state = stp222x->tme_stp222x_reset_state - 1;
                    547: 
                    548:   /* if we have finished asserting RESET on the I/O bus, and
                    549:      the UPA bus reset signal is negated: */
                    550:   if (reset_state == TME_STP222X_RESET_STATE_ASSERTED
                    551:       && stp222x->tme_stp222x_reset_level == TME_BUS_SIGNAL_LEVEL_NEGATED) {
                    552: 
                    553:     /* start negating RESET on the I/O bus: */
                    554:     reset_state = TME_STP222X_RESET_STATE_NEGATING;
                    555:   }
                    556: 
                    557:   /* update the reset state: */
                    558:   stp222x->tme_stp222x_reset_state = reset_state;
                    559: 
                    560:   /* unused: */
                    561:   completion = 0;
                    562:   arg = 0;
                    563: }
                    564: 
                    565: /* this completes a bus request assertion or negation: */
                    566: static void
                    567: _tme_stp222x_complete_br(struct tme_stp22xx *stp22xx,
                    568:                         struct tme_completion *completion,
                    569:                         void *arg)
                    570: {
                    571:   struct tme_stp222x *stp222x;
                    572: 
                    573:   /* recover our data structure: */
                    574:   stp222x = (struct tme_stp222x *) stp22xx;
                    575: 
                    576:   /* our bus request has been flipped: */
                    577:   stp222x->tme_stp222x_br = !stp222x->tme_stp222x_br;
                    578: 
                    579:   /* unused: */
                    580:   completion = 0;
                    581:   arg = 0;
                    582: }
                    583: 
                    584: /* this completes a bus grant: */
                    585: #define _tme_stp222x_complete_bg tme_stp22xx_complete_bg
                    586: 
                    587: /* this calls out a bus signal to a connection: */
                    588: #define _tme_stp222x_callout_signal(stp222x, conn_index, signal, completion_handler) \
                    589:   tme_stp22xx_callout_signal(&(stp222x)->tme_stp222x, conn_index, signal, completion_handler)
                    590: 
                    591: /* the run function: */
                    592: static void
                    593: _tme_stp222x_run(struct tme_stp22xx *stp22xx)
                    594: {
                    595:   struct tme_stp222x *stp222x;
                    596:   unsigned int reset_state;
                    597:   unsigned int io_conn_index;
                    598:   unsigned int master_conn_index;
                    599:   tme_uint32_t io_brs;
                    600: 
                    601:   /* recover our data structure: */
                    602:   stp222x = (struct tme_stp222x *) stp22xx;
                    603: 
                    604:   /* loop forever: */
                    605:   for (;;) {
                    606: 
                    607:     /* if we need to assert reset to another I/O connection: */
                    608:     reset_state = stp222x->tme_stp222x_reset_state;
                    609:     if (reset_state > TME_STP222X_RESET_STATE_ASSERTED) {
                    610: 
                    611:       /* assert reset to the next I/O connection: */
                    612:       io_conn_index = reset_state - (TME_STP222X_RESET_STATE_ASSERTED + 1);
                    613:       _tme_stp222x_callout_signal(stp222x,
                    614:                                  io_conn_index,
                    615:                                  (TME_BUS_SIGNAL_RESET
                    616:                                   | TME_BUS_SIGNAL_EDGE
                    617:                                   | TME_BUS_SIGNAL_LEVEL_ASSERTED),
                    618:                                  _tme_stp222x_complete_reset);
                    619:       continue;
                    620:     }
                    621: 
                    622:     /* if there is a current master: */
                    623:     master_conn_index = stp222x->tme_stp222x_master_conn_index;
                    624:     if (master_conn_index != TME_STP222X_CONN_NULL) {
                    625:       assert (master_conn_index < TME_STP222X_CONN_SLAVE0);
                    626: 
                    627:       /* if the current master is still requesting the bus: */
                    628:       if (stp222x->tme_stp222x_io_brs & (1 << master_conn_index)) { 
                    629: 
                    630:        /* stop now.  we can't do anything else until the current
                    631:           master releases the bus: */
                    632:        break;
                    633:       }
                    634: 
                    635:       /* there should be no master completion pending: */
                    636:       assert (stp222x->tme_stp222x.tme_stp22xx_master_completion == NULL);
                    637: 
                    638:       /* there is no current master: */
                    639:       stp222x->tme_stp222x_master_conn_index = TME_STP222X_CONN_NULL;
                    640: 
                    641:       /* negate bus grant to the former master: */
                    642:       _tme_stp222x_callout_signal(stp222x,
                    643:                                  master_conn_index,
                    644:                                  (TME_BUS_SIGNAL_BG
                    645:                                   | TME_BUS_SIGNAL_EDGE
                    646:                                   | TME_BUS_SIGNAL_LEVEL_NEGATED),
                    647:                                  tme_stp22xx_complete_nop);
                    648:       continue;
                    649:     }
                    650: 
                    651:     /* we need the UPA bus if an I/O connection is requesting the bus,
                    652:        or if we have an interrupt to dispatch, or if we have a
                    653:        streaming cache to flush.  if our UPA bus request line doesn't
                    654:        reflect whether we need the UPA bus: */
                    655:     if (!stp222x->tme_stp222x_br
                    656:        == (stp222x->tme_stp222x_io_brs != 0
                    657: #if TME_STP222X_MDU_BUFFER_COUNT != 2
                    658: #error "TME_STP222X_MDU_BUFFER_COUNT changed"
                    659: #endif
                    660:            || (stp222x->tme_stp222x_mdu_dispatch_imr[0] != 0 /* !TME_STP222X_MDU_IMR_V */
                    661:                && stp222x->tme_stp222x_mdu_dispatch_state[0] == 0) /* TME_STP222X_MDU_DISPATCH_NOW */
                    662:            || (stp222x->tme_stp222x_mdu_dispatch_imr[1] != 0 /* !TME_STP222X_MDU_IMR_V */
                    663:                && stp222x->tme_stp222x_mdu_dispatch_state[1] == 0) /* TME_STP222X_MDU_DISPATCH_NOW */
                    664: #if TME_STP222X_STC_COUNT != 2
                    665: #error "TME_STP222X_STC_COUNT changed"
                    666: #endif
                    667:            || stp222x->tme_stp222x_stcs[0].tme_stp222x_stc_pgflush
                    668:            || stp222x->tme_stp222x_stcs[1].tme_stp222x_stc_pgflush
                    669:            )) {
                    670: 
                    671:       /* assert or negate our bus request on the UPA bus: */
                    672:       _tme_stp222x_callout_signal(stp222x,
                    673:                                  TME_STP222X_CONN_UPA,
                    674:                                  (TME_BUS_SIGNAL_BR
                    675:                                   | TME_BUS_SIGNAL_EDGE
                    676:                                   | (stp222x->tme_stp222x_br
                    677:                                      ? TME_BUS_SIGNAL_LEVEL_NEGATED
                    678:                                      : TME_BUS_SIGNAL_LEVEL_ASSERTED)),
                    679:                                  _tme_stp222x_complete_br);
                    680:       continue;
                    681:     }
                    682: 
                    683:     /* if we need to negate reset to another I/O connection: */
                    684:     reset_state = stp222x->tme_stp222x_reset_state;
                    685:     if (reset_state > TME_STP222X_RESET_STATE_NEGATED
                    686:        && reset_state < TME_STP222X_RESET_STATE_ASSERTED) {
                    687: 
                    688:       /* negate reset to the next I/O connection: */
                    689:       io_conn_index = reset_state - (TME_STP222X_RESET_STATE_NEGATED + 1);
                    690:       _tme_stp222x_callout_signal(stp222x,
                    691:                                  io_conn_index,
                    692:                                  (TME_BUS_SIGNAL_RESET
                    693:                                   | TME_BUS_SIGNAL_EDGE
                    694:                                   | TME_BUS_SIGNAL_LEVEL_NEGATED),
                    695:                                  _tme_stp222x_complete_reset);
                    696:       continue;
                    697:     }
                    698: 
                    699:     /* if we don't own the UPA bus: */
                    700:     if (!stp222x->tme_stp222x_bg) {
                    701: 
                    702:       /* stop now.  we can't do anything else until we own the UPA
                    703:         bus: */
                    704:       break;
                    705:     }
                    706: 
                    707:     /* dispatch any interrupt: */
                    708:     if (tme_stp222x_mdu_dispatch(stp222x)) {
                    709:       continue;
                    710:     }
                    711: 
                    712:     /* flush any streaming cache: */
                    713:     if (tme_stp222x_stc_flush(stp222x)) {
                    714:       continue;
                    715:     }
                    716: 
                    717:     /* if one or more I/O connections are requesting the bus: */
                    718:     io_brs = stp222x->tme_stp222x_io_brs;
                    719:     if (io_brs != 0) {
                    720: 
                    721:       /* get the connection index for the next master: */
                    722:       /* XXX FIXME - should we do something fair here? */
                    723:       for (master_conn_index = 0;
                    724:           (io_brs & 1) == 0;
                    725:           io_brs >>= 1, master_conn_index++);
                    726: 
                    727:       /* set the pending master: */
                    728:       stp222x->tme_stp222x_master_conn_index_pending = master_conn_index;
                    729: 
                    730:       /* assert bus grant to the current master: */
                    731:       _tme_stp222x_callout_signal(stp222x,
                    732:                                  master_conn_index,
                    733:                                  (TME_BUS_SIGNAL_BG
                    734:                                   | TME_BUS_SIGNAL_EDGE
                    735:                                   | TME_BUS_SIGNAL_LEVEL_ASSERTED),
                    736:                                  _tme_stp222x_complete_bg);
                    737:       continue;
                    738:     }
                    739: 
                    740:     /* no other callouts are needed: */
                    741:     break;
                    742:   }
                    743: }
                    744: 
                    745: /* this handles a bus signal: */
                    746: static void
                    747: _tme_stp222x_signal(struct tme_bus_connection *conn_bus,
                    748:                    unsigned int signal,
                    749:                    struct tme_completion *completion)
                    750: {
                    751:   struct tme_stp222x *stp222x;
                    752:   tme_uint32_t level;
                    753:   tme_uint32_t io_conn_index;
                    754:   tme_uint32_t br_mask;
                    755:   tme_uint32_t idi;
                    756: 
                    757:   /* enter: */
                    758:   stp222x = tme_stp222x_enter_bus(conn_bus);
                    759: 
                    760:   /* get the level.  this must be an edge: */
                    761:   assert (signal & TME_BUS_SIGNAL_EDGE);
                    762:   level = signal - TME_BUS_SIGNAL_EDGE;
                    763:   signal = TME_BUS_SIGNAL_WHICH(signal);
                    764:   level ^= signal;
                    765: 
                    766:   /* if this bus signal is on the UPA connection: */
                    767:   if (conn_bus == stp222x->tme_stp222x.tme_stp22xx_conns[TME_STP222X_CONN_UPA].tme_stp22xx_conn_bus) {
                    768: 
                    769:     /* if this is the bus grant signal: */
                    770:     if (signal == TME_BUS_SIGNAL_BG) {
                    771: 
                    772:       /* mark our bus grant as either asserted or negated: */
                    773:       assert (level == TME_BUS_SIGNAL_LEVEL_NEGATED
                    774:              || level == TME_BUS_SIGNAL_LEVEL_ASSERTED);
                    775:       stp222x->tme_stp222x_bg = (level == TME_BUS_SIGNAL_LEVEL_ASSERTED);
                    776:     }
                    777: 
                    778:     /* otherwise, this must be reset signal: */
                    779:     else {
                    780:       assert (signal == TME_BUS_SIGNAL_RESET);
                    781: 
                    782:       /* update the level of the UPA reset signal: */
                    783:       stp222x->tme_stp222x_reset_level = level;
                    784: 
                    785:       /* if the UPA reset signal is asserted: */
                    786:       if (level == TME_BUS_SIGNAL_LEVEL_ASSERTED) {
                    787: 
                    788:        /* start asserting RESET on the I/O bus: */
                    789:        stp222x->tme_stp222x_reset_state = TME_STP222X_RESET_STATE_ASSERTING;
                    790:       }
                    791: 
                    792:       /* otherwise, the UPA reset signal must be negated: */
                    793:       else {
                    794:        assert (level == TME_BUS_SIGNAL_LEVEL_NEGATED);
                    795: 
                    796:        /* if RESET is currently asserted on the I/O bus, start
                    797:           negating it: */
                    798:        assert (stp222x->tme_stp222x_reset_state >= TME_STP222X_RESET_STATE_ASSERTED);
                    799:        if (stp222x->tme_stp222x_reset_state == TME_STP222X_RESET_STATE_ASSERTED) {
                    800:          stp222x->tme_stp222x_reset_state = TME_STP222X_RESET_STATE_NEGATING;
                    801:        }
                    802:       }
                    803:     }
                    804:   }
                    805: 
                    806:   /* otherwise, this bus signal is on an I/O connection: */
                    807:   else {
                    808: 
                    809:     /* if this is the bus request signal: */
                    810:     if (signal == TME_BUS_SIGNAL_BR) {
                    811: 
                    812:       /* get this I/O connection's bus request mask: */
                    813:       io_conn_index = _tme_stp222x_io_conn_index(stp222x, conn_bus);
                    814:       assert (io_conn_index < TME_STP222X_CONN_SLAVE0);
                    815:       br_mask = (1 << io_conn_index);
                    816: 
                    817:       /* mark this caller's bus request line as either asserted or
                    818:         negated: */
                    819:       assert (level == TME_BUS_SIGNAL_LEVEL_NEGATED
                    820:              || level == TME_BUS_SIGNAL_LEVEL_ASSERTED);
                    821:       stp222x->tme_stp222x_io_brs
                    822:        = ((stp222x->tme_stp222x_io_brs
                    823:            | br_mask)
                    824:           & (level == TME_BUS_SIGNAL_LEVEL_ASSERTED
                    825:              ? 0
                    826:              : ~br_mask));
                    827:     }
                    828: 
                    829:     /* otherwise, this must be an interrupt signal: */
                    830:     else {
                    831:       assert (signal == TME_BUS_SIGNAL_INT_UNSPEC
                    832:              || TME_BUS_SIGNAL_IS_INT(signal));
                    833: 
                    834:       /* get the IDI: */
                    835:       idi = _tme_stp222x_io_idi(stp222x, conn_bus, signal);
                    836: 
                    837:       /* update the interrupt concentrator: */
                    838:       tme_stp222x_mdu_intcon(stp222x, idi, level);
                    839:     }
                    840:   }
                    841: 
                    842:   /* leave: */
                    843:   tme_stp222x_completion_validate(stp222x, completion);
                    844:   tme_stp222x_leave(stp222x);
                    845: }
                    846: 
                    847: /* this handles a bus cycle: */
                    848: static void
                    849: _tme_stp222x_cycle(struct tme_bus_connection *master_conn_bus,
                    850:                   struct tme_bus_cycle *master_cycle,
                    851:                   tme_uint32_t *_master_fast_cycle_types,
                    852:                   struct tme_completion *master_completion)
                    853: {
                    854:   struct tme_stp222x *stp222x;
                    855:   tme_bus_addr64_t slave_address;
                    856:   tme_uint32_t aspace_i;
                    857:   unsigned int slave_conn_index;
                    858:   tme_bus_addr32_t region_size_m1;
                    859:   struct tme_stp222x_reg reg;
                    860:   tme_uint32_t reggroup;
                    861: 
                    862:   /* enter: */
                    863:   stp222x = tme_stp222x_enter_master_bus(master_conn_bus);
                    864: 
                    865:   /* convert the master's address into an address space, slave
                    866:      connection index and address: */
                    867:   slave_address = master_cycle->tme_bus_cycle_address;
                    868:   aspace_i
                    869:     = _tme_stp222x_lookup_address(stp222x,
                    870:                                  slave_address,
                    871:                                  &region_size_m1);
                    872:   slave_address &= region_size_m1;
                    873:   slave_conn_index
                    874:     = (aspace_i == TME_STP222X_ASPACE_NULL
                    875:        ? TME_STP222X_CONN_NULL
                    876:        : tme_stp222x_aspace_lookup(stp222x,
                    877:                                   aspace_i,
                    878:                                   &slave_address));
                    879:   master_cycle->tme_bus_cycle_address = slave_address;
                    880: 
                    881:   /* dispatch on the address space: */
                    882:   switch (aspace_i) {
                    883: 
                    884:   case TME_STP2222_ASPACE_PCI_CONFIGURATION:
                    885:     assert (!TME_STP222X_IS_2220(stp222x));
                    886: #if 0
                    887:     master_cycle->tme_bus_cycle_type |= TME_PCI_CYCLE_CONFIGURATION;
                    888: #endif
                    889:     abort();
                    890: 
                    891:   case TME_STP2222_ASPACE_PCI_IO(0):
                    892:   case TME_STP2222_ASPACE_PCI_IO(1):
                    893:     assert (!TME_STP222X_IS_2220(stp222x));
                    894: #if 0
                    895:     master_cycle->tme_bus_cycle_type |= TME_PCI_CYCLE_IO;
                    896: #endif
                    897:     abort();
                    898: 
                    899:   case TME_STP2220_ASPACE_SBUS:
                    900:     assert (TME_STP222X_IS_2220(stp222x));
                    901:     break;
                    902: 
                    903:   default:
                    904:     assert (!TME_STP222X_IS_2220(stp222x));
                    905:     assert (aspace_i == TME_STP2222_ASPACE_PCI_MEMORY(0)
                    906:            || aspace_i == TME_STP2222_ASPACE_PCI_MEMORY(1));
                    907:     abort();
                    908: 
                    909:   case TME_STP222X_ASPACE_NULL:
                    910: 
                    911:     /* if this isn't an aligned 64-bit access: */
                    912:     if (__tme_predict_false((slave_address % TME_STP222X_REG_SIZE) != 0
                    913:                            || master_cycle->tme_bus_cycle_size != TME_STP222X_REG_SIZE)) {
                    914:       abort();
                    915:     }
                    916: 
                    917:     /* NB: read the _tme_stp103x_bus_port() comment about bus routing
                    918:        information coming out of the CPU: */
                    919:     /* replace the bus cycle routing information: */
                    920:     assert (TME_STP222X_REG_SIZE == (1 << TME_BUS64_LOG2));
                    921:     master_cycle->tme_bus_cycle_port = TME_BUS_CYCLE_PORT(0, TME_BUS64_LOG2);
                    922:     master_cycle->tme_bus_cycle_lane_routing
                    923:       = (_tme_stp222x_bus_router_regs
                    924:         - TME_BUS_ROUTER_INDEX(TME_BUS64_LOG2, TME_BUS64_LOG2, 0));
                    925: 
                    926:     /* set the register address, poisoning it if it's too big for the
                    927:        structure: */
                    928:     reg.tme_stp222x_reg_address = slave_address;
                    929:     if (reg.tme_stp222x_reg_address != slave_address) {
                    930:       reg.tme_stp222x_reg_address = 0xffff;
                    931:     }
                    932: 
                    933:     /* if this is a write: */
                    934:     reg.tme_stp222x_reg_write = (master_cycle->tme_bus_cycle_type == TME_BUS_CYCLE_WRITE);
                    935:     if (reg.tme_stp222x_reg_write) {
                    936: 
                    937:       /* get value being written: */
                    938:       tme_bus_cycle_xfer_memory(master_cycle,
                    939:                                ((tme_uint8_t *) &reg.tme_stp222x_reg_value) - slave_address,
                    940:                                slave_address + sizeof(tme_uint64_t) - 1);
                    941:       reg.tme_stp222x_reg_value = tme_betoh_u64(reg.tme_stp222x_reg_value);
                    942:     }
                    943: 
                    944:     /* otherwise, this must be a read: */
                    945:     else if (__tme_predict_false(master_cycle->tme_bus_cycle_type != TME_BUS_CYCLE_READ)) {
                    946:       abort();
                    947:     }
                    948: 
                    949:     /* assume that this register access won't be completed: */
                    950:     reg.tme_stp222x_reg_completed = FALSE;
                    951: 
                    952:     /* dispatch on the register group: */
                    953:     reggroup = TME_STP222X_REGGROUP_WHICH(reg.tme_stp222x_reg_address);
                    954:     switch (reggroup) {
                    955: 
                    956:     case 0x00:
                    957:       _tme_stp222x_reg00_regs(stp222x, &reg);
                    958:       break;
                    959: 
                    960:     case 0x01:
                    961:       switch (TME_STP222X_REGGROUP_INDEX(reg.tme_stp222x_reg_address)) {
                    962:       case TME_STP222X_REGGROUP_INDEX(TME_STP222X_REG01_PM_CR):
                    963:        abort();
                    964:       case TME_STP222X_REGGROUP_INDEX(TME_STP222X_REG01_PM_COUNT):
                    965:        abort();
                    966:       default:
                    967:        break;
                    968:       }
                    969:       break;
                    970: 
                    971:     case 0x24:
                    972:     case 0x02:
                    973:       if (reggroup 
                    974:          == (TME_STP222X_IS_2220(stp222x)
                    975:              ? 0x24
                    976:              : 0x02)) {
                    977:        tme_stp222x_iommu_regs(stp222x, &reg);
                    978:       }
                    979:       break;
                    980: 
                    981:     case 0x2c:
                    982:     case 0x0c:
                    983:     case 0x30:
                    984:     case 0x10:
                    985:     case 0x1a:
                    986:     case 0x60:
                    987:     case 0x80:
                    988:       tme_stp222x_mdu_regs_imr_retry(stp222x, &reg);
                    989:       break;
                    990: 
                    991:     case 0x20:
                    992:       if (TME_STP222X_IS_2220(stp222x)) {
                    993:        _tme_stp2220_sbus_regs(stp222x, &reg);
                    994:       }
                    995:       break;
                    996: 
                    997:     case 0x34:
                    998:     case 0x14:
                    999:     case 0x38:
                   1000:     case 0x18:
                   1001:       tme_stp222x_mdu_regs_clear(stp222x, &reg);
                   1002:       break;
                   1003: 
                   1004:     case 0x3c:
                   1005:     case 0x1c:
                   1006:       if ((reggroup < 0x30) == !TME_STP222X_IS_2220(stp222x)) {
                   1007:        tme_stp222x_timer_regs(stp222x, &reg);
                   1008:       }
                   1009:       break;
                   1010: 
                   1011:     case 0x28:
                   1012:       tme_stp222x_stc_regs(stp222x, 0, &reg);
                   1013:       break;
                   1014: 
                   1015:     case 0x40:
                   1016:       abort();
                   1017: 
                   1018:     case 0x48:
                   1019:       if (TME_STP222X_IS_2220(stp222x)) {
                   1020:         tme_stp222x_mdu_regs_diag(stp222x, &reg);
                   1021:       }
                   1022:       else {
                   1023:        tme_stp222x_stc_regs(stp222x, 1, &reg);
                   1024:       }
                   1025:       break;
                   1026: 
                   1027:     case 0xa0:
                   1028:       abort();
                   1029: 
                   1030:     case 0x44:
                   1031:     case 0x45:
                   1032:     case 0x46:
                   1033:     case 0xa4:
                   1034:     case 0xa5:
                   1035:     case 0xa6:
                   1036:       if ((reggroup >= 0xa0) == !TME_STP222X_IS_2220(stp222x)) {
                   1037:        tme_stp222x_iommu_regs_diag(stp222x, &reg);
                   1038:       }
                   1039:       break;
                   1040: 
                   1041:     case 0xa8:
                   1042:       if (!TME_STP222X_IS_2220(stp222x)) {
                   1043:        tme_stp222x_mdu_regs_diag(stp222x, &reg);
                   1044:       }
                   1045:       break;
                   1046: 
                   1047:     default:
                   1048:       if (TME_STP222X_IS_2220(stp222x)
                   1049:          ? (reggroup >= 0x50
                   1050:             && reggroup <= 0x59)
                   1051:          : (reggroup >= 0xb0
                   1052:             && reggroup <= 0xb9)) {
                   1053:        tme_stp222x_stc_regs_diag(stp222x, 0, &reg);
                   1054:       }
                   1055:       else if (!TME_STP222X_IS_2220(stp222x)
                   1056:               && reggroup >= 0xc0
                   1057:               && reggroup <= 0xc9) {
                   1058:        tme_stp222x_stc_regs_diag(stp222x, 1, &reg);
                   1059:       }
                   1060:       break;
                   1061:     }
                   1062: 
                   1063:     /* if this register access was not completed: */
                   1064:     if (__tme_predict_false(!reg.tme_stp222x_reg_completed)) {
                   1065: 
                   1066:       tme_log(TME_STP222X_LOG_HANDLE(stp222x), 100, TME_OK,
                   1067:              (TME_STP222X_LOG_HANDLE(stp222x),
                   1068:               _("unknown[0x%04x] %s 0x%" TME_PRIx64),
                   1069:               reg.tme_stp222x_reg_address,
                   1070:               (reg.tme_stp222x_reg_write
                   1071:                ? "<-"
                   1072:                : "->"),
                   1073:               reg.tme_stp222x_reg_value));
                   1074:     }
                   1075: 
                   1076:     /* if this was a read: */
                   1077:     if (!reg.tme_stp222x_reg_write) {
                   1078: 
                   1079:       /* return the value: */
                   1080:       reg.tme_stp222x_reg_value = tme_htobe_u64(reg.tme_stp222x_reg_value);
                   1081:       tme_bus_cycle_xfer_memory(master_cycle,
                   1082:                                ((tme_uint8_t *) &reg.tme_stp222x_reg_value) - slave_address,
                   1083:                                slave_address + sizeof(tme_uint64_t) - 1);
                   1084:     }
                   1085: 
                   1086:     /* complete the cycle: */
                   1087:     master_completion->tme_completion_error = TME_OK;
                   1088:     tme_stp222x_completion_validate(stp222x, master_completion);
                   1089:     master_completion = NULL;
                   1090:     *_master_fast_cycle_types = 0;
                   1091:     break;
                   1092:   }
                   1093: 
                   1094:   /* if we didn't complete the cycle ourselves: */
                   1095:   if (master_completion != NULL) {
                   1096: 
                   1097:     /* start this cycle: */
                   1098:     assert (stp222x->tme_stp222x_master_completion == NULL);
                   1099:     stp222x->tme_stp222x_master_completion = &master_completion;
                   1100: 
                   1101:     /* run the slave bus cycle: */
                   1102:     tme_stp22xx_slave_cycle(master_conn_bus,
                   1103:                            slave_conn_index,
                   1104:                            master_cycle,
                   1105:                            _master_fast_cycle_types,
                   1106:                            &master_completion);
                   1107:   }
                   1108:  
                   1109:   /* leave: */
                   1110:   tme_stp222x_leave(stp222x);
                   1111: }
                   1112: 
                   1113: /* this receives an interrupt: */
                   1114: static void
                   1115: _tme_stp222x_interrupt(struct tme_upa_bus_connection *master_conn_upa,
                   1116:                       tme_uint32_t slave_mid,
                   1117:                       const tme_uint64_t *data,
                   1118:                       struct tme_completion *master_completion)
                   1119: {
                   1120:   abort();
                   1121: }
                   1122: 
                   1123: /* this fills a TLB entry: */
                   1124: static void
                   1125: _tme_stp222x_tlb_fill(struct tme_bus_connection *agent_conn_bus,
                   1126:                      struct tme_bus_tlb *tlb,
                   1127:                      tme_bus_addr_t agent_address_wider,
                   1128:                      unsigned int cycle_type)
                   1129: {
                   1130:   struct tme_stp222x *stp222x;
                   1131:   tme_bus_addr64_t slave_address;
                   1132:   tme_uint32_t aspace_i;
                   1133:   tme_uint32_t slave_conn_index;
                   1134:   tme_bus_addr32_t region_size_m1;
                   1135:   tme_bus_addr64_t agent_address;
                   1136:   struct tme_bus_tlb tlb_mapping;
                   1137: 
                   1138:   /* enter: */
                   1139:   stp222x = tme_stp222x_enter_bus(agent_conn_bus);
                   1140: 
                   1141:   /* convert the agent's address into an address space, slave
                   1142:      connection index and address: */
                   1143:   slave_address = agent_address_wider;
                   1144:   aspace_i
                   1145:     = _tme_stp222x_lookup_address(stp222x,
                   1146:                                  agent_address_wider,
                   1147:                                  &region_size_m1);
                   1148:   slave_address &= region_size_m1;
                   1149:   slave_conn_index
                   1150:     = (aspace_i == TME_STP222X_ASPACE_NULL
                   1151:        ? TME_STP222X_CONN_NULL
                   1152:        : tme_stp222x_aspace_lookup(stp222x,
                   1153:                                   aspace_i,
                   1154:                                   &slave_address));
                   1155: 
                   1156:   /* fill this TLB entry: */
                   1157:   tme_stp22xx_tlb_fill(agent_conn_bus,
                   1158:                       tlb,
                   1159:                       slave_conn_index,
                   1160:                       slave_address,
                   1161:                       cycle_type);
                   1162: 
                   1163:   /* leave: */
                   1164:   tme_stp222x_leave(stp222x);
                   1165: 
                   1166:   /* map the filled TLB entry: */
                   1167:   agent_address = ~ (tme_bus_addr64_t) region_size_m1;
                   1168:   agent_address &= agent_address_wider;
                   1169:   tlb_mapping.tme_bus_tlb_addr_first = agent_address;
                   1170:   agent_address |= region_size_m1;
                   1171:   tlb_mapping.tme_bus_tlb_addr_last = agent_address;
                   1172: #if TME_STP22XX_BUS_TRANSITION
                   1173:   tlb_mapping.tme_bus_tlb_cycles_ok = (TME_BUS_CYCLE_READ | TME_BUS_CYCLE_WRITE);
                   1174: #endif /* TME_STP22XX_BUS_TRANSITION */
                   1175:   tme_bus_tlb_map(tlb, slave_address, &tlb_mapping, agent_address_wider);
                   1176: }
                   1177: 
                   1178: #if TME_STP22XX_BUS_TRANSITION
                   1179: 
                   1180: /* this is the bus signal transition glue: */
                   1181: static int
                   1182: _tme_stp222x_signal_transition(struct tme_bus_connection *conn_bus,
                   1183:                               unsigned int signal)
                   1184: {
                   1185:   struct tme_completion completion_buffer;
                   1186:   tme_completion_init(&completion_buffer);
                   1187:   _tme_stp222x_signal(conn_bus,
                   1188:                      signal,
                   1189:                      &completion_buffer);
                   1190:   return (TME_OK);
                   1191: }
                   1192: #define _tme_stp222x_signal _tme_stp222x_signal_transition
                   1193: 
                   1194: /* this is the bus cycle transition glue: */
                   1195: static int
                   1196: _tme_stp222x_cycle_transition(void *_master_conn_bus,
                   1197:                              struct tme_bus_cycle *master_cycle)
                   1198: {
                   1199:   struct tme_completion completion_buffer;
                   1200:   struct tme_stp222x *stp222x;
                   1201:   struct tme_bus_connection *master_conn_bus;
                   1202:   tme_uint32_t master_fast_cycle_types;
                   1203: 
                   1204:   tme_completion_init(&completion_buffer);
                   1205: 
                   1206:   master_conn_bus = (struct tme_bus_connection *) _master_conn_bus;
                   1207:   stp222x = (struct tme_stp222x *) master_conn_bus->tme_bus_connection.tme_connection_element->tme_element_private;
                   1208:   (master_conn_bus == stp222x->tme_stp222x.tme_stp22xx_conns[TME_STP222X_CONN_UPA].tme_stp22xx_conn_bus
                   1209:    ? _tme_stp222x_cycle
                   1210:    : tme_stp222x_iommu_cycle)
                   1211:     (master_conn_bus,
                   1212:      master_cycle,
                   1213:      &master_fast_cycle_types,
                   1214:      &completion_buffer);
                   1215:   return (completion_buffer.tme_completion_error);
                   1216: }
                   1217: 
                   1218: /* the bus TLB fill transition glue: */
                   1219: static int
                   1220: _tme_stp222x_tlb_fill_transition(struct tme_bus_connection *agent_conn_bus,
                   1221:                                 struct tme_bus_tlb *tlb,
                   1222:                                 tme_bus_addr_t agent_address_wider,
                   1223:                                 unsigned int cycle_type)
                   1224: {
                   1225:   struct tme_stp222x *stp222x;
                   1226: 
                   1227:   stp222x = (struct tme_stp222x *) agent_conn_bus->tme_bus_connection.tme_connection_element->tme_element_private;
                   1228:   (agent_conn_bus == stp222x->tme_stp222x.tme_stp22xx_conns[TME_STP222X_CONN_UPA].tme_stp22xx_conn_bus
                   1229:    ? _tme_stp222x_tlb_fill
                   1230:    : tme_stp222x_iommu_tlb_fill)
                   1231:     (agent_conn_bus,
                   1232:      tlb,
                   1233:      agent_address_wider,
                   1234:      cycle_type);
                   1235: 
                   1236:   /* we always handle any slow cycles: */
                   1237:   tlb->tme_bus_tlb_cycles_ok |= cycle_type;
                   1238:   tlb->tme_bus_tlb_addr_offset = 0;
                   1239:   tlb->tme_bus_tlb_addr_shift = 0;
                   1240:   tlb->tme_bus_tlb_cycle = _tme_stp222x_cycle_transition;
                   1241:   tlb->tme_bus_tlb_cycle_private = agent_conn_bus;
                   1242:   assert (tlb->tme_bus_tlb_fault_handler_count == 0);
                   1243: 
                   1244:   return (TME_OK);
                   1245: }
                   1246: #define _tme_stp222x_tlb_fill _tme_stp222x_tlb_fill_transition
                   1247: #define tme_stp222x_iommu_tlb_fill _tme_stp222x_tlb_fill_transition
                   1248: 
                   1249: #endif /* TME_STP22XX_BUS_TRANSITION */
                   1250: 
                   1251: /* the connection scorer: */
                   1252: static int
                   1253: _tme_stp222x_connection_score(struct tme_connection *conn,
                   1254:                              unsigned int *_score)
                   1255: {
                   1256:   struct tme_bus_connection *conn_bus;
                   1257:   struct tme_stp222x *stp222x;
                   1258:   unsigned int score;
                   1259:   struct tme_upa_bus_connection *conn_upa_other;
                   1260:   struct tme_bus_connection *conn_bus_other;
                   1261: 
                   1262:   /* recover the bus connection: */
                   1263:   conn_bus = (struct tme_bus_connection *) conn;
                   1264: 
                   1265:   /* enter: */
                   1266:   stp222x = tme_stp222x_enter_bus(conn_bus);
                   1267: 
                   1268:   /* assume that this connection is useless: */
                   1269:   score = 0;
                   1270: 
                   1271:   /* dispatch on the connection type: */
                   1272:   conn_upa_other = (struct tme_upa_bus_connection *) conn->tme_connection_other;
                   1273:   conn_bus_other = (struct tme_bus_connection *) conn->tme_connection_other;
                   1274:   switch (conn->tme_connection_type) {
                   1275:   
                   1276:     /* this must be a UPA controller, and not another agent: */
                   1277:   case TME_CONNECTION_BUS_UPA:
                   1278:     if (conn_upa_other->tme_upa_bus_connection.tme_bus_tlb_set_add != NULL
                   1279:        && conn_upa_other->tme_upa_bus_interrupt != NULL) {
                   1280:       score = 10;
                   1281:     }
                   1282:     break;
                   1283: 
                   1284:     /* this must be a bus device: */
                   1285:   case TME_CONNECTION_BUS_GENERIC:
                   1286:     if (conn_bus_other->tme_bus_tlb_set_add == NULL) {
                   1287:       score = 1;
                   1288:     }
                   1289:     break;
                   1290: 
                   1291:   default: abort();
                   1292:   }
                   1293: 
                   1294:   /* leave: */
                   1295:   tme_stp222x_leave(stp222x);
                   1296:   *_score = score;
                   1297:   return (TME_OK);
                   1298: }
                   1299: 
                   1300: /* this makes a new connection: */
                   1301: static int
                   1302: _tme_stp222x_connection_make(struct tme_connection *conn, unsigned int state)
                   1303: {
                   1304:   struct tme_upa_bus_connection *conn_upa;
                   1305:   struct tme_bus_connection *conn_bus;
                   1306:   struct tme_stp222x *stp222x;
                   1307:   unsigned int conn_index;
                   1308:   tme_uint32_t slot;
                   1309:   tme_bus_addr32_t offset;
                   1310:   int slaveonly;
                   1311:   tme_uint32_t connid;
                   1312:   unsigned int obio_i;
                   1313: 
                   1314:   /* ignore a half-connection: */
                   1315:   if (state == TME_CONNECTION_HALF) {
                   1316:     return (TME_OK);
                   1317:   }
                   1318: 
                   1319:   /* recover the bus connection: */
                   1320:   conn_upa = (struct tme_upa_bus_connection *) conn;
                   1321:   conn_bus = (struct tme_bus_connection *) conn;
                   1322: 
                   1323:   /* enter: */
                   1324:   stp222x = tme_stp222x_enter_bus(conn_bus);
                   1325: 
                   1326:   /* if this is the UPA bus connection: */
                   1327:   if (conn->tme_connection_type == TME_CONNECTION_BUS_UPA) {
                   1328: 
                   1329:     /* save the UPA bus connection: */
                   1330:     stp222x->tme_stp222x.tme_stp22xx_conns[TME_STP222X_CONN_UPA].tme_stp22xx_conn_upa = conn_upa;
                   1331:   }
                   1332: 
                   1333:   /* otherwise, this is a device bus connection: */
                   1334:   else {
                   1335: 
                   1336:     /* if this is an stp2220: */
                   1337:     if (TME_STP222X_IS_2220(stp222x)) {
                   1338: 
                   1339:       /* split the temporary connection id into the slot, offset, and
                   1340:         slaveonly flag: */
                   1341:       offset = conn->tme_connection_id;
                   1342:       slot = (offset / TME_STP2220_SLOT_SIZE);
                   1343:       offset %= TME_STP2220_SLOT_SIZE;
                   1344:       slaveonly
                   1345:        = (slot > TME_STP2220_SLOT_CARD(TME_STP2220_SLOTS_CARD - 1)
                   1346:           && slot < TME_STP2220_SLOT_OBIO(0));
                   1347:       if (slaveonly) {
                   1348:        slot ^= TME_STP2220_SLOT_CARD(TME_STP2220_SLOTS_CARD);
                   1349:       }
                   1350: 
                   1351:       /* if this is a card: */
                   1352:       if (slot >= TME_STP2220_SLOT_CARD(0)
                   1353:          && slot <= TME_STP2220_SLOT_CARD(TME_STP2220_SLOTS_CARD - 1)) {
                   1354: 
                   1355:        /* start the card connection ID: */
                   1356:        connid = TME_STP222X_CONNID_TYPE_CARD;
                   1357:        TME_FIELD_MASK_DEPOSITU(connid,
                   1358:                                TME_STP2220_CONNID_CARD_WHICH,
                   1359:                                (slot - TME_STP2220_SLOT_CARD(0)));
                   1360:        TME_FIELD_MASK_DEPOSITU(connid,
                   1361:                                TME_STP2220_CONNID_CARD_OFFSET,
                   1362:                                offset);
                   1363: 
                   1364:        /* if this is a slave connection: */
                   1365:        if (slaveonly) {
                   1366: 
                   1367:          /* this connection will use the next slave connection index,
                   1368:             which is an alternate connection index: */
                   1369:          conn_index = stp222x->tme_stp222x_slave_conn_index_next++;
                   1370:          connid |= TME_STP2220_CONNID_CARD_ALTERNATE;
                   1371:        }
                   1372: 
                   1373:        else {
                   1374: 
                   1375:          /* assume that this is the first master connection for this
                   1376:             card, which will use the card's primary master connection
                   1377:             index: */
                   1378:          conn_index = TME_FIELD_MASK_EXTRACTU(connid, TME_STP2220_CONNID_CARD_WHICH);
                   1379: 
                   1380:          /* if this is not the first master connection for this card: */
                   1381:          if (stp222x->tme_stp222x.tme_stp22xx_conns[conn_index].tme_stp22xx_conn_bus != NULL) {
                   1382: 
                   1383:            /* this connection will use an alternate master connection
                   1384:               index: */
                   1385:            connid |= TME_STP2220_CONNID_CARD_ALTERNATE;
                   1386: 
                   1387:            /* starting from the first alternate master connection
                   1388:               index for this card and moving forward, search the
                   1389:               remaining master connection indices for a free one: */
                   1390:            /* NB: this means if you have an SBus card with a lot of
                   1391:               different masters on it, you should put it in the last
                   1392:               card slot, to save the preferred alternate master
                   1393:               connection indices for the other card slots: */
                   1394:            conn_index
                   1395:              = (TME_STP2220_SLOTS_CARD
                   1396:                 + (connid & TME_STP2220_CONNID_CARD_WHICH));
                   1397:            for (; stp222x->tme_stp222x.tme_stp22xx_conns[conn_index].tme_stp22xx_conn_bus != NULL;) {
                   1398:              if (++conn_index == TME_STP222X_CONN_SLAVE0) {
                   1399:                abort();
                   1400:              }
                   1401:            }
                   1402:          }
                   1403:        }
                   1404:       }
                   1405: 
                   1406:       /* otherwise, this is an obio device: */
                   1407:       else {
                   1408: 
                   1409:        /* if this is the slave I/O slot, force slaveonly: */
                   1410:        if (slot == TME_STP2220_SLOT_SLAVIO) {
                   1411:          slaveonly = TRUE;
                   1412:        }
                   1413: 
                   1414:        /* if this is a slave connection: */
                   1415:        if (slaveonly) {
                   1416: 
                   1417:          /* this connection will use the next slave connection index: */
                   1418:          conn_index = stp222x->tme_stp222x_slave_conn_index_next++;
                   1419:        }
                   1420: 
                   1421:        /* otherwise, this is a master connection: */
                   1422:        else {
                   1423: 
                   1424:          /* starting from the last master connection index and
                   1425:             moving backwards, search for a free one: */
                   1426:          conn_index = TME_STP222X_CONN_SLAVE0 - 1;
                   1427:          for (; stp222x->tme_stp222x.tme_stp22xx_conns[conn_index].tme_stp22xx_conn_bus != NULL;) {
                   1428:            if (conn_index-- == 0) {
                   1429:              abort();
                   1430:            }
                   1431:          }
                   1432:        }
                   1433: 
                   1434:        /* assume that this is not a known obio connection, and make
                   1435:           the obio long connection id: */
                   1436:        connid
                   1437:          = (TME_STP222X_CONNID_TYPE_OBIO
                   1438:             | TME_STP222X_CONNID_OBIO_TYPE_LONG);
                   1439:        TME_FIELD_MASK_DEPOSITU(connid,
                   1440:                                TME_STP222X_CONNID_OBIO_LONG_WHICH,
                   1441:                                (slot - TME_STP2220_SLOT_OBIO(0)));
                   1442:        TME_FIELD_MASK_DEPOSITU(connid,
                   1443:                                TME_STP222X_CONNID_OBIO_LONG_OFFSET,
                   1444:                                offset);
                   1445: 
                   1446:        /* if this is a known obio connection: */
                   1447:        for (obio_i = 0; obio_i < TME_ARRAY_ELS(_tme_stp2220_obios); obio_i++) {
                   1448:          if (_tme_stp2220_obios[obio_i]._tme_stp2220_obio_slot == slot
                   1449:              && _tme_stp2220_obios[obio_i]._tme_stp2220_obio_offset == offset) {
                   1450: 
                   1451:            /* make the obio short connection id: */
                   1452:            connid
                   1453:              = (TME_STP222X_CONNID_TYPE_OBIO
                   1454:                 | TME_STP222X_CONNID_OBIO_TYPE_SHORT);
                   1455:            TME_FIELD_MASK_DEPOSITU(connid,
                   1456:                                    TME_STP222X_CONNID_OBIO_SHORT_IDI,
                   1457:                                    _tme_stp2220_obios[obio_i]._tme_stp2220_obio_idi);
                   1458:            TME_FIELD_MASK_DEPOSITU(connid,
                   1459:                                    TME_STP222X_CONNID_OBIO_SHORT_CONN_WHICH,
                   1460:                                    conn_index);
                   1461:            break;
                   1462:          }
                   1463:        }
                   1464:       }
                   1465: 
                   1466:       /* save the SBus offset for this connection: */
                   1467:       assert (conn_index < TME_STP222X_CONN_NULL);
                   1468:       stp222x->tme_stp2220_conn_offset[conn_index] = TME_STP2220_SBUS_ADDRESS(slot, offset);
                   1469:     }
                   1470: 
                   1471:     /* otherwise, this is an stp222x: */
                   1472:     else {
                   1473:       abort();
                   1474:     }
                   1475: 
                   1476:     /* update this connection's id: */
                   1477:     conn->tme_connection_id = connid;
                   1478:       
                   1479:     /* add this connection to the list: */
                   1480:     assert (conn_index < TME_STP222X_CONN_NULL);
                   1481:     if (conn->tme_connection_type == TME_CONNECTION_BUS_GENERIC) {
                   1482:       assert (TME_STP222X_IS_2220(stp222x));
                   1483:       stp222x->tme_stp222x.tme_stp22xx_conns[conn_index].tme_stp22xx_conn_bus = conn_bus;
                   1484:     }
                   1485:     else {
                   1486:       assert (FALSE);
                   1487:     }
                   1488: 
                   1489:     /* rebuild the address spaces: */
                   1490:     if (tme_stp222x_aspaces_rebuild(stp222x)) {
                   1491:       abort();
                   1492:     }
                   1493:   }
                   1494: 
                   1495:   /* leave: */
                   1496:   tme_stp222x_leave(stp222x);
                   1497:   return (TME_OK);
                   1498: }
                   1499: 
                   1500: /* this breaks a connection: */
                   1501: static int 
                   1502: _tme_stp222x_connection_break(struct tme_connection *conn, unsigned int state)
                   1503: {
                   1504:   abort();
                   1505: }
                   1506: 
                   1507: /* this makes new connection sides: */
                   1508: static int
                   1509: _tme_stp222x_connections_new(struct tme_element *element,
                   1510:                             const char * const *args,
                   1511:                             struct tme_connection **_conns,
                   1512:                             char **_output)
                   1513: {
                   1514:   int rc;
                   1515:   struct tme_stp222x *stp222x;
                   1516:   struct tme_upa_bus_connection *conn_upa;
                   1517:   struct tme_bus_connection *conn_bus;
                   1518:   struct tme_connection *conn;
                   1519:   tme_bus_addr_t slot_wider;
                   1520:   tme_bus_addr_t offset_wider;
                   1521:   int slaveonly;
                   1522: 
                   1523:   /* assume that we will succeed: */
                   1524:   rc = TME_OK;
                   1525: 
                   1526:   /* recover our data structure: */
                   1527:   stp222x = (struct tme_stp222x *) element->tme_element_private;
                   1528: 
                   1529:   /* lock the mutex: */
                   1530:   tme_mutex_lock(&stp222x->tme_stp222x.tme_stp22xx_mutex);
                   1531: 
                   1532:   /* if we have no arguments, this is the UPA connection: */
                   1533:   if (args[1] == NULL) {
                   1534: 
                   1535:     /* if we already have the UPA connection: */
                   1536:     if (stp222x->tme_stp222x.tme_stp22xx_conns[TME_STP222X_CONN_UPA].tme_stp22xx_conn_upa != NULL) {
                   1537:       rc = EEXIST;
                   1538:     }
                   1539: 
                   1540:     /* otherwise, we don't have a UPA connection yet: */
                   1541:     else {
                   1542: 
                   1543:       /* create a UPA connection: */
                   1544:       conn_upa = tme_new0(struct tme_upa_bus_connection, 1);
                   1545:       conn_upa->tme_upa_bus_connection.tme_bus_connection.tme_connection_type = TME_CONNECTION_BUS_UPA;
                   1546:       conn_upa->tme_upa_bus_interrupt = _tme_stp222x_interrupt;
                   1547: 
                   1548:       /* fill in the generic bus connection: */
                   1549:       conn_bus = &conn_upa->tme_upa_bus_connection;
                   1550:       conn_bus->tme_bus_signals_add = NULL;
                   1551:       conn_bus->tme_bus_signal = _tme_stp222x_signal;
                   1552:       conn_bus->tme_bus_intack = NULL;
                   1553:       conn_bus->tme_bus_tlb_set_add = NULL;
                   1554:       conn_bus->tme_bus_tlb_fill = _tme_stp222x_tlb_fill;
                   1555: 
                   1556:       /* fill in the generic connection: */
                   1557:       conn = &conn_bus->tme_bus_connection;
                   1558:       conn->tme_connection_score = _tme_stp222x_connection_score;
                   1559:       conn->tme_connection_make = _tme_stp222x_connection_make;
                   1560:       conn->tme_connection_break = _tme_stp222x_connection_break;
                   1561: 
                   1562:       /* add in this connection side possibility: */
                   1563:       conn->tme_connection_next = *_conns;
                   1564:       *_conns = conn;
                   1565:     }
                   1566:   }
                   1567: 
                   1568:   /* otherwise, if this is an stp2220 and we have "slot" and "offset"
                   1569:      arguments, and an optional "slaveonly" argument, this is an SBus
                   1570:      connection: */
                   1571:   else if (TME_STP222X_IS_2220(stp222x)
                   1572:           && TME_ARG_IS(args[1], "slot")
                   1573:           && args[2] != NULL
                   1574:           && TME_ARG_IS(args[3], "offset")
                   1575:           && args[4] != NULL
                   1576:           && (((slaveonly = TME_ARG_IS(args[5], "slaveonly"))
                   1577:                && args[6] == NULL)
                   1578:               || args[5] == NULL)) {
                   1579: 
                   1580:     /* convert the slot and base offset: */
                   1581:     slot_wider = tme_bus_addr_parse(args[2], TME_STP2220_SLOT_OBIO(TME_STP2220_SLOTS_OBIO));
                   1582:     offset_wider = tme_bus_addr_parse(args[4], TME_STP2220_SLOT_SIZE);
                   1583: 
                   1584:     /* if this is a bad slot: */
                   1585:     if ((slot_wider < TME_STP2220_SLOT_CARD(0)
                   1586:         || slot_wider > TME_STP2220_SLOT_CARD(TME_STP2220_SLOTS_CARD - 1))
                   1587:        && (slot_wider < TME_STP2220_SLOT_OBIO(0)
                   1588:            || slot_wider > TME_STP2220_SLOT_OBIO(TME_STP2220_SLOTS_OBIO - 1))) {
                   1589:       tme_output_append_error(_output, 
                   1590:                              "%s %s",
                   1591:                              _("bad slot"),
                   1592:                              args[2]);
                   1593:       rc = EINVAL;
                   1594:     }
                   1595: 
                   1596:     /* if this is a bad offset: */
                   1597:     else if (offset_wider >= TME_STP2220_SLOT_SIZE) {
                   1598:       tme_output_append_error(_output, 
                   1599:                              "%s %s",
                   1600:                              _("bad offset"),
                   1601:                              args[4]);
                   1602:       rc = EINVAL;
                   1603:     }
                   1604: 
                   1605:     /* otherwise, the arguments are ok: */
                   1606:     else {
                   1607: 
                   1608:       /* create a generic bus connection: */
                   1609:       conn_bus = tme_new0(struct tme_bus_connection, 1);
                   1610:       conn_bus->tme_bus_connection.tme_connection_type = TME_CONNECTION_BUS_GENERIC;
                   1611: 
                   1612:       /* fill in the generic bus connection: */
                   1613:       conn_bus->tme_bus_signals_add = NULL;
                   1614:       conn_bus->tme_bus_signal = _tme_stp222x_signal;
                   1615:       conn_bus->tme_bus_intack = NULL;
                   1616:       conn_bus->tme_bus_tlb_set_add = tme_stp22xx_tlb_set_add;
                   1617:       conn_bus->tme_bus_tlb_fill = tme_stp222x_iommu_tlb_fill;
                   1618: 
                   1619:       /* fill in the generic connection: */
                   1620:       /* NB: this connection's temporary id is the SBus address, with
                   1621:         the slot exclusive-ORed with the maximum number of cards if
                   1622:         the "slaveonly" flag was given: */
                   1623:       conn = &conn_bus->tme_bus_connection;
                   1624:       conn->tme_connection_id
                   1625:        = TME_STP2220_SBUS_ADDRESS((slot_wider
                   1626:                                    ^ (slaveonly
                   1627:                                       ? TME_STP2220_SLOT_CARD(TME_STP2220_SLOTS_CARD)
                   1628:                                       : 0)),
                   1629:                                   offset_wider);
                   1630:       conn->tme_connection_score = _tme_stp222x_connection_score;
                   1631:       conn->tme_connection_make = _tme_stp222x_connection_make;
                   1632:       conn->tme_connection_break = _tme_stp222x_connection_break;
                   1633: 
                   1634:       /* add in this connection side possibility: */
                   1635:       conn->tme_connection_next = *_conns;
                   1636:       *_conns = conn;
                   1637:     }
                   1638:   }
                   1639: 
                   1640:   /* otherwise, the arguments are unknown: */
                   1641:   else {
                   1642:     if (TME_STP222X_IS_2220(stp222x)) {
                   1643:       tme_output_append_error(_output, 
                   1644:                              "%s %s [ slot %s offset %s [ slaveonly ] ]",
                   1645:                              _("usage:"),
                   1646:                              args[0],
                   1647:                              _("SLOT"),
                   1648:                              _("OFFSET"));
                   1649:     }
                   1650:     rc = EINVAL;
                   1651:   }
                   1652: 
                   1653:   /* unlock the mutex: */
                   1654:   tme_mutex_unlock(&stp222x->tme_stp222x.tme_stp22xx_mutex);
                   1655: 
                   1656:   return (rc);
                   1657: }
                   1658: 
                   1659: /* this creates a new stp222x element: */
                   1660: static int
                   1661: _tme_stp222x_new(struct tme_element *element,
                   1662:                 const char * const *args,
                   1663:                 const void *extra,
                   1664:                 char **_output,
                   1665:                 unsigned int is_2220)
                   1666: {
                   1667:   struct tme_stp222x *stp222x;
                   1668:   int arg_i;
                   1669:   int usage;
                   1670: 
                   1671:   /* check our arguments: */
                   1672:   usage = 0;
                   1673:   arg_i = 1;
                   1674:   for (;;) {
                   1675: 
                   1676:     if (0) {
                   1677:     }
                   1678: 
                   1679:     /* if we ran out of arguments: */
                   1680:     else if (args[arg_i] == NULL) {
                   1681: 
                   1682:       break;
                   1683:     }
                   1684: 
                   1685:     /* otherwise this is a bad argument: */
                   1686:     else {
                   1687:       tme_output_append_error(_output,
                   1688:                              "%s %s, ",
                   1689:                              args[arg_i],
                   1690:                              _("unexpected"));
                   1691:       usage = TRUE;
                   1692:       break;
                   1693:     }
                   1694:   }
                   1695: 
                   1696:   if (usage) {
                   1697:     tme_output_append_error(_output, 
                   1698:                            "%s %s",
                   1699:                            _("usage:"),
                   1700:                            args[0]);
                   1701:     return (EINVAL);
                   1702:   }
                   1703: 
                   1704:   /* start the stp222x structure: */
                   1705:   stp222x = tme_new0(struct tme_stp222x, 1);
                   1706:   stp222x->tme_stp222x.tme_stp22xx_element = element;
                   1707:   stp222x->tme_stp222x.tme_stp22xx_run = _tme_stp222x_run;
                   1708:   tme_stp22xx_init(&stp222x->tme_stp222x,
                   1709:                   sizeof(struct tme_stp222x),
                   1710:                   TME_STP222X_CONN_NULL);
                   1711: 
                   1712:   /* set the type: */
                   1713:   stp222x->tme_stp222x_is_2220 = is_2220;
                   1714:   if (TME_STP222X_IS_2220(stp222x) != is_2220) {
                   1715:     tme_free(stp222x);
                   1716:     return (ENXIO);
                   1717:   }
                   1718: 
                   1719:   /* the UPA bus reset signal is initially negated: */
                   1720:   stp222x->tme_stp222x_reset_level = TME_BUS_SIGNAL_LEVEL_NEGATED;
                   1721: 
                   1722:   /* initialize the CSR: */
                   1723:   stp222x->tme_stp222x_csr
                   1724:     = (0x1f * _TME_FIELD_MASK_FACTOR(TME_STP222X_CSR_MID));
                   1725: 
                   1726:   /* initialize the miscellaneous registers: */
                   1727:   stp222x->tme_stp222x_upa_port_config = 1;
                   1728: 
                   1729:   /* initialize the connections: */
                   1730:   stp222x->tme_stp222x_slave_conn_index_next = TME_STP222X_CONN_SLAVE0;
                   1731: 
                   1732:   /* initialize the timers: */
                   1733:   tme_stp222x_timer_init(stp222x, &stp222x->tme_stp222x_timers[0]);
                   1734:   tme_stp222x_timer_init(stp222x, &stp222x->tme_stp222x_timers[1]);
                   1735: 
                   1736:   /* initialize the MDU: */
                   1737:   tme_stp222x_mdu_init(stp222x);
                   1738: 
                   1739:   /* initialize the IOMMU: */
                   1740:   tme_stp222x_iommu_init(stp222x);
                   1741: 
                   1742:   /* initialize the streaming caches: */
                   1743:   tme_stp222x_stc_init(&stp222x->tme_stp222x_stcs[0]);
                   1744:   tme_stp222x_stc_init(&stp222x->tme_stp222x_stcs[1]);
                   1745: 
                   1746:   /* fill the element: */
                   1747:   element->tme_element_private = stp222x;
                   1748:   element->tme_element_connections_new = _tme_stp222x_connections_new;
                   1749: 
                   1750:   return (TME_OK);
                   1751: }
                   1752: 
                   1753: /* this creates a new stp2220 element: */
                   1754: TME_ELEMENT_X_NEW_DECL(tme_ic_,stp22xx,stp2220) {
                   1755:   return (_tme_stp222x_new(element, args, extra, _output, TRUE));
                   1756: }

unix.superglobalmegacorp.com

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