Annotation of tme/ic/stp22xx/stp220x.c, revision 1.1.1.1

1.1       root        1: /* $Id: stp220x.c,v 1.5 2010/06/05 18:59:29 fredette Exp $ */
                      2: 
                      3: /* ic/stp220x.c - emulation of the uniprocessor system controller
                      4:    (STP2200) and the dual-processor system controller (STP2202): */
                      5: 
                      6: /*
                      7:  * Copyright (c) 2009 Matt Fredette
                      8:  * All rights reserved.
                      9:  *
                     10:  * Redistribution and use in source and binary forms, with or without
                     11:  * modification, are permitted provided that the following conditions
                     12:  * are met:
                     13:  * 1. Redistributions of source code must retain the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer.
                     15:  * 2. Redistributions in binary form must reproduce the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer in the
                     17:  *    documentation and/or other materials provided with the distribution.
                     18:  * 3. All advertising materials mentioning features or use of this software
                     19:  *    must display the following acknowledgement:
                     20:  *      This product includes software developed by Matt Fredette.
                     21:  * 4. The name of the author may not be used to endorse or promote products
                     22:  *    derived from this software without specific prior written permission.
                     23:  *
                     24:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     25:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
                     26:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
                     27:  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
                     28:  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
                     29:  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
                     30:  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     31:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
                     32:  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
                     33:  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     34:  * POSSIBILITY OF SUCH DAMAGE.
                     35:  */
                     36: 
                     37: #include <tme/common.h>
                     38: _TME_RCSID("$Id: stp220x.c,v 1.5 2010/06/05 18:59:29 fredette Exp $");
                     39: 
                     40: /* includes: */
                     41: #include "stp22xx-impl.h"
                     42: 
                     43: /* macros: */
                     44: 
                     45: /* MIDs: */
                     46: #define TME_STP220X_MID_CPU(n)                 (n)
                     47: #define TME_STP220X_MID_IO                     (31)
                     48: 
                     49: /* UPA ports: */
                     50: #define TME_STP220X_UPA_PORT_CPU(n)            (n)
                     51: #define TME_STP220X_UPA_PORT_IO                        (2)
                     52: #define TME_STP220X_UPA_PORT_FFB               (3)
                     53: #define TME_STP220X_UPA_PORT_COUNT_MAX         (4)
                     54: 
                     55: /* the size of a UPA port: */
                     56: #define TME_STP220X_UPA_PORT_SIZE              (((tme_uint64_t) 1) << 33)
                     57: 
                     58: /* the number of SIMM groups: */
                     59: #define TME_STP220X_SIMM_GROUP_COUNT           (4)
                     60: 
                     61: /* registers: */
                     62: #define TME_STP220X_SC_CONTROL                 (0x00)
                     63: #define TME_STP220X_SC_ID                      (0x04)
                     64: #define TME_STP220X_SC_PERF(n)                 (0x08 + (4 * (n)))
                     65: #define TME_STP220X_SC_PERFSHADOW              (0x10)
                     66: #define TME_STP220X_SC_PERF_CTRL               (0x20)
                     67: #define TME_STP220X_SC_DEBUG_PIN_CTRL          (0x30)
                     68: #define TME_STP220X_SC_UPA_CONFIG(port)                (0x40 + (8 * (port)))
                     69: #define TME_STP220X_SC_UPA_STATUS(port)                (0x44 + (8 * (port)))
                     70: #define TME_STP2200_SC_MC_CONTROL0             (0x60)
                     71: #define TME_STP2200_SC_MC_CONTROL1             (0x64)
                     72: #define TME_STP2202_SC_CC_DIAG                 (0x70)
                     73: #define TME_STP2202_SC_CC_SNPVEC               (0x74)
                     74: #define TME_STP2202_SC_CC_FAULT                        (0x78)
                     75: #define TME_STP2202_SC_CC_PROC_INDEX           (0x7c)
                     76: #define TME_STP2202_SC_MEMCTRL(n)              (0x80 + (4 * (n)))
                     77: 
                     78: /* this converts an SC UPA port config or status register address into
                     79:    a UPA port: */
                     80: #define TME_STP220X_SC_ADDRESS_UPA_PORT(address)       \
                     81:   (((address)                                          \
                     82:     - TME_STP220X_SC_UPA_CONFIG(0))                    \
                     83:    / (TME_STP220X_SC_UPA_CONFIG(1)                     \
                     84:       - TME_STP220X_SC_UPA_CONFIG(0)))
                     85: 
                     86: /* the control register: */
                     87: #define TME_STP220X_SC_CONTROL_POR             (((tme_uint32_t) 1) << 31)
                     88: #define TME_STP220X_SC_CONTROL_SOFT_POR                TME_BIT(30)
                     89: #define TME_STP220X_SC_CONTROL_SOFT_XIR                TME_BIT(29)
                     90: #define TME_STP220X_SC_CONTROL_B_POR           TME_BIT(28)
                     91: #define TME_STP220X_SC_CONTROL_B_XIR           TME_BIT(27)
                     92: #define TME_STP220X_SC_CONTROL_WAKEUP          TME_BIT(26)
                     93: #define TME_STP220X_SC_CONTROL_FATAL           TME_BIT(25)
                     94: #define TME_STP220X_SC_CONTROL_IAP             TME_BIT(23)
                     95: #define TME_STP220X_SC_CONTROL_EN_WKUP_POR     TME_BIT(22)
                     96: #define TME_STP220X_SC_CONTROL_MBZ     \
                     97:   (TME_BIT(24)                         \
                     98:    | ((2 << 21) - (1 << 0)))
                     99: 
                    100: /* a UPA port configuration register: */
                    101: #define TME_STP220X_UPA_CONFIG_MD              (((tme_uint32_t) 1) << 31)
                    102: #define TME_STP220X_UPA_CONFIG_S_SLEEP         TME_BIT(30)
                    103: #define TME_STP220X_UPA_CONFIG_SPRQS           ((2 << 27) - (1 << 24))
                    104: #define TME_STP220X_UPA_CONFIG_SPDQS           ((2 << 23) - (1 << 18))
                    105: #define TME_STP220X_UPA_CONFIG_SPIQS           ((2 << 17) - (1 << 16))
                    106: #define TME_STP220X_UPA_CONFIG_SQUEN           TME_BIT(15)
                    107: #define TME_STP220X_UPA_CONFIG_ONEREAD         TME_BIT(14)
                    108: #define TME_STP220X_UPA_CONFIG_MBZ             \
                    109:   (((2 << 29) - (1 << 28))                     \
                    110:    | ((2 << 13) - (1 << 0)))
                    111: 
                    112: /* a UPA port status register: */
                    113: #define TME_STP220X_UPA_STATUS_FATAL           (((tme_uint32_t) 1) << 31)
                    114: #define TME_STP220X_UPA_STATUS_IADDR           TME_BIT(30)
                    115: #define TME_STP220X_UPA_STATUS_IPORT           TME_BIT(29)
                    116: #define TME_STP220X_UPA_STATUS_IPRTY           TME_BIT(28)
                    117: #define TME_STP220X_UPA_STATUS_MC0OF           TME_BIT(27)
                    118: #define TME_STP220X_UPA_STATUS_MC1OF           TME_BIT(26)
                    119: #define TME_STP220X_UPA_STATUS_MC0Q            ((2 << 25) - (1 << 23))
                    120: #define TME_STP220X_UPA_STATUS_MC1Q            ((2 << 22) - (1 << 20))
                    121: #define TME_STP220X_UPA_STATUS_MC1Q_0          TME_BIT(19)
                    122: 
                    123: /* this gives the log2 of the SIMM group size: */
                    124: #define TME_STP220X_SIMM_GROUP_SIZE_LOG2(stp220x) (TME_STP220X_IS_2200(stp220x) ? 28 : 29)
                    125: 
                    126: /* connections: */
                    127: #define TME_STP220X_CONN_UPA_PORT(n)           (n)
                    128: #define TME_STP220X_CONN_SIMM_GROUP(n)         TME_STP220X_CONN_UPA_PORT(TME_STP220X_UPA_PORT_COUNT_MAX + (n))
                    129: #define TME_STP220X_CONN_EBUS                  TME_STP220X_CONN_SIMM_GROUP(TME_STP220X_SIMM_GROUP_COUNT)
                    130: #define TME_STP220X_CONN_COUNT                 (TME_STP220X_CONN_EBUS + 1)
                    131: #define TME_STP220X_CONN_NULL                  (TME_STP220X_CONN_COUNT)
                    132: 
                    133: /* reset states: */
                    134: #define TME_STP220X_RESET_STATE_NEGATING       (TME_STP220X_UPA_PORT_COUNT_MAX)
                    135: #define TME_STP220X_RESET_STATE_ASSERTING      (TME_STP220X_UPA_PORT_COUNT_MAX * 2)
                    136: 
                    137: /* predicates: */
                    138: #define TME_STP220X_IS_2200(stp220x)           ((stp220x)->tme_stp220x_is_2200)
                    139: 
                    140: /* types: */
                    141: 
                    142: /* the device: */
                    143: struct tme_stp220x {
                    144: 
                    145:   /* the common structure, and space for the connections: */
                    146:   struct tme_stp22xx tme_stp220x;
                    147: #define tme_stp220x_master_conn_index_pending tme_stp220x.tme_stp22xx_master_conn_index_pending
                    148: #define tme_stp220x_master_conn_index tme_stp220x.tme_stp22xx_master_conn_index
                    149: #define tme_stp220x_master_completion tme_stp220x.tme_stp22xx_master_completion
                    150:   union tme_stp22xx_conn __tme_stp220x_conns[TME_STP220X_CONN_COUNT];
                    151: 
                    152:   /* the last address in each connection: */
                    153:   tme_bus_addr64_t tme_stp220x_conn_address_last[TME_STP220X_CONN_COUNT];
                    154: 
                    155:   /* this is nonzero if this is an STP2200: */
                    156:   int tme_stp220x_is_2200;
                    157: 
                    158:   /* the reset state: */
                    159:   unsigned int tme_stp220x_reset_state;
                    160: 
                    161:   /* the reset bus signal: */
                    162:   tme_uint32_t tme_stp220x_reset_signal;
                    163: 
                    164:   /* the mask of connection indices requesting the bus: */
                    165:   tme_uint32_t tme_stp220x_brs;
                    166: 
                    167:   /* the ebus EB_ADDR and EB_DATA registers: */
                    168:   unsigned int tme_stp220x_eb_addr;
                    169:   tme_uint8_t tme_stp220x_eb_data[sizeof(tme_uint32_t)];
                    170: 
                    171:   /* the registers: */
                    172:   tme_uint32_t tme_stp220x_sc_control;
                    173:   tme_uint32_t tme_stp220x_sc_perf[2];
                    174:   tme_uint32_t tme_stp220x_sc_perfshadow;
                    175:   tme_uint32_t tme_stp220x_sc_perf_ctrl;
                    176:   tme_uint32_t tme_stp220x_sc_upa_config[TME_STP220X_UPA_PORT_COUNT_MAX];
                    177:   tme_uint32_t tme_stp220x_sc_upa_status[TME_STP220X_UPA_PORT_COUNT_MAX];
                    178:   tme_uint32_t tme_stp2202_sc_cc_diag;
                    179:   tme_uint32_t tme_stp2202_sc_cc_fault;
                    180:   tme_uint32_t tme_stp2202_sc_cc_proc_index;
                    181:   tme_uint32_t tme_stp220x_sc_memctrl[0xe];
                    182: #define tme_stp2200_sc_mc_control tme_stp220x_sc_memctrl
                    183: #define tme_stp2202_sc_memctrl tme_stp220x_sc_memctrl
                    184: };
                    185: 
                    186: /* globals: */
                    187: 
                    188: /* the ebus subregion, decoded by the PAL block of the RIC chip
                    189:    (STP2210), for the PLL chip (either an mc12429 or an mc12439): */
                    190: static const struct tme_bus_subregion _tme_stp2210_mc124x9_subregion = {
                    191: 
                    192:   /* the first and last addresses, starting from zero, of this
                    193:      subregion: */
                    194:   0x4000,
                    195:   0x4003,
                    196: 
                    197:   /* there are no other subregions for this bus connection: */
                    198:   (const struct tme_bus_subregion *) NULL
                    199: };
                    200: 
                    201: /* this converts a connection index into a MID: */
                    202: static unsigned int
                    203: _tme_stp220x_conn_index_mid(const struct tme_stp220x *stp220x,
                    204:                            unsigned int conn_index)
                    205: {
                    206:   switch (conn_index) {
                    207:   default: assert (FALSE);
                    208:   case TME_STP220X_CONN_UPA_PORT(TME_STP220X_UPA_PORT_CPU(0)):
                    209:     return (TME_STP220X_MID_CPU(0));
                    210:   case TME_STP220X_CONN_UPA_PORT(TME_STP220X_UPA_PORT_CPU(1)):
                    211:     assert (!TME_STP220X_IS_2200(stp220x));
                    212:     return (TME_STP220X_MID_CPU(1));
                    213:   case TME_STP220X_CONN_UPA_PORT(TME_STP220X_UPA_PORT_IO):
                    214:     return (TME_STP220X_MID_IO);
                    215:   }
                    216: }
                    217: 
                    218: /* this converts a MID into a connection index: */
                    219: static unsigned int
                    220: _tme_stp220x_lookup_mid(const struct tme_stp220x *stp220x,
                    221:                        tme_uint32_t mid)
                    222: {
                    223:   switch (mid) {
                    224:   case TME_STP220X_MID_CPU(0):
                    225:     return (TME_STP220X_CONN_UPA_PORT(TME_STP220X_UPA_PORT_CPU(0)));
                    226:   case TME_STP220X_MID_CPU(1):
                    227:     return (TME_STP220X_IS_2200(stp220x)
                    228:            ? TME_STP220X_CONN_NULL
                    229:            : TME_STP220X_CONN_UPA_PORT(TME_STP220X_UPA_PORT_CPU(1)));
                    230:   case TME_STP220X_MID_IO:
                    231:     return (TME_STP220X_CONN_UPA_PORT(TME_STP220X_UPA_PORT_IO));
                    232:   default:
                    233:     return (TME_STP220X_CONN_NULL);
                    234:   }
                    235: }
                    236: 
                    237: /* this converts an address into a connection index and a
                    238:    connection-relative address: */
                    239: static unsigned int
                    240: _tme_stp220x_lookup_address(const struct tme_stp220x *stp220x,
                    241:                            tme_bus_addr64_t *_address,
                    242:                            tme_bus_addr64_t *_region_size_m1)
                    243: {
                    244:   tme_uint32_t address_32_64;
                    245:   tme_uint32_t address_0_31;
                    246:   unsigned int group_size_log2;
                    247:   unsigned int group;
                    248:   tme_uint32_t group_size_m1;
                    249:   unsigned int conn_index;
                    250:   tme_uint32_t upn;
                    251: 
                    252:   /* get bits 32..64 of the address: */
                    253:   address_32_64 = (*_address >> 32);
                    254: 
                    255:   /* if this address is in memory: */
                    256:   if (address_32_64 < 0x100) {
                    257: 
                    258:     /* get bits 0..31 of the address: */
                    259:     address_0_31 = *_address;
                    260: 
                    261:     /* get the SIMM group number: */
                    262:     group_size_log2 = TME_STP220X_SIMM_GROUP_SIZE_LOG2(stp220x);
                    263:     group = (address_0_31 >> group_size_log2) % TME_STP220X_SIMM_GROUP_COUNT;
                    264: 
                    265:     /* get the connection index for this SIMM group: */
                    266:     conn_index = TME_STP220X_CONN_SIMM_GROUP(group);
                    267: 
                    268:     /* get the size, minus one, of the SIMM group: */
                    269:     group_size_m1 = stp220x->tme_stp220x_conn_address_last[conn_index];
                    270: 
                    271:     /* return the truncated address within the SIMM group, the size of
                    272:        the SIMM group, and the connection index: */
                    273:     *_address = (address_0_31 & group_size_m1);
                    274:     *_region_size_m1 = group_size_m1;
                    275:     return (conn_index);
                    276:   }
                    277: 
                    278:   /* make the region size the UPA port size: */
                    279:   *_region_size_m1 = (TME_STP220X_UPA_PORT_SIZE - 1);
                    280: 
                    281:   /* if this address is in a UPA port: */
                    282:   if (__tme_predict_true(address_32_64 >= 0x1c0)) {
                    283: 
                    284:     /* make the address within the UPA port: */
                    285:     *_address %= TME_STP220X_UPA_PORT_SIZE;
                    286: 
                    287:     /* get the UPN: */
                    288:     upn = (address_32_64 - 0x1c0) >> 1;
                    289: 
                    290:     /* UPN 30 is the FFB: */
                    291:     if (upn == 30) {
                    292:       return (TME_STP220X_CONN_UPA_PORT(TME_STP220X_UPA_PORT_FFB));
                    293:     }
                    294: 
                    295:     /* all other UPNs are either valid MIDs or are reserved: */
                    296:     return (_tme_stp220x_lookup_mid(stp220x, upn));
                    297:   }
                    298: 
                    299:   /* this address is in a reserved region: */
                    300:   return (TME_STP220X_CONN_NULL);
                    301: }
                    302: 
                    303: /* this busies an agent generic bus connection: */
                    304: #define _tme_stp220x_agent_busy_bus(stp220x, agent_conn_index) \
                    305:   tme_stp22xx_busy_bus(&(stp220x)->tme_stp220x, agent_conn_index)
                    306: 
                    307: /* this unbusies an agent generic bus connection: */
                    308: #define _tme_stp220x_agent_unbusy_bus(stp220x, agent_conn_bus) \
                    309:   tme_stp22xx_unbusy_bus(&(stp220x)->tme_stp220x, agent_conn_bus)
                    310: 
                    311: /* this busies a slave generic bus connection: */
                    312: #define _tme_stp220x_slave_busy_bus(stp220x, slave_conn_index) \
                    313:   tme_stp22xx_slave_busy_bus(&(stp220x)->tme_stp220x, slave_conn_index)
                    314: 
                    315: /* this unbusies a slave connection: */
                    316: #define _tme_stp220x_slave_unbusy(stp220x) \
                    317:   tme_stp22xx_slave_unbusy(&(stp220x)->tme_stp220x)
                    318: 
                    319: /* this busies a slave UPA connection: */
                    320: static struct tme_upa_bus_connection *
                    321: _tme_stp220x_slave_busy_upa(struct tme_stp220x *stp220x,
                    322:                            unsigned int slave_conn_index)
                    323: {
                    324:   struct tme_upa_bus_connection *slave_conn_upa;
                    325:   struct tme_bus_connection *slave_conn_bus;
                    326: 
                    327:   /* if the connection index is valid: */
                    328:   slave_conn_upa = NULL;
                    329:   if (__tme_predict_true(slave_conn_index != TME_STP220X_CONN_NULL)) {
                    330: 
                    331:     /* if there is a UPA slave at this connection index: */
                    332:     slave_conn_upa = stp220x->tme_stp220x.tme_stp22xx_conns[slave_conn_index].tme_stp22xx_conn_upa;
                    333:     if (__tme_predict_true(slave_conn_upa != NULL
                    334:                           && slave_conn_upa->tme_upa_bus_connection.tme_bus_connection.tme_connection_type == TME_CONNECTION_BUS_UPA)) {
                    335: 
                    336:       /* busy the connection to the UPA slave: */
                    337:       slave_conn_bus = _tme_stp220x_slave_busy_bus(stp220x, slave_conn_index);
                    338:       assert (slave_conn_bus == &slave_conn_upa->tme_upa_bus_connection);
                    339:       return ((struct tme_upa_bus_connection *) slave_conn_bus);
                    340:     }
                    341:   }
                    342: 
                    343:   return (NULL);
                    344: }
                    345: 
                    346: /* this enters an stp220x: */
                    347: #define _tme_stp220x_enter_bus(agent_conn_bus) \
                    348:   ((struct tme_stp220x *) tme_stp22xx_enter((struct tme_stp22xx *) (agent_conn_bus)->tme_bus_connection.tme_connection_element->tme_element_private))
                    349: 
                    350: /* these enter an stp220x as the bus master: */
                    351: #define _tme_stp220x_enter_master_bus(agent_conn_bus) \
                    352:   ((struct tme_stp220x *) tme_stp22xx_enter_master(agent_conn_bus))
                    353: #define _tme_stp220x_enter_master_upa(agent_conn_upa) \
                    354:   _tme_stp220x_enter_master_bus(&(agent_conn_upa)->tme_upa_bus_connection)
                    355: 
                    356: /* this leaves an stp220x: */
                    357: #define _tme_stp220x_leave(stp220x) \
                    358:   tme_stp22xx_leave(&(stp220x)->tme_stp220x)
                    359: 
                    360: /* this validates an agent's completion: */
                    361: /* NB: agent_completion may be NULL: */
                    362: #define _tme_stp220x_completion_validate(stp220x, completion) \
                    363:   tme_stp22xx_completion_validate(&(stp220x)->tme_stp220x, completion)
                    364: 
                    365: /* this allocates a completion: */
                    366: #define _tme_stp220x_completion_alloc(stp220x, handler, arg) \
                    367:   tme_stp22xx_completion_alloc(&(stp220x)->tme_stp220x, handler, arg)
                    368: 
                    369: /* this completes a bus operation between master and slave: */
                    370: #define _tme_stp220x_complete_master tme_stp22xx_complete_master
                    371: 
                    372: /* this completes a reset assertion or negation: */
                    373: static void
                    374: _tme_stp220x_complete_reset(struct tme_stp22xx *stp22xx,
                    375:                            struct tme_completion *completion,
                    376:                            void *arg)
                    377: {
                    378:   struct tme_stp220x *stp220x;
                    379: 
                    380:   /* recover our data structure: */
                    381:   stp220x = (struct tme_stp220x *) stp22xx;
                    382: 
                    383:   /* update the reset state: */
                    384:   stp220x->tme_stp220x_reset_state--;
                    385: 
                    386:   /* unused: */
                    387:   completion = 0;
                    388:   arg = 0;
                    389: }
                    390: 
                    391: /* this completes a bus grant: */
                    392: #define _tme_stp220x_complete_bg tme_stp22xx_complete_bg
                    393: 
                    394: /* this calls out a bus signal to an agent: */
                    395: #define _tme_stp220x_callout_signal(stp220x, conn_index, signal, completion_handler) \
                    396:   tme_stp22xx_callout_signal(&(stp220x)->tme_stp220x, conn_index, signal, completion_handler)
                    397: 
                    398: /* the run function: */
                    399: static void
                    400: _tme_stp220x_run(struct tme_stp22xx *stp22xx)
                    401: {
                    402:   struct tme_stp220x *stp220x;
                    403:   unsigned int reset_state;
                    404:   unsigned int agent_conn_index;
                    405:   unsigned int master_conn_index;
                    406:   tme_uint32_t brs;
                    407: 
                    408:   /* recover our data structure: */
                    409:   stp220x = (struct tme_stp220x *) stp22xx;
                    410: 
                    411:   /* loop forever: */
                    412:   for (;;) {
                    413: 
                    414:     /* if we need to assert reset to another agent: */
                    415:     reset_state = stp220x->tme_stp220x_reset_state;
                    416:     if (reset_state > TME_STP220X_RESET_STATE_NEGATING) {
                    417: 
                    418:       /* assert reset to the next agent: */
                    419:       agent_conn_index = reset_state - (TME_STP220X_RESET_STATE_NEGATING + 1);
                    420:       _tme_stp220x_callout_signal(stp220x,
                    421:                                  agent_conn_index,
                    422:                                  (stp220x->tme_stp220x_reset_signal
                    423:                                   | TME_BUS_SIGNAL_EDGE
                    424:                                   | TME_BUS_SIGNAL_LEVEL_ASSERTED),
                    425:                                  _tme_stp220x_complete_reset);
                    426:       continue;
                    427:     }
                    428: 
                    429:     /* if there is a current master: */
                    430:     master_conn_index = stp220x->tme_stp220x_master_conn_index;
                    431:     if (master_conn_index != TME_STP220X_CONN_NULL) {
                    432: 
                    433:       /* if the current master is still requesting the bus: */
                    434:       if (stp220x->tme_stp220x_brs & (1 << master_conn_index)) { 
                    435: 
                    436:        /* stop now.  we can't do anything else until the current
                    437:           master releases the bus: */
                    438:        break;
                    439:       }
                    440: 
                    441:       /* there is no current master: */
                    442:       stp220x->tme_stp220x_master_conn_index = TME_STP220X_CONN_NULL;
                    443: 
                    444:       /* negate bus grant to the former master: */
                    445:       _tme_stp220x_callout_signal(stp220x,
                    446:                                  master_conn_index,
                    447:                                  (TME_BUS_SIGNAL_BG
                    448:                                   | TME_BUS_SIGNAL_EDGE
                    449:                                   | TME_BUS_SIGNAL_LEVEL_NEGATED),
                    450:                                  tme_stp22xx_complete_nop);
                    451:       continue;
                    452:     }
                    453: 
                    454:     /* if we need to negate reset to another agent: */
                    455:     reset_state = stp220x->tme_stp220x_reset_state;
                    456:     if (reset_state) {
                    457: 
                    458:       /* negate reset to the next agent: */
                    459:       agent_conn_index = reset_state - 1;
                    460:       _tme_stp220x_callout_signal(stp220x,
                    461:                                  agent_conn_index,
                    462:                                  (stp220x->tme_stp220x_reset_signal
                    463:                                   | TME_BUS_SIGNAL_EDGE
                    464:                                   | TME_BUS_SIGNAL_LEVEL_NEGATED),
                    465:                                  _tme_stp220x_complete_reset);
                    466:       continue;
                    467:     }
                    468: 
                    469:     /* if one or more agents are requesting the bus: */
                    470:     brs = stp220x->tme_stp220x_brs;
                    471:     if (brs != 0) {
                    472: 
                    473:       /* get the connection index for the next master: */
                    474:       /* XXX FIXME - should we do something fair here? */
                    475:       for (master_conn_index = 0;
                    476:           (brs & 1) == 0;
                    477:           brs >>= 1, master_conn_index++);
                    478: 
                    479:       /* set the pending master: */
                    480:       stp220x->tme_stp220x_master_conn_index_pending = master_conn_index;
                    481: 
                    482:       /* assert bus grant to the current master: */
                    483:       _tme_stp220x_callout_signal(stp220x,
                    484:                                  master_conn_index,
                    485:                                  (TME_BUS_SIGNAL_BG
                    486:                                   | TME_BUS_SIGNAL_EDGE
                    487:                                   | TME_BUS_SIGNAL_LEVEL_ASSERTED),
                    488:                                  _tme_stp220x_complete_bg);
                    489:       continue;
                    490:     }
                    491: 
                    492:     /* no other running is needed: */
                    493:     break;
                    494:   }
                    495: }
                    496: 
                    497: /* this does a reset: */
                    498: static void
                    499: _tme_stp220x_reset(struct tme_stp220x *stp220x,
                    500:                   tme_uint32_t resets)
                    501: {
                    502:   tme_uint32_t sc_control;
                    503:   tme_uint32_t reset;
                    504: 
                    505:   /* get the current status registers, so that the chosen reset may
                    506:      reset them: */
                    507:   sc_control = stp220x->tme_stp220x_sc_control;
                    508: 
                    509:   /* "If multiple resets occur simultaneously, the following order
                    510:      will be chosen for the reporting:" */
                    511: 
                    512:   if (resets & TME_STP220X_SC_CONTROL_POR) {
                    513:     sc_control = 0;
                    514:     reset = TME_STP220X_SC_CONTROL_POR;
                    515:   }
                    516:   else if (resets & TME_STP220X_SC_CONTROL_FATAL) {
                    517:     reset = TME_STP220X_SC_CONTROL_FATAL;
                    518:   }
                    519:   else if (resets & TME_STP220X_SC_CONTROL_B_POR) {
                    520:     sc_control = 0;
                    521:     reset = TME_STP220X_SC_CONTROL_B_POR;
                    522:   }
                    523:   else if (resets & TME_STP220X_SC_CONTROL_WAKEUP) {
                    524:     reset = TME_STP220X_SC_CONTROL_WAKEUP;
                    525:   }
                    526:   else if (resets & TME_STP220X_SC_CONTROL_SOFT_POR) {
                    527:     sc_control = 0;
                    528:     reset = TME_STP220X_SC_CONTROL_SOFT_POR;
                    529:   }
                    530:   else if (resets & TME_STP220X_SC_CONTROL_B_XIR) {
                    531:     reset = TME_STP220X_SC_CONTROL_B_XIR;
                    532:   }
                    533:   else {
                    534:     assert (resets == TME_STP220X_SC_CONTROL_SOFT_XIR);
                    535:     reset = TME_STP220X_SC_CONTROL_SOFT_XIR;
                    536:   }
                    537: 
                    538:   /* update the status registers: */
                    539:   stp220x->tme_stp220x_sc_control = sc_control | reset;
                    540: 
                    541:   /* if this is a type of power or fatal reset: */
                    542:   if (reset
                    543:       & (TME_STP220X_SC_CONTROL_FATAL
                    544:         | TME_STP220X_SC_CONTROL_POR
                    545:         | TME_STP220X_SC_CONTROL_B_POR
                    546:         | TME_STP220X_SC_CONTROL_SOFT_POR)) {
                    547: 
                    548:     /* start asserting SYS_RESET_L: */
                    549:     stp220x->tme_stp220x_reset_state = TME_STP220X_RESET_STATE_ASSERTING;
                    550:     stp220x->tme_stp220x_reset_signal = TME_BUS_SIGNAL_RESET;
                    551:   }
                    552: 
                    553:   /* otherwise, if this is a wakeup: */
                    554:   else if (reset == TME_STP220X_SC_CONTROL_WAKEUP) {
                    555: 
                    556:     /* XXX WRITEME: */
                    557:     abort();
                    558:   }
                    559: 
                    560:   /* otherwise, this must be an XIR: */
                    561:   else {
                    562:     assert (reset == TME_STP220X_SC_CONTROL_B_XIR
                    563:            || reset == TME_STP220X_SC_CONTROL_SOFT_XIR);
                    564: 
                    565:     /* start asserting UPA_XIR_L: */
                    566:     /* NB: we reuse TME_BUS_SIGNAL_HALT for this: */
                    567:     stp220x->tme_stp220x_reset_state = TME_STP220X_RESET_STATE_ASSERTING;
                    568:     stp220x->tme_stp220x_reset_signal = TME_BUS_SIGNAL_HALT;
                    569:   }
                    570: }
                    571: 
                    572: /* this handles a bus signal: */
                    573: static void
                    574: _tme_stp220x_signal(struct tme_bus_connection *agent_conn_bus,
                    575:                    unsigned int signal,
                    576:                    struct tme_completion *agent_completion)
                    577: {
                    578:   struct tme_stp220x *stp220x;
                    579:   tme_uint32_t level;
                    580:   tme_uint32_t agent_conn_index_mask;
                    581: 
                    582:   /* enter: */
                    583:   stp220x = _tme_stp220x_enter_bus(agent_conn_bus);
                    584: 
                    585:   /* get the level.  this must be an edge: */
                    586:   assert (signal & TME_BUS_SIGNAL_EDGE);
                    587:   level = signal - TME_BUS_SIGNAL_EDGE;
                    588:   signal = TME_BUS_SIGNAL_WHICH(signal);
                    589:   level ^= signal;
                    590: 
                    591:   /* get the agent's connection index mask: */
                    592:   agent_conn_index_mask = (1 << agent_conn_bus->tme_bus_connection.tme_connection_id);
                    593: 
                    594:   /* dispatch on the signal: */
                    595:   switch (signal) {
                    596: 
                    597:     /* the bus request signal: */
                    598:   case TME_BUS_SIGNAL_BR:
                    599: 
                    600:     /* mark this caller's bus request line as either asserted or
                    601:        negated: */
                    602:     assert (level == TME_BUS_SIGNAL_LEVEL_NEGATED
                    603:            || level == TME_BUS_SIGNAL_LEVEL_ASSERTED);
                    604:     stp220x->tme_stp220x_brs 
                    605:       = ((stp220x->tme_stp220x_brs
                    606:          | agent_conn_index_mask)
                    607:         & (level == TME_BUS_SIGNAL_LEVEL_ASSERTED
                    608:            ? ~0
                    609:            : ~agent_conn_index_mask));
                    610:     break;
                    611: 
                    612:   default:
                    613:     assert (FALSE);
                    614:     break;
                    615:   }
                    616: 
                    617:   /* leave: */
                    618:   _tme_stp220x_completion_validate(stp220x, agent_completion);
                    619:   _tme_stp220x_leave(stp220x);
                    620: }
                    621: 
                    622: /* this handles a bus cycle: */
                    623: static void
                    624: _tme_stp220x_cycle(struct tme_bus_connection *master_conn_bus,
                    625:                   struct tme_bus_cycle *master_cycle,
                    626:                   tme_uint32_t *_master_fast_cycle_types,
                    627:                   struct tme_completion *master_completion)
                    628: {
                    629:   struct tme_stp220x *stp220x;
                    630:   tme_bus_addr64_t slave_address;
                    631:   unsigned int slave_conn_index;
                    632:   tme_bus_addr64_t region_size_m1;
                    633: 
                    634:   /* enter: */
                    635:   stp220x = _tme_stp220x_enter_master_bus(master_conn_bus);
                    636: 
                    637:   /* start this cycle: */
                    638:   assert (stp220x->tme_stp220x_master_completion == NULL);
                    639:   stp220x->tme_stp220x_master_completion = &master_completion;
                    640: 
                    641:   /* convert the master's address into a slave connection index and
                    642:      address: */
                    643:   slave_address = master_cycle->tme_bus_cycle_address;
                    644:   slave_conn_index = _tme_stp220x_lookup_address(stp220x, &slave_address, &region_size_m1);
                    645:   master_cycle->tme_bus_cycle_address = slave_address;
                    646: 
                    647:   /* run the slave bus cycle: */
                    648:   tme_stp22xx_slave_cycle(master_conn_bus,
                    649:                          slave_conn_index,
                    650:                          master_cycle,
                    651:                          _master_fast_cycle_types,
                    652:                          &master_completion);
                    653:  
                    654:   /* leave: */
                    655:   _tme_stp220x_leave(stp220x);
                    656: }
                    657: 
                    658: /* this delivers an interrupt: */
                    659: static void
                    660: _tme_stp220x_interrupt(struct tme_upa_bus_connection *master_conn_upa,
                    661:                       tme_uint32_t slave_mid,
                    662:                       const tme_uint64_t *data,
                    663:                       struct tme_completion *master_completion)
                    664: {
                    665:   struct tme_stp220x *stp220x;
                    666:   unsigned int slave_conn_index;
                    667:   struct tme_upa_bus_connection *slave_conn_upa;
                    668:   struct tme_completion *completion;
                    669:   struct tme_upa_bus_connection *slave_conn_upa_other;
                    670: 
                    671:   /* enter: */
                    672:   stp220x = _tme_stp220x_enter_master_upa(master_conn_upa);
                    673: 
                    674:   /* convert the MID into a connection index: */
                    675:   slave_conn_index = _tme_stp220x_lookup_mid(stp220x, slave_mid);
                    676: 
                    677:   /* busy the connection to the slave: */
                    678:   slave_conn_upa = _tme_stp220x_slave_busy_upa(stp220x, slave_conn_index);
                    679: 
                    680:   /* if this slave does not exist: */
                    681:   if (__tme_predict_false(slave_conn_upa == NULL)) {
                    682: 
                    683:     /* complete with an error: */
                    684:     master_completion->tme_completion_error = ENOENT;
                    685:     _tme_stp220x_completion_validate(stp220x, master_completion);
                    686:   }
                    687: 
                    688:   /* otherwise, if this master is trying to interrupt itself: */
                    689:   else if (__tme_predict_false(slave_conn_upa == master_conn_upa)) {
                    690: 
                    691:     /* unbusy the connection to the slave: */
                    692:     _tme_stp220x_slave_unbusy(stp220x);
                    693: 
                    694:     /* complete with an error: */
                    695:     master_completion->tme_completion_error = EIO;
                    696:     _tme_stp220x_completion_validate(stp220x, master_completion);
                    697:   }
                    698: 
                    699:   /* otherwise, we can deliver this interrupt: */
                    700:   else {
                    701: 
                    702:     /* start this cycle: */
                    703:     assert (stp220x->tme_stp220x_master_completion == NULL);
                    704:     stp220x->tme_stp220x_master_completion = &master_completion;
                    705: 
                    706:     /* when we complete, we will will complete for the master: */
                    707:     completion = _tme_stp220x_completion_alloc(stp220x,
                    708:                                               _tme_stp220x_complete_master,
                    709:                                               &master_completion);
                    710: 
                    711:     /* leave: */
                    712:     _tme_stp220x_leave(stp220x);
                    713: 
                    714:     /* deliver this interrupt: */
                    715:     slave_conn_upa_other = (struct tme_upa_bus_connection *) slave_conn_upa->tme_upa_bus_connection.tme_bus_connection.tme_connection_other;
                    716:     (*slave_conn_upa_other->tme_upa_bus_interrupt)
                    717:       (slave_conn_upa_other,
                    718:        master_conn_upa->tme_upa_bus_connection_mid,
                    719:        data,
                    720:        completion);
                    721: 
                    722:     /* reenter: */
                    723:     stp220x = _tme_stp220x_enter_bus(&master_conn_upa->tme_upa_bus_connection);
                    724:   }
                    725: 
                    726:   /* leave: */
                    727:   _tme_stp220x_leave(stp220x);
                    728: }
                    729: 
                    730: /* this fills a TLB entry: */
                    731: static void
                    732: _tme_stp220x_tlb_fill(struct tme_bus_connection *agent_conn_bus,
                    733:                      struct tme_bus_tlb *tlb,
                    734:                      tme_bus_addr_t agent_address_wider,
                    735:                      unsigned int cycle_type)
                    736: {
                    737:   struct tme_stp220x *stp220x;
                    738:   tme_bus_addr64_t slave_address;
                    739:   unsigned int slave_conn_index;
                    740:   tme_bus_addr64_t region_size_m1;
                    741:   tme_bus_addr64_t agent_address;
                    742:   struct tme_bus_tlb tlb_mapping;
                    743: 
                    744:   /* enter: */
                    745:   stp220x = _tme_stp220x_enter_bus(agent_conn_bus);
                    746: 
                    747:   /* convert the agent's address into a slave connection index and
                    748:      address: */
                    749:   slave_address = agent_address_wider;
                    750:   slave_conn_index = _tme_stp220x_lookup_address(stp220x, &slave_address, &region_size_m1);
                    751: 
                    752:   /* fill the TLB entry: */
                    753:   tme_stp22xx_tlb_fill(agent_conn_bus,
                    754:                       tlb,
                    755:                       slave_conn_index,
                    756:                       slave_address,
                    757:                       cycle_type);
                    758: 
                    759:   /* leave: */
                    760:   _tme_stp220x_leave(stp220x);
                    761: 
                    762:   /* map the filled TLB entry: */
                    763:   agent_address = ~region_size_m1;
                    764:   agent_address &= agent_address_wider;
                    765:   tlb_mapping.tme_bus_tlb_addr_first = agent_address;
                    766:   agent_address |= region_size_m1;
                    767:   tlb_mapping.tme_bus_tlb_addr_last = agent_address;
                    768: #if TME_STP22XX_BUS_TRANSITION
                    769:   tlb_mapping.tme_bus_tlb_cycles_ok = (TME_BUS_CYCLE_READ | TME_BUS_CYCLE_WRITE);
                    770: #endif /* TME_STP22XX_BUS_TRANSITION */
                    771:   tme_bus_tlb_map(tlb, slave_address, &tlb_mapping, agent_address_wider);
                    772: }
                    773: 
                    774: /* this handles an ebus cycle: */
                    775: static void
                    776: _tme_stp220x_ebus_cycle(struct tme_bus_connection *ebus_conn_bus,
                    777:                        struct tme_bus_cycle *cycle,
                    778:                        tme_uint32_t *_master_fast_cycle_types,
                    779:                        struct tme_completion *completion)
                    780: {
                    781:   struct tme_stp220x *stp220x;
                    782:   unsigned int upa_port;
                    783:   tme_bus_addr32_t address;
                    784:   tme_uint8_t value8;
                    785:   tme_uint32_t value32;
                    786: 
                    787:   /* enter: */
                    788:   stp220x = _tme_stp220x_enter_bus(ebus_conn_bus);
                    789: 
                    790:   /* get the address: */
                    791:   address = cycle->tme_bus_cycle_address;
                    792: 
                    793:   /* get any UPA port number: */
                    794:   upa_port = TME_STP220X_SC_ADDRESS_UPA_PORT(stp220x->tme_stp220x_eb_addr);
                    795: 
                    796:   /* if this is a write: */
                    797:   if (cycle->tme_bus_cycle_type == TME_BUS_CYCLE_WRITE) {
                    798: 
                    799:     /* get value being written: */
                    800:     tme_bus_cycle_xfer_memory(cycle,
                    801:                              &value8 - address,
                    802:                              address);
                    803: 
                    804:     /* if this is a write to EB_ADDR: */
                    805:     if (address < sizeof(tme_uint32_t)) {
                    806: 
                    807:       /* update EB_ADDR: */
                    808:       stp220x->tme_stp220x_eb_addr = value8;
                    809:     }
                    810: 
                    811:     /* otherwise, if this is a write to EB_DATA: */
                    812:     else if (address < (2 * sizeof(tme_uint32_t))) {
                    813: 
                    814:       /* update EB_DATA: */
                    815:       stp220x->tme_stp220x_eb_data[address % sizeof(tme_uint32_t)] = value8;
                    816: 
                    817:       /* if this was a write to EB_DATA bits 0..7: */
                    818:       if (address == ((sizeof(tme_uint32_t) * 2) - 1)) {
                    819: 
                    820:        /* get the EB_DATA value: */
                    821:        value32 = stp220x->tme_stp220x_eb_data[0];
                    822:        value32 = (value32 << 8) + stp220x->tme_stp220x_eb_data[1];
                    823:        value32 = (value32 << 8) + stp220x->tme_stp220x_eb_data[2];
                    824:        value32 = (value32 << 8) + stp220x->tme_stp220x_eb_data[3];
                    825: 
                    826:        /* dispatch on EB_ADDR: */
                    827:        switch (stp220x->tme_stp220x_eb_addr) {
                    828:        default:
                    829:        /* case TME_STP220X_SC_DEBUG_PIN_CTRL: */
                    830:        /* case TME_STP2202_SC_CC_SNPVEC: */
                    831:          abort();
                    832:          break;
                    833:        case TME_STP220X_SC_CONTROL:
                    834: 
                    835:          /* clear any R/W1C bits: */
                    836:          stp220x->tme_stp220x_sc_control
                    837:            = (stp220x->tme_stp220x_sc_control
                    838:               & ~(value32
                    839:                   & (TME_STP220X_SC_CONTROL_POR
                    840:                      | TME_STP220X_SC_CONTROL_B_POR
                    841:                      | TME_STP220X_SC_CONTROL_B_XIR
                    842:                      | TME_STP220X_SC_CONTROL_WAKEUP
                    843:                      | TME_STP220X_SC_CONTROL_FATAL)));
                    844: 
                    845:          /* we don't support these bits: */
                    846:          if (value32
                    847:              & (TME_STP220X_SC_CONTROL_IAP
                    848:                 | TME_STP220X_SC_CONTROL_EN_WKUP_POR)) {
                    849:            abort();
                    850:          }
                    851: 
                    852:          /* update the R/W bits: */
                    853:          value32
                    854:            = ((stp220x->tme_stp220x_sc_control
                    855:                ^ value32)
                    856:               & (TME_STP220X_SC_CONTROL_SOFT_POR
                    857:                  | TME_STP220X_SC_CONTROL_SOFT_XIR
                    858:                  ));
                    859:          stp220x->tme_stp220x_sc_control ^= value32;
                    860: 
                    861:          /* handle any soft resets: */
                    862:          value32 &= stp220x->tme_stp220x_sc_control;
                    863:          value32
                    864:            &= (TME_STP220X_SC_CONTROL_SOFT_POR
                    865:                | TME_STP220X_SC_CONTROL_SOFT_XIR);
                    866:          if (value32 != 0) {
                    867:            _tme_stp220x_reset(stp220x, value32);
                    868:          }
                    869:          break;
                    870:        case TME_STP220X_SC_ID:
                    871:        case TME_STP220X_SC_PERF(0):
                    872:        case TME_STP220X_SC_PERF(1):
                    873:        case TME_STP220X_SC_PERFSHADOW:
                    874:          break;
                    875:        case TME_STP220X_SC_PERF_CTRL:
                    876:          if (value32 & (1 << 15)) {
                    877:            stp220x->tme_stp220x_sc_perf[1] = 0;
                    878:          }
                    879:          if (value32 & (1 << 7)) {
                    880:            stp220x->tme_stp220x_sc_perf[0] = 0;
                    881:          }
                    882:          stp220x->tme_stp220x_sc_perf_ctrl = value32;
                    883:          break;
                    884:        case TME_STP220X_SC_UPA_CONFIG(TME_STP220X_UPA_PORT_CPU(0)):
                    885:        case TME_STP220X_SC_UPA_CONFIG(TME_STP220X_UPA_PORT_CPU(1)):
                    886:        case TME_STP220X_SC_UPA_CONFIG(TME_STP220X_UPA_PORT_IO):
                    887:        case TME_STP220X_SC_UPA_CONFIG(TME_STP220X_UPA_PORT_FFB):
                    888:          if (upa_port == TME_STP220X_UPA_PORT_CPU(0)
                    889:              || upa_port == TME_STP220X_UPA_PORT_CPU(1)) {
                    890:            value32 &= ~TME_STP220X_UPA_CONFIG_SPDQS;
                    891:          }
                    892:          else {
                    893:            value32
                    894:              &= ~(TME_STP220X_UPA_CONFIG_S_SLEEP
                    895:                   | TME_STP220X_UPA_CONFIG_SPIQS);
                    896:          }
                    897:          if (upa_port == TME_STP220X_UPA_PORT_FFB) {
                    898:            value32
                    899:              |= (TME_STP220X_UPA_CONFIG_MD
                    900:                  | TME_STP220X_UPA_CONFIG_ONEREAD);
                    901:          }
                    902:          if ((value32 & TME_STP220X_UPA_CONFIG_SQUEN) == 0) {
                    903:            value32
                    904:              = ((value32
                    905:                  & ~(TME_STP220X_UPA_CONFIG_SPRQS
                    906:                      | TME_STP220X_UPA_CONFIG_SPIQS))
                    907:                 | (stp220x->tme_stp220x_sc_upa_config[upa_port]
                    908:                    & (TME_STP220X_UPA_CONFIG_SPRQS
                    909:                       | TME_STP220X_UPA_CONFIG_SPIQS)));
                    910:          }
                    911:          value32
                    912:            &= ~(TME_STP220X_UPA_CONFIG_SQUEN
                    913:                 | TME_STP220X_UPA_CONFIG_MBZ);
                    914:          stp220x->tme_stp220x_sc_upa_config[upa_port] = value32;
                    915:          break;
                    916:        case TME_STP220X_SC_UPA_STATUS(TME_STP220X_UPA_PORT_CPU(0)):
                    917:        case TME_STP220X_SC_UPA_STATUS(TME_STP220X_UPA_PORT_CPU(1)):
                    918:        case TME_STP220X_SC_UPA_STATUS(TME_STP220X_UPA_PORT_IO):
                    919:        case TME_STP220X_SC_UPA_STATUS(TME_STP220X_UPA_PORT_FFB):
                    920:          stp220x->tme_stp220x_sc_upa_status[upa_port]
                    921:            &= ~(value32
                    922:                 & (TME_STP220X_UPA_STATUS_FATAL
                    923:                    | TME_STP220X_UPA_STATUS_IADDR
                    924:                    | TME_STP220X_UPA_STATUS_IPORT
                    925:                    | TME_STP220X_UPA_STATUS_IPRTY
                    926:                    | TME_STP220X_UPA_STATUS_MC0OF
                    927:                    | TME_STP220X_UPA_STATUS_MC1OF));
                    928:          break;
                    929:        case TME_STP2200_SC_MC_CONTROL0:
                    930:          stp220x->tme_stp2200_sc_mc_control[0]
                    931:            = (value32
                    932:               & ~((((tme_uint32_t) 2) << 30) - (1 << 16)));
                    933:          break;
                    934:        case TME_STP2200_SC_MC_CONTROL1:
                    935:          stp220x->tme_stp2200_sc_mc_control[1]
                    936:            = (value32
                    937:               & ~((((tme_uint32_t) 2) << 31) - (1 << 13)));
                    938:          break;
                    939:        case TME_STP2202_SC_MEMCTRL(0x0):
                    940:        case TME_STP2202_SC_MEMCTRL(0x1):
                    941:        case TME_STP2202_SC_MEMCTRL(0x2):
                    942:        case TME_STP2202_SC_MEMCTRL(0x3):
                    943:        case TME_STP2202_SC_MEMCTRL(0x4):
                    944:        case TME_STP2202_SC_MEMCTRL(0x5):
                    945:        case TME_STP2202_SC_MEMCTRL(0x6):
                    946:        case TME_STP2202_SC_MEMCTRL(0x7):
                    947:        case TME_STP2202_SC_MEMCTRL(0x8):
                    948:        case TME_STP2202_SC_MEMCTRL(0x9):
                    949:        case TME_STP2202_SC_MEMCTRL(0xa):
                    950:        case TME_STP2202_SC_MEMCTRL(0xb):
                    951:        case TME_STP2202_SC_MEMCTRL(0xc):
                    952:        case TME_STP2202_SC_MEMCTRL(0xd):
                    953:          stp220x->tme_stp2202_sc_memctrl
                    954:            [(stp220x->tme_stp220x_eb_addr
                    955:              - TME_STP2202_SC_MEMCTRL(0x0))
                    956:             / (TME_STP2202_SC_MEMCTRL(0x1)
                    957:                - TME_STP2202_SC_MEMCTRL(0x0))]
                    958:            = value32;
                    959:          break;
                    960:        case TME_STP2202_SC_CC_DIAG:
                    961:          stp220x->tme_stp2202_sc_cc_diag
                    962:            = (value32
                    963:               & ~((2 << 14) - (1 << 0)));
                    964:          break;
                    965:        case TME_STP2202_SC_CC_FAULT:
                    966:          stp220x->tme_stp2202_sc_cc_fault
                    967:            = ((stp220x->tme_stp2202_sc_cc_fault
                    968:                | ((2 << 27) - (1 << 13)))      /* FLTIndex */
                    969:               & (value32
                    970:                  ^ ((1 << 31)          /* PERR0 */
                    971:                     | (1 << 30)        /* CERR0 */
                    972:                     | (1 << 29)        /* PERR1 */
                    973:                     | (1 << 28))));    /* CERR1 */
                    974:        case TME_STP2202_SC_CC_PROC_INDEX:
                    975:          stp220x->tme_stp2202_sc_cc_proc_index = value32;
                    976:          break;
                    977:        }
                    978:       }
                    979:     }
                    980: 
                    981:     /* otherwise, this must be a write to the PLL chip: */
                    982:     else {
                    983:       assert (address >= _tme_stp2210_mc124x9_subregion.tme_bus_subregion_address_first
                    984:              && address <= _tme_stp2210_mc124x9_subregion.tme_bus_subregion_address_last);
                    985: 
                    986:       /* we can ignore all writes to the PLL chip, except for a write
                    987:         to the PLL serial load and reset address, which is the first
                    988:         address: */
                    989:       if (address
                    990:          == (tme_bus_addr32_t) _tme_stp2210_mc124x9_subregion.tme_bus_subregion_address_first) {
                    991: 
                    992:        /* when the PLL serial load and reset address is written, the
                    993:           STP2210 asserts B_POR to the STP220x: */
                    994:        _tme_stp220x_reset(stp220x, TME_STP220X_SC_CONTROL_B_POR);
                    995:       }
                    996:     }
                    997:   }
                    998: 
                    999:   /* otherwise, this must be a read: */
                   1000:   else {
                   1001:     assert (cycle->tme_bus_cycle_type == TME_BUS_CYCLE_READ);
                   1002: 
                   1003:     /* if this is a read of EB_ADDR: */
                   1004:     if (address < sizeof(tme_uint32_t)) {
                   1005: 
                   1006:       /* return EB_ADDR: */
                   1007:       value8 = stp220x->tme_stp220x_eb_addr;
                   1008:     }
                   1009: 
                   1010:     /* otherwise, if this is a read of EB_DATA: */
                   1011:     else if (address < (2 * sizeof(tme_uint32_t))) {
                   1012: 
                   1013:       /* if this is a read of EB_DATA bits 24..31: */
                   1014:       if (address == sizeof(tme_uint32_t)) {
                   1015: 
                   1016:        /* dispatch on EB_ADDR: */
                   1017:        switch (stp220x->tme_stp220x_eb_addr) {
                   1018:        default:
                   1019:         /* case TME_STP220X_SC_DEBUG_PIN_CTRL: */
                   1020:        /* case TME_STP2202_SC_CC_SNPVEC: */
                   1021:          abort();
                   1022:        case TME_STP220X_SC_CONTROL:
                   1023:          value32 = stp220x->tme_stp220x_sc_control;
                   1024:          break;
                   1025:        case TME_STP220X_SC_ID:
                   1026:          value32
                   1027:            = (((TME_STP220X_IS_2200(stp220x)
                   1028:                 ? 0x3340
                   1029:                 : 0xacf1) << 16)
                   1030:               + ((TME_STP220X_IS_2200(stp220x)
                   1031:                   ? 3
                   1032:                   : 4) << 12)
                   1033:               + (1 << 4)
                   1034:               + (1 << 0));
                   1035:          break;
                   1036:        case TME_STP220X_SC_PERF(0):
                   1037:          value32 = stp220x->tme_stp220x_sc_perf[0];
                   1038:          stp220x->tme_stp220x_sc_perfshadow = stp220x->tme_stp220x_sc_perf[1];
                   1039:          break;
                   1040:        case TME_STP220X_SC_PERF(1):
                   1041:          value32 = stp220x->tme_stp220x_sc_perf[1];
                   1042:          stp220x->tme_stp220x_sc_perfshadow = stp220x->tme_stp220x_sc_perf[0];
                   1043:          break;
                   1044:        case TME_STP220X_SC_PERFSHADOW:
                   1045:          value32 = stp220x->tme_stp220x_sc_perfshadow;
                   1046:          break;
                   1047:        case TME_STP220X_SC_PERF_CTRL:
                   1048:          value32 = stp220x->tme_stp220x_sc_perf_ctrl;
                   1049:          break;
                   1050:        case TME_STP220X_SC_UPA_CONFIG(TME_STP220X_UPA_PORT_CPU(0)):
                   1051:        case TME_STP220X_SC_UPA_CONFIG(TME_STP220X_UPA_PORT_CPU(1)):
                   1052:        case TME_STP220X_SC_UPA_CONFIG(TME_STP220X_UPA_PORT_IO):
                   1053:        case TME_STP220X_SC_UPA_CONFIG(TME_STP220X_UPA_PORT_FFB):
                   1054:          value32 = stp220x->tme_stp220x_sc_upa_config[upa_port];
                   1055:          break;
                   1056:        case TME_STP220X_SC_UPA_STATUS(TME_STP220X_UPA_PORT_CPU(0)):
                   1057:        case TME_STP220X_SC_UPA_STATUS(TME_STP220X_UPA_PORT_CPU(1)):
                   1058:        case TME_STP220X_SC_UPA_STATUS(TME_STP220X_UPA_PORT_IO):
                   1059:        case TME_STP220X_SC_UPA_STATUS(TME_STP220X_UPA_PORT_FFB):
                   1060:          value32 = stp220x->tme_stp220x_sc_upa_status[upa_port];
                   1061:          break;
                   1062:        case TME_STP2200_SC_MC_CONTROL0:
                   1063:          value32 = stp220x->tme_stp2200_sc_mc_control[0];
                   1064:          break;
                   1065:        case TME_STP2200_SC_MC_CONTROL1:
                   1066:          value32 = stp220x->tme_stp2200_sc_mc_control[1];
                   1067:          break;
                   1068:        case TME_STP2202_SC_CC_DIAG:
                   1069:          value32 = stp220x->tme_stp2202_sc_cc_diag;
                   1070:          break;
                   1071:        case TME_STP2202_SC_CC_FAULT:
                   1072:          value32 = stp220x->tme_stp2202_sc_cc_fault;
                   1073:          break;
                   1074:        case TME_STP2202_SC_CC_PROC_INDEX:
                   1075:          value32 = stp220x->tme_stp2202_sc_cc_proc_index;
                   1076:          break;
                   1077:        case TME_STP2202_SC_MEMCTRL(0x0):
                   1078:        case TME_STP2202_SC_MEMCTRL(0x1):
                   1079:        case TME_STP2202_SC_MEMCTRL(0x2):
                   1080:        case TME_STP2202_SC_MEMCTRL(0x3):
                   1081:        case TME_STP2202_SC_MEMCTRL(0x4):
                   1082:        case TME_STP2202_SC_MEMCTRL(0x5):
                   1083:        case TME_STP2202_SC_MEMCTRL(0x6):
                   1084:        case TME_STP2202_SC_MEMCTRL(0x7):
                   1085:        case TME_STP2202_SC_MEMCTRL(0x8):
                   1086:        case TME_STP2202_SC_MEMCTRL(0x9):
                   1087:        case TME_STP2202_SC_MEMCTRL(0xa):
                   1088:        case TME_STP2202_SC_MEMCTRL(0xb):
                   1089:        case TME_STP2202_SC_MEMCTRL(0xc):
                   1090:        case TME_STP2202_SC_MEMCTRL(0xd):
                   1091:          value32
                   1092:            = (stp220x->tme_stp2202_sc_memctrl
                   1093:               [(stp220x->tme_stp220x_eb_addr
                   1094:                 - TME_STP2202_SC_MEMCTRL(0x0))
                   1095:                / (TME_STP2202_SC_MEMCTRL(0x1)
                   1096:                   - TME_STP2202_SC_MEMCTRL(0x0))]);
                   1097:          break;
                   1098:        }
                   1099: 
                   1100:        /* update the EB_DATA value: */
                   1101:        stp220x->tme_stp220x_eb_data[3] = value32;
                   1102:        value32 >>= 8;
                   1103:        stp220x->tme_stp220x_eb_data[2] = value32;
                   1104:        value32 >>= 8;
                   1105:        stp220x->tme_stp220x_eb_data[1] = value32;
                   1106:        value32 >>= 8;
                   1107:        stp220x->tme_stp220x_eb_data[0] = value32;
                   1108:       }
                   1109: 
                   1110:       /* return the EB_DATA byte: */
                   1111:       value8 = stp220x->tme_stp220x_eb_data[address % sizeof(tme_uint32_t)];
                   1112:     }
                   1113:      
                   1114:     /* return the value: */
                   1115:     tme_bus_cycle_xfer_memory(cycle,
                   1116:                              &value8 - address,
                   1117:                              address);
                   1118:   }
                   1119: 
                   1120:   /* leave: */
                   1121:   completion->tme_completion_error = TME_OK;
                   1122:   _tme_stp220x_completion_validate(stp220x, completion);
                   1123:   _tme_stp220x_leave(stp220x);
                   1124: 
                   1125:   /* ebus cycles can never be fast: */
                   1126:   *_master_fast_cycle_types = 0;
                   1127: }
                   1128: 
                   1129: /* this fills a TLB entry for the ebus connection: */
                   1130: static void
                   1131: _tme_stp220x_ebus_tlb_fill(struct tme_bus_connection *ebus_conn_bus,
                   1132:                           struct tme_bus_tlb *tlb,
                   1133:                           tme_bus_addr_t address_wider,
                   1134:                           unsigned int cycle_type)
                   1135: {
                   1136: 
                   1137:   /* initialize the TLB entry: */
                   1138:   tme_bus_tlb_initialize(tlb);
                   1139: 
                   1140:   /* this TLB entry covers only this address: */
                   1141:   /* XXX FIXME - this is because we're lazy and don't want to write
                   1142:      the bus cycle handler to size cycles down to a byte: */
                   1143:   tlb->tme_bus_tlb_addr_first = address_wider;
                   1144:   tlb->tme_bus_tlb_addr_last = address_wider;
                   1145: }
                   1146: 
                   1147: #if TME_STP22XX_BUS_TRANSITION
                   1148: 
                   1149: /* this is the bus signal transition glue: */
                   1150: static int
                   1151: _tme_stp220x_signal_transition(struct tme_bus_connection *agent_conn_bus,
                   1152:                               unsigned int signal)
                   1153: {
                   1154:   struct tme_completion completion_buffer;
                   1155:   tme_completion_init(&completion_buffer);
                   1156:   _tme_stp220x_signal(agent_conn_bus,
                   1157:                      signal,
                   1158:                      &completion_buffer);
                   1159:   return (TME_OK);
                   1160: }
                   1161: #define _tme_stp220x_signal _tme_stp220x_signal_transition
                   1162: 
                   1163: /* this is the bus cycle transition glue: */
                   1164: static int
                   1165: _tme_stp220x_cycle_transition(void *_master_conn_bus,
                   1166:                              struct tme_bus_cycle *master_cycle)
                   1167: {
                   1168:   struct tme_completion completion_buffer;
                   1169:   tme_uint32_t master_fast_cycle_types;
                   1170:   tme_completion_init(&completion_buffer);
                   1171:   _tme_stp220x_cycle((struct tme_bus_connection *) _master_conn_bus,
                   1172:                     master_cycle,
                   1173:                     &master_fast_cycle_types,
                   1174:                     &completion_buffer);
                   1175:   return (completion_buffer.tme_completion_error);
                   1176: }
                   1177: 
                   1178: /* this is the bus TLB fill transition glue: */
                   1179: static int
                   1180: _tme_stp220x_tlb_fill_transition(struct tme_bus_connection *agent_conn_bus,
                   1181:                                 struct tme_bus_tlb *tlb,
                   1182:                                 tme_bus_addr_t agent_address_wider,
                   1183:                                 unsigned int cycle_type)
                   1184: {
                   1185:   _tme_stp220x_tlb_fill(agent_conn_bus,
                   1186:                        tlb,
                   1187:                        agent_address_wider,
                   1188:                        cycle_type);
                   1189: 
                   1190:   /* we always handle any slow cycles: */
                   1191:   tlb->tme_bus_tlb_cycles_ok |= cycle_type;
                   1192:   tlb->tme_bus_tlb_addr_offset = 0;
                   1193:   tlb->tme_bus_tlb_addr_shift = 0;
                   1194:   tlb->tme_bus_tlb_cycle = _tme_stp220x_cycle_transition;
                   1195:   tlb->tme_bus_tlb_cycle_private = agent_conn_bus;
                   1196:   assert (tlb->tme_bus_tlb_fault_handler_count == 0);
                   1197: 
                   1198:   return (TME_OK);
                   1199: }
                   1200: #define _tme_stp220x_tlb_fill _tme_stp220x_tlb_fill_transition
                   1201: 
                   1202: /* this is the ebus cycle transition glue: */
                   1203: static int
                   1204: _tme_stp220x_ebus_cycle_transition(void *_ebus_conn_bus,
                   1205:                                   struct tme_bus_cycle *cycle)
                   1206: {
                   1207:   struct tme_completion completion_buffer;
                   1208:   tme_uint32_t master_fast_cycle_types;
                   1209:   tme_completion_init(&completion_buffer);
                   1210:   _tme_stp220x_ebus_cycle((struct tme_bus_connection *) _ebus_conn_bus,
                   1211:                          cycle,
                   1212:                          &master_fast_cycle_types,
                   1213:                          &completion_buffer);
                   1214:   return (completion_buffer.tme_completion_error);
                   1215: }
                   1216: 
                   1217: /* this is the ebus TLB fill transition glue: */
                   1218: static int
                   1219: _tme_stp220x_ebus_tlb_fill_transition(struct tme_bus_connection *ebus_conn_bus,
                   1220:                                      struct tme_bus_tlb *tlb,
                   1221:                                      tme_bus_addr_t address_wider,
                   1222:                                      unsigned int cycle_type)
                   1223: {
                   1224:   _tme_stp220x_ebus_tlb_fill(ebus_conn_bus,
                   1225:                             tlb,
                   1226:                             address_wider,
                   1227:                             cycle_type);
                   1228: 
                   1229:   /* allow reading and writing: */
                   1230:   tlb->tme_bus_tlb_cycles_ok = TME_BUS_CYCLE_READ | TME_BUS_CYCLE_WRITE;
                   1231: 
                   1232:   /* our bus cycle handler: */
                   1233:   tlb->tme_bus_tlb_cycle_private = ebus_conn_bus;
                   1234:   tlb->tme_bus_tlb_cycle = _tme_stp220x_ebus_cycle_transition;
                   1235: 
                   1236:   return (TME_OK);
                   1237: }
                   1238: #define _tme_stp220x_ebus_tlb_fill _tme_stp220x_ebus_tlb_fill_transition
                   1239: 
                   1240: #endif /* TME_STP22XX_BUS_TRANSITION */
                   1241: 
                   1242: /* our command function: */
                   1243: static int
                   1244: _tme_stp220x_command(struct tme_element *element,
                   1245:                     const char * const * args,
                   1246:                     char **_output)
                   1247: {
                   1248:   struct tme_bus_connection dummy_conn_bus;
                   1249:   struct tme_stp220x *stp220x;
                   1250:   int do_reset;
                   1251: 
                   1252:   /* enter: */
                   1253:   dummy_conn_bus.tme_bus_connection.tme_connection_element = element;
                   1254:   stp220x = _tme_stp220x_enter_bus(&dummy_conn_bus);
                   1255: 
                   1256:   /* assume no reset: */
                   1257:   do_reset = FALSE;
                   1258: 
                   1259:   /* the "power" command: */
                   1260:   if (TME_ARG_IS(args[1], "power")
                   1261:       && args[2] == NULL) {
                   1262:     _tme_stp220x_reset(stp220x, TME_STP220X_SC_CONTROL_POR);
                   1263:   }
                   1264: 
                   1265:   /* the "reset" command: */
                   1266:   else if (TME_ARG_IS(args[1], "reset")
                   1267:           && args[2] == NULL) {
                   1268:     _tme_stp220x_reset(stp220x, TME_STP220X_SC_CONTROL_B_XIR);
                   1269:   }
                   1270: 
                   1271:   /* any other command: */
                   1272:   else {
                   1273:     if (args[1] != NULL) {
                   1274:       tme_output_append_error(_output,
                   1275:                              "%s '%s', ",
                   1276:                              _("unknown command"),
                   1277:                              args[1]);
                   1278:     }
                   1279:     tme_output_append_error(_output,
                   1280:                            _("available %s commands: %s %s"),
                   1281:                            args[0],
                   1282:                            "power",
                   1283:                            "reset");
                   1284:     return (EINVAL);
                   1285:   }
                   1286: 
                   1287:   /* leave: */
                   1288:   _tme_stp220x_leave(stp220x);
                   1289:   return (TME_OK);
                   1290: }
                   1291: 
                   1292: /* the connection scorer: */
                   1293: static int
                   1294: _tme_stp220x_connection_score(struct tme_connection *conn,
                   1295:                              unsigned int *_score)
                   1296: {
                   1297:   struct tme_bus_connection *conn_bus;
                   1298:   struct tme_stp220x *stp220x;
                   1299:   struct tme_upa_bus_connection *conn_upa_other;
                   1300:   struct tme_bus_connection *conn_bus_other;
                   1301:   unsigned int score;
                   1302: 
                   1303:   /* recover the bus connection: */
                   1304:   conn_bus = (struct tme_bus_connection *) conn;
                   1305: 
                   1306:   /* enter: */
                   1307:   stp220x = _tme_stp220x_enter_bus(conn_bus);
                   1308: 
                   1309:   /* assume that this connection is useless: */
                   1310:   score = 0;
                   1311: 
                   1312:   /* dispatch on the connection type: */
                   1313:   conn_upa_other = (struct tme_upa_bus_connection *) conn->tme_connection_other;
                   1314:   conn_bus_other = (struct tme_bus_connection *) conn->tme_connection_other;
                   1315:   switch (conn->tme_connection_type) {
                   1316: 
                   1317:     /* this must be a UPA agent, and not another controller: */
                   1318:   case TME_CONNECTION_BUS_UPA:
                   1319:     if (conn_upa_other->tme_upa_bus_connection.tme_bus_tlb_set_add == NULL
                   1320:        && conn_upa_other->tme_upa_bus_interrupt != NULL) {
                   1321:       score = 10;
                   1322:     }
                   1323:     break;
                   1324: 
                   1325:     /* the ebus connection must be to a bus, not an agent.  FFB and
                   1326:        memory connections must be to agents, not buses: */
                   1327:   case TME_CONNECTION_BUS_GENERIC:
                   1328:     if ((conn_bus_other->tme_bus_tlb_set_add != NULL)
                   1329:        == (conn->tme_connection_id == TME_STP220X_CONN_EBUS)) {
                   1330:       score = 1;
                   1331:     }
                   1332:     break;
                   1333: 
                   1334:   default: abort();
                   1335:   }
                   1336: 
                   1337:   /* leave: */
                   1338:   _tme_stp220x_leave(stp220x);
                   1339:   *_score = score;
                   1340:   return (TME_OK);
                   1341: }
                   1342: 
                   1343: /* this makes a new connection: */
                   1344: static int
                   1345: _tme_stp220x_connection_make(struct tme_connection *conn, unsigned int state)
                   1346: {
                   1347:   struct tme_upa_bus_connection *conn_upa;
                   1348:   struct tme_bus_connection *conn_bus;
                   1349:   struct tme_stp220x *stp220x;
                   1350:   unsigned int conn_index;
                   1351:   const struct tme_bus_connection *conn_bus_other;
                   1352:   tme_bus_addr64_t slave_address_last;
                   1353: 
                   1354:   /* ignore a half-connection: */
                   1355:   if (state == TME_CONNECTION_HALF) {
                   1356:     return (TME_OK);
                   1357:   }
                   1358: 
                   1359:   /* recover the bus connection: */
                   1360:   conn_upa = (struct tme_upa_bus_connection *) conn;
                   1361:   conn_bus = (struct tme_bus_connection *) conn;
                   1362: 
                   1363:   /* enter: */
                   1364:   stp220x = _tme_stp220x_enter_bus(conn_bus);
                   1365: 
                   1366:   /* dispatch on the connection index: */
                   1367:   conn_index = conn->tme_connection_id;
                   1368:   switch (conn_index) {
                   1369:   default: assert (FALSE);
                   1370:   case TME_STP220X_CONN_UPA_PORT(TME_STP220X_UPA_PORT_CPU(0)):
                   1371:   case TME_STP220X_CONN_UPA_PORT(TME_STP220X_UPA_PORT_CPU(1)):
                   1372:   case TME_STP220X_CONN_UPA_PORT(TME_STP220X_UPA_PORT_IO):
                   1373:     stp220x->tme_stp220x.tme_stp22xx_conns[conn_index].tme_stp22xx_conn_upa = conn_upa;
                   1374:     break;
                   1375:   case TME_STP220X_CONN_UPA_PORT(TME_STP220X_UPA_PORT_FFB):
                   1376:   case TME_STP220X_CONN_SIMM_GROUP(0):
                   1377:   case TME_STP220X_CONN_SIMM_GROUP(1):
                   1378:   case TME_STP220X_CONN_SIMM_GROUP(2):
                   1379:   case TME_STP220X_CONN_SIMM_GROUP(3):
                   1380: #if TME_STP220X_SIMM_GROUP_COUNT != 4
                   1381: #error "TME_STP220X_SIMM_GROUP_COUNT changed"
                   1382: #endif
                   1383:     conn_bus_other = (struct tme_bus_connection *) conn_bus->tme_bus_connection.tme_connection_other;
                   1384:     slave_address_last = conn_bus_other->tme_bus_subregions.tme_bus_subregion_address_last;
                   1385:     stp220x->tme_stp220x_conn_address_last[conn_index] = slave_address_last;
                   1386:     assert (conn_bus_other->tme_bus_subregions.tme_bus_subregion_address_first == 0);
                   1387:     assert (slave_address_last > 0
                   1388:            && (((slave_address_last + 1) & slave_address_last) == 0)
                   1389:            && (conn_index == TME_STP220X_CONN_UPA_PORT(TME_STP220X_UPA_PORT_FFB)
                   1390:                || slave_address_last < (((tme_uint32_t) 1) << TME_STP220X_SIMM_GROUP_SIZE_LOG2(stp220x))));
                   1391:     assert (conn_bus_other->tme_bus_subregions.tme_bus_subregion_next == NULL);
                   1392:   case TME_STP220X_CONN_EBUS:
                   1393:     stp220x->tme_stp220x.tme_stp22xx_conns[conn_index].tme_stp22xx_conn_bus = conn_bus;
                   1394:     break;
                   1395:   }
                   1396: 
                   1397:   /* leave: */
                   1398:   _tme_stp220x_leave(stp220x);
                   1399:   return (TME_OK);
                   1400: }
                   1401: 
                   1402: /* this breaks a connection: */
                   1403: static int 
                   1404: _tme_stp220x_connection_break(struct tme_connection *conn, unsigned int state)
                   1405: {
                   1406:   abort();
                   1407: }
                   1408: 
                   1409: /* this makes new connection sides: */
                   1410: static int
                   1411: _tme_stp220x_connections_new(struct tme_element *element,
                   1412:                             const char * const *args,
                   1413:                             struct tme_connection **_conns,
                   1414:                             char **_output)
                   1415: {
                   1416:   int rc;
                   1417:   struct tme_stp220x *stp220x;
                   1418:   struct tme_upa_bus_connection *conn_upa;
                   1419:   struct tme_bus_connection *conn_bus;
                   1420:   struct tme_connection *conn;
                   1421:   tme_bus_addr_t address;
                   1422:   unsigned int conn_index;
                   1423:   tme_bus_addr64_t region_size_m1;
                   1424: 
                   1425:   /* assume that we will succeed: */
                   1426:   rc = TME_OK;
                   1427: 
                   1428:   /* recover our data structure: */
                   1429:   stp220x = (struct tme_stp220x *) element->tme_element_private;
                   1430: 
                   1431:   /* lock the mutex: */
                   1432:   tme_mutex_lock(&stp220x->tme_stp220x.tme_stp22xx_mutex);
                   1433: 
                   1434:   /* if we have no arguments, this is the ebus connection: */
                   1435:   if (args[1] == NULL) {
                   1436: 
                   1437:     /* if an ebus connection has already been made: */
                   1438:     if (stp220x->tme_stp220x.tme_stp22xx_conns[TME_STP220X_CONN_EBUS].tme_stp22xx_conn_bus != NULL) {
                   1439:       rc = EEXIST;
                   1440:     }
                   1441: 
                   1442:     /* otherwise, the ebus connection hasn't already been made: */
                   1443:     else {
                   1444: 
                   1445:       /* create our side of a generic bus connection: */
                   1446:       conn_bus = tme_new0(struct tme_bus_connection, 1);
                   1447:       conn_bus->tme_bus_connection.tme_connection_type = TME_CONNECTION_BUS_GENERIC;
                   1448: 
                   1449:       /* fill in the generic bus connection: */
                   1450:       conn_bus->tme_bus_subregions.tme_bus_subregion_address_first = 0;
                   1451:       conn_bus->tme_bus_subregions.tme_bus_subregion_address_last = (sizeof(tme_uint32_t) * 2) - 1;
                   1452:       conn_bus->tme_bus_subregions.tme_bus_subregion_next = &_tme_stp2210_mc124x9_subregion;
                   1453:       conn_bus->tme_bus_signals_add = NULL;
                   1454:       conn_bus->tme_bus_signal = NULL;
                   1455:       conn_bus->tme_bus_intack = NULL;
                   1456:       conn_bus->tme_bus_tlb_set_add = NULL;
                   1457:       conn_bus->tme_bus_tlb_fill = _tme_stp220x_ebus_tlb_fill;
                   1458: 
                   1459:       /* fill in the generic connection: */
                   1460:       conn = &conn_bus->tme_bus_connection;
                   1461:       conn->tme_connection_id = TME_STP220X_CONN_EBUS;
                   1462:       conn->tme_connection_score = _tme_stp220x_connection_score;
                   1463:       conn->tme_connection_make = _tme_stp220x_connection_make;
                   1464:       conn->tme_connection_break = _tme_stp220x_connection_break;
                   1465: 
                   1466:       /* add in this connection side possibility: */
                   1467:       conn->tme_connection_next = *_conns;
                   1468:       *_conns = conn;
                   1469:     }
                   1470:   }
                   1471: 
                   1472:   /* otherwise, if this is a UPA bus connection: */
                   1473:   else if (TME_ARG_IS(args[1], "addr")
                   1474:           && ((address
                   1475:                = tme_bus_addr_parse(args[2], 0 - (tme_uint64_t) 1))
                   1476:               != (0 - (tme_uint64_t) 1))
                   1477:           && args[3] == NULL) {
                   1478: 
                   1479:     /* convert the address into a connection index and address: */
                   1480:     conn_index = _tme_stp220x_lookup_address(stp220x, &address, &region_size_m1);
                   1481: 
                   1482:     /* if this connection is reserved: */
                   1483:     if (conn_index == TME_STP220X_CONN_NULL) {
                   1484:       rc = EINVAL;
                   1485:     }
                   1486: 
                   1487:     /* otherwise, if this connection is already made: */
                   1488:     else if (stp220x->tme_stp220x.tme_stp22xx_conns[conn_index].tme_stp22xx_conn_bus != NULL) {
                   1489:       rc = EEXIST;
                   1490:     }
                   1491: 
                   1492:     /* otherwise, this connection hasn't been made yet: */
                   1493:     else {
                   1494: 
                   1495:       /* if this is a CPU or IO connection: */
                   1496:       if (conn_index == TME_STP220X_CONN_UPA_PORT(TME_STP220X_UPA_PORT_IO)
                   1497:          || conn_index == TME_STP220X_CONN_UPA_PORT(TME_STP220X_UPA_PORT_CPU(0))
                   1498:          || conn_index == TME_STP220X_CONN_UPA_PORT(TME_STP220X_UPA_PORT_CPU(1))) {
                   1499: 
                   1500:        /* create our side of a UPA connection: */
                   1501:        conn_upa = tme_new0(struct tme_upa_bus_connection, 1);
                   1502:        conn_upa->tme_upa_bus_interrupt = _tme_stp220x_interrupt;
                   1503:        conn_upa->tme_upa_bus_connection_mid = _tme_stp220x_conn_index_mid(stp220x, conn_index);
                   1504:        conn_bus = &conn_upa->tme_upa_bus_connection;
                   1505:        conn_bus->tme_bus_connection.tme_connection_type = TME_CONNECTION_BUS_UPA;
                   1506:       }
                   1507: 
                   1508:       /* otherwise, this is an FFB or memory connection: */
                   1509:       else {
                   1510: 
                   1511:        /* create our side of a generic bus connection: */
                   1512:        conn_bus = tme_new0(struct tme_bus_connection, 1);
                   1513:        conn_bus->tme_bus_connection.tme_connection_type = TME_CONNECTION_BUS_GENERIC;
                   1514:       }
                   1515: 
                   1516:       /* fill in the generic bus connection: */
                   1517:       conn_bus->tme_bus_signals_add = NULL;
                   1518:       conn_bus->tme_bus_signal = _tme_stp220x_signal;
                   1519:       conn_bus->tme_bus_intack = NULL;
                   1520:       conn_bus->tme_bus_tlb_set_add = tme_stp22xx_tlb_set_add;
                   1521:       conn_bus->tme_bus_tlb_fill = _tme_stp220x_tlb_fill;
                   1522: 
                   1523:       /* fill in the generic connection: */
                   1524:       conn = &conn_bus->tme_bus_connection;
                   1525:       conn->tme_connection_id = conn_index;
                   1526:       conn->tme_connection_score = _tme_stp220x_connection_score;
                   1527:       conn->tme_connection_make = _tme_stp220x_connection_make;
                   1528:       conn->tme_connection_break = _tme_stp220x_connection_break;
                   1529: 
                   1530:       /* add in this connection side possibility: */
                   1531:       conn->tme_connection_next = *_conns;
                   1532:       *_conns = conn;
                   1533:     }
                   1534:   }
                   1535: 
                   1536:   /* otherwise, the arguments are unknown: */
                   1537:   else {
                   1538:     tme_output_append_error(_output, 
                   1539:                            "%s %s [ addr %s ]",
                   1540:                            _("usage:"),
                   1541:                            args[0],
                   1542:                            _("BUS-ADDRESS"));
                   1543:     rc = EINVAL;
                   1544:   }
                   1545: 
                   1546:   /* unlock the mutex: */
                   1547:   tme_mutex_unlock(&stp220x->tme_stp220x.tme_stp22xx_mutex);
                   1548: 
                   1549:   return (rc);
                   1550: }
                   1551: 
                   1552: /* this creates a new stp220x element: */
                   1553: static int
                   1554: _tme_stp220x_new(struct tme_element *element,
                   1555:                 const char * const *args,
                   1556:                 const void *extra,
                   1557:                 char **_output,
                   1558:                 unsigned int is_2200)
                   1559: {
                   1560:   struct tme_stp220x *stp220x;
                   1561:   int arg_i;
                   1562:   int usage;
                   1563: 
                   1564:   /* check our arguments: */
                   1565:   usage = 0;
                   1566:   arg_i = 1;
                   1567:   for (;;) {
                   1568: 
                   1569:     if (0) {
                   1570:     }
                   1571: 
                   1572:     /* if we ran out of arguments: */
                   1573:     else if (args[arg_i] == NULL) {
                   1574: 
                   1575:       break;
                   1576:     }
                   1577: 
                   1578:     /* otherwise this is a bad argument: */
                   1579:     else {
                   1580:       tme_output_append_error(_output,
                   1581:                              _("%s unexpected, "),
                   1582:                              args[arg_i]);
                   1583:       usage = TRUE;
                   1584:       break;
                   1585:     }
                   1586:   }
                   1587: 
                   1588:   if (usage) {
                   1589:     tme_output_append_error(_output, 
                   1590:                            "%s %s",
                   1591:                            _("usage:"),
                   1592:                            args[0]);
                   1593:     return (EINVAL);
                   1594:   }
                   1595: 
                   1596:   /* start the stp220x structure: */
                   1597:   stp220x = tme_new0(struct tme_stp220x, 1);
                   1598:   stp220x->tme_stp220x.tme_stp22xx_element = element;
                   1599:   stp220x->tme_stp220x.tme_stp22xx_run = _tme_stp220x_run;
                   1600:   tme_stp22xx_init(&stp220x->tme_stp220x,
                   1601:                   sizeof(struct tme_stp220x),
                   1602:                   TME_STP220X_CONN_NULL);
                   1603: 
                   1604:   /* set the type: */
                   1605:   stp220x->tme_stp220x_is_2200 = is_2200;
                   1606:   if (TME_STP220X_IS_2200(stp220x) != is_2200) {
                   1607:     tme_free(stp220x);
                   1608:     return (ENXIO);
                   1609:   }
                   1610: 
                   1611:   /* initialize the last address in each connection to all-bits-one: */
                   1612:   memset (stp220x->tme_stp220x_conn_address_last,
                   1613:          0xff,
                   1614:          sizeof(stp220x->tme_stp220x_conn_address_last));
                   1615: 
                   1616:   /* fill the element: */
                   1617:   element->tme_element_private = stp220x;
                   1618:   element->tme_element_connections_new = _tme_stp220x_connections_new;
                   1619:   element->tme_element_command = _tme_stp220x_command;
                   1620: 
                   1621:   return (TME_OK);
                   1622: }
                   1623: 
                   1624: /* this creates a new stp2200 element: */
                   1625: TME_ELEMENT_X_NEW_DECL(tme_ic_,stp22xx,stp2200) {
                   1626:   return (_tme_stp220x_new(element, args, extra, _output, TRUE));
                   1627: }

unix.superglobalmegacorp.com

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