Annotation of tme/ic/stp22xx/stp220x.c, revision 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.