Annotation of tme/ic/stp22xx/stp222x-stc.c, revision 1.1

1.1     ! root        1: /* $Id: stp222x-stc.c,v 1.4 2010/06/05 18:59:29 fredette Exp $ */
        !             2: 
        !             3: /* ic/stp222x-stc.c - emulation of the STC of the UPA to SBus
        !             4:    interface controller (STP2220) and the UPA to PCI interface
        !             5:    controller (STP2222): */
        !             6: 
        !             7: /*
        !             8:  * Copyright (c) 2009 Matt Fredette
        !             9:  * All rights reserved.
        !            10:  *
        !            11:  * Redistribution and use in source and binary forms, with or without
        !            12:  * modification, are permitted provided that the following conditions
        !            13:  * are met:
        !            14:  * 1. Redistributions of source code must retain the above copyright
        !            15:  *    notice, this list of conditions and the following disclaimer.
        !            16:  * 2. Redistributions in binary form must reproduce the above copyright
        !            17:  *    notice, this list of conditions and the following disclaimer in the
        !            18:  *    documentation and/or other materials provided with the distribution.
        !            19:  * 3. All advertising materials mentioning features or use of this software
        !            20:  *    must display the following acknowledgement:
        !            21:  *      This product includes software developed by Matt Fredette.
        !            22:  * 4. The name of the author may not be used to endorse or promote products
        !            23:  *    derived from this software without specific prior written permission.
        !            24:  *
        !            25:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
        !            26:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
        !            27:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
        !            28:  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
        !            29:  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
        !            30:  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
        !            31:  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            32:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
        !            33:  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
        !            34:  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
        !            35:  * POSSIBILITY OF SUCH DAMAGE.
        !            36:  */
        !            37: 
        !            38: #include <tme/common.h>
        !            39: _TME_RCSID("$Id: stp222x-stc.c,v 1.4 2010/06/05 18:59:29 fredette Exp $");
        !            40: 
        !            41: /* includes: */
        !            42: #include "stp222x-impl.h"
        !            43: 
        !            44: /* macros: */
        !            45: 
        !            46: /* streaming buffer register offsets: */
        !            47: #define TME_STP222X_STC_REGGROUP_INDEX_CR              TME_STP222X_REGGROUP_INDEX(0x00)
        !            48: #define TME_STP222X_STC_REGGROUP_INDEX_PGFLUSH         TME_STP222X_REGGROUP_INDEX(0x08)
        !            49: #define TME_STP222X_STC_REGGROUP_INDEX_FLUSHSYNC       TME_STP222X_REGGROUP_INDEX(0x10)
        !            50: 
        !            51: /* an STC control register: */
        !            52: #define TME_STP222X_STC_CR_LPTR                                ((2 << 7) - (1 << 4))
        !            53: #define TME_STP222X_STC_CR_LE                          (1 << 3)
        !            54: #define TME_STP222X_STC_CR_RR_DIS                      (1 << 2)
        !            55: #define TME_STP222X_STC_CR_DE                          (1 << 1)
        !            56: #define TME_STP222X_STC_CR_SB_EN                       (1 << 0)
        !            57: 
        !            58: /* the size of the stp222x flush blocks: */
        !            59: #define TME_STP2220_STC_FLUSHSYNC_SIZE                 ((tme_uint64_t) 4)
        !            60: #define TME_STP2222_STC_FLUSHSYNC_SIZE                 ((tme_uint64_t) 64)
        !            61: 
        !            62: /* the number of entries in each streaming buffer: */
        !            63: #define TME_STP222X_STC_ENTRY_COUNT                    (16)
        !            64: 
        !            65: /* this flushes a streaming cache: */
        !            66: int
        !            67: tme_stp222x_stc_flush(struct tme_stp222x *stp222x)
        !            68: {
        !            69:   struct tme_stp222x_stc *stc;
        !            70:   tme_uint64_t address;
        !            71:   struct tme_bus_tlb *tlb;
        !            72:   struct tme_bus_connection *slave_conn_bus;
        !            73:   struct tme_bus_connection *slave_conn_bus_other;
        !            74: #if TME_STP22XX_BUS_TRANSITION
        !            75:   int rc;
        !            76: #endif /* TME_STP22XX_BUS_TRANSITION */
        !            77:   tme_shared tme_uint8_t *memory;
        !            78: 
        !            79:   stc = &stp222x->tme_stp222x_stcs[0];
        !            80:   if (!stc->tme_stp222x_stc_pgflush) {
        !            81:     stc = &stp222x->tme_stp222x_stcs[1];
        !            82:     if (!stc->tme_stp222x_stc_pgflush) {
        !            83:       return (FALSE);
        !            84:     }
        !            85:   }
        !            86: 
        !            87:   /* get the flushsync address: */
        !            88:   address
        !            89:     = (stc->tme_stp222x_stc_flushsync
        !            90:        & (TME_STP222X_IS_2220(stp222x)
        !            91:          ? ((((tme_uint64_t) 2) << 40)
        !            92:             - TME_STP2220_STC_FLUSHSYNC_SIZE)
        !            93:          : ((((tme_uint64_t) 2) << 40)
        !            94:             - TME_STP2222_STC_FLUSHSYNC_SIZE)));
        !            95: 
        !            96:   /* busy the flushsync TLB: */
        !            97:   tlb = &stc->tme_stp222x_stc_flushsync_tlb;
        !            98:   tme_bus_tlb_busy(tlb);
        !            99: 
        !           100:   /* if the flushsync TLB is invalid or doesn't apply: */
        !           101:   if (tme_bus_tlb_is_invalid(tlb)
        !           102:       || address < (tme_bus_addr64_t) tlb->tme_bus_tlb_addr_first
        !           103:       || address > (tme_bus_addr64_t) tlb->tme_bus_tlb_addr_last) {
        !           104: 
        !           105:     /* unbusy the flushsync TLB for filling: */
        !           106:     tme_bus_tlb_unbusy_fill(tlb);
        !           107: 
        !           108:     /* busy the UPA connection: */
        !           109:     slave_conn_bus = tme_stp222x_slave_busy_bus(stp222x, TME_STP222X_CONN_UPA);
        !           110: 
        !           111:     /* leave: */
        !           112:     tme_stp222x_leave(stp222x);
        !           113: 
        !           114:     /* fill the TLB entry: */
        !           115:     slave_conn_bus_other = (struct tme_bus_connection *) slave_conn_bus->tme_bus_connection.tme_connection_other;
        !           116: #if TME_STP22XX_BUS_TRANSITION
        !           117:      rc =
        !           118: #endif /* TME_STP22XX_BUS_TRANSITION */
        !           119:      (*slave_conn_bus_other->tme_bus_tlb_fill)
        !           120:        (slave_conn_bus_other,
        !           121:        tlb,
        !           122:        address,
        !           123:        TME_BUS_CYCLE_WRITE);
        !           124: #if TME_STP22XX_BUS_TRANSITION
        !           125:      assert (rc == TME_OK);
        !           126: #endif /* TME_STP22XX_BUS_TRANSITION */
        !           127: 
        !           128:      /* reenter: */
        !           129:      stp222x = tme_stp222x_enter_bus(slave_conn_bus);
        !           130: 
        !           131:      /* unbusy the UPA connection: */
        !           132:      tme_stp222x_slave_unbusy(stp222x);
        !           133: 
        !           134:      return (TRUE);
        !           135:   }
        !           136: 
        !           137:   /* the flushsync TLB must allow fast writing of the entire block: */
        !           138:   memory = tlb->tme_bus_tlb_emulator_off_write;
        !           139:   assert (memory != TME_EMULATOR_OFF_UNDEF
        !           140:          && ((address
        !           141:               + (TME_STP222X_IS_2220(stp222x)
        !           142:                  ? TME_STP2220_STC_FLUSHSYNC_SIZE
        !           143:                  : TME_STP2222_STC_FLUSHSYNC_SIZE)
        !           144:               - 1)
        !           145:              <= (tme_bus_addr64_t) tlb->tme_bus_tlb_addr_last));
        !           146: 
        !           147:   /* write the flush doublewords: */
        !           148:   memory += address;
        !           149: 
        !           150:   /* if this is an stp2220: */
        !           151:   if (TME_STP222X_IS_2220(stp222x)) {
        !           152: 
        !           153:     /* the stp2220 only writes four bytes: */
        !           154:     tme_memory_atomic_write32(((tme_shared tme_uint32_t *) memory) + 0,
        !           155:                              tme_htobe_u32(1),
        !           156:                              tlb->tme_bus_tlb_rwlock,
        !           157:                              sizeof(tme_uint32_t));
        !           158:   }
        !           159: 
        !           160:   /* otherwise, this is an stp2222: */
        !           161:   else {
        !           162: 
        !           163:     /* the stp2222 writes 64 bytes: */
        !           164: 
        !           165:     /* XXX FIXME - all of these doublewords are actually written as
        !           166:        one atomic transaction.  the best we can do is either 64- or
        !           167:        128-bit atomic writes: */
        !           168: #ifdef tme_memory_atomic_write128
        !           169:     tme_memory_atomic_write128(((tme_shared tme_uint128_t *) memory) + 0,
        !           170:                               tme_htobe_u128(((tme_uint128_t) 1) << (128 - 32)),
        !           171:                               tlb->tme_bus_tlb_rwlock,
        !           172:                               sizeof(tme_uint128_t));
        !           173:     tme_memory_atomic_write128(((tme_shared tme_uint128_t *) memory) + 1,
        !           174:                               0,
        !           175:                               tlb->tme_bus_tlb_rwlock,
        !           176:                               sizeof(tme_uint128_t));
        !           177:     tme_memory_atomic_write128(((tme_shared tme_uint128_t *) memory) + 2,
        !           178:                               0,
        !           179:                               tlb->tme_bus_tlb_rwlock,
        !           180:                               sizeof(tme_uint128_t));
        !           181:     tme_memory_atomic_write128(((tme_shared tme_uint128_t *) memory) + 3,
        !           182:                               0,
        !           183:                               tlb->tme_bus_tlb_rwlock,
        !           184:                               sizeof(tme_uint128_t));
        !           185: #else  /* !tme_memory_atomic_write128 */
        !           186:     tme_memory_atomic_write64(((tme_shared tme_uint64_t *) memory) + 0,
        !           187:                              tme_htobe_u64(((tme_uint64_t) 1) << (64 - 32)),
        !           188:                              tlb->tme_bus_tlb_rwlock,
        !           189:                              sizeof(tme_uint64_t));
        !           190:     tme_memory_atomic_write64(((tme_shared tme_uint64_t *) memory) + 1,
        !           191:                              0,
        !           192:                              tlb->tme_bus_tlb_rwlock,
        !           193:                              sizeof(tme_uint64_t));
        !           194:     tme_memory_atomic_write64(((tme_shared tme_uint64_t *) memory) + 2,
        !           195:                              0,
        !           196:                              tlb->tme_bus_tlb_rwlock,
        !           197:                              sizeof(tme_uint64_t));
        !           198:     tme_memory_atomic_write64(((tme_shared tme_uint64_t *) memory) + 3,
        !           199:                              0,
        !           200:                              tlb->tme_bus_tlb_rwlock,
        !           201:                              sizeof(tme_uint64_t));
        !           202:     tme_memory_atomic_write64(((tme_shared tme_uint64_t *) memory) + 4,
        !           203:                              0,
        !           204:                              tlb->tme_bus_tlb_rwlock,
        !           205:                              sizeof(tme_uint64_t));
        !           206:     tme_memory_atomic_write64(((tme_shared tme_uint64_t *) memory) + 5,
        !           207:                              0,
        !           208:                              tlb->tme_bus_tlb_rwlock,
        !           209:                              sizeof(tme_uint64_t));
        !           210:     tme_memory_atomic_write64(((tme_shared tme_uint64_t *) memory) + 6,
        !           211:                              0,
        !           212:                              tlb->tme_bus_tlb_rwlock,
        !           213:                              sizeof(tme_uint64_t));
        !           214:     tme_memory_atomic_write64(((tme_shared tme_uint64_t *) memory) + 7,
        !           215:                              0,
        !           216:                              tlb->tme_bus_tlb_rwlock,
        !           217:                              sizeof(tme_uint64_t));
        !           218: #endif /* !tme_memory_atomic_write128 */
        !           219:   }
        !           220: 
        !           221:   /* unbusy the flushsync TLB: */
        !           222:   tme_bus_tlb_unbusy(tlb);
        !           223: 
        !           224:   /* the flush has been done: */
        !           225:   stc->tme_stp222x_stc_pgflush = FALSE;
        !           226: 
        !           227:   return (TRUE);
        !           228: }
        !           229: 
        !           230: /* the STC register handler: */
        !           231: void
        !           232: tme_stp222x_stc_regs(struct tme_stp222x *stp222x,
        !           233:                     unsigned long stc_i,
        !           234:                     struct tme_stp222x_reg *reg)
        !           235: {
        !           236:   struct tme_stp222x_stc *stc;
        !           237:   tme_uint32_t reggroup_index;
        !           238:   const char *name;
        !           239: 
        !           240:   /* get the streaming cache: */
        !           241:   stc = &stp222x->tme_stp222x_stcs[stc_i];
        !           242: 
        !           243:   /* get the register: */
        !           244:   reggroup_index = TME_STP222X_REGGROUP_INDEX(reg->tme_stp222x_reg_address);
        !           245: 
        !           246:   /* if this is a write: */
        !           247:   if (reg->tme_stp222x_reg_write) {
        !           248: 
        !           249:     /* dispatch on the register: */
        !           250:     switch (reggroup_index) {
        !           251: 
        !           252:     case TME_STP222X_STC_REGGROUP_INDEX_CR:
        !           253:       stc->tme_stp222x_stc_cr
        !           254:        = (reg->tme_stp222x_reg_value
        !           255:           & (TME_STP222X_STC_CR_LPTR
        !           256:              | TME_STP222X_STC_CR_LE
        !           257:              | TME_STP222X_STC_CR_RR_DIS
        !           258:              | TME_STP222X_STC_CR_DE
        !           259:              | TME_STP222X_STC_CR_SB_EN));
        !           260:       name = "CR";
        !           261:       break;
        !           262: 
        !           263:     case TME_STP222X_STC_REGGROUP_INDEX_PGFLUSH:
        !           264:       name = "PGFLUSH";
        !           265:       break;
        !           266: 
        !           267:     case TME_STP222X_STC_REGGROUP_INDEX_FLUSHSYNC:
        !           268:       stc->tme_stp222x_stc_flushsync = reg->tme_stp222x_reg_value;
        !           269:       stc->tme_stp222x_stc_pgflush = TRUE;
        !           270:       name = "FLUSHSYNC";
        !           271:       break;
        !           272: 
        !           273:     default:
        !           274:       return;
        !           275:     }
        !           276:   }
        !           277: 
        !           278:   /* otherwise, this is a read: */
        !           279:   else {
        !           280: 
        !           281:     /* dispatch on the register: */
        !           282:     switch (reggroup_index) {
        !           283:     case TME_STP222X_STC_REGGROUP_INDEX_CR:
        !           284:       reg->tme_stp222x_reg_value = stc->tme_stp222x_stc_cr;
        !           285:       name = "CR";
        !           286:       break;
        !           287:     case TME_STP222X_STC_REGGROUP_INDEX_PGFLUSH:
        !           288:     case TME_STP222X_STC_REGGROUP_INDEX_FLUSHSYNC:
        !           289:       reg->tme_stp222x_reg_completed = TRUE;
        !           290:       return;
        !           291:     default:
        !           292:       return;
        !           293:     }
        !           294:   }
        !           295: 
        !           296:   tme_log(TME_STP222X_LOG_HANDLE(stp222x), 2000, TME_OK,
        !           297:          (TME_STP222X_LOG_HANDLE(stp222x),
        !           298:           _("STC%lu %s %s 0x%" TME_PRIx64),
        !           299:           stc_i,
        !           300:           name,
        !           301:           (reg->tme_stp222x_reg_write
        !           302:            ? "<-"
        !           303:            : "->"),
        !           304:           reg->tme_stp222x_reg_value));
        !           305: 
        !           306:   /* this register access has been completed: */
        !           307:   reg->tme_stp222x_reg_completed = TRUE;
        !           308: }
        !           309: 
        !           310: /* the STC diagnostic register handler: */
        !           311: void
        !           312: tme_stp222x_stc_regs_diag(struct tme_stp222x *stp222x,
        !           313:                          unsigned long stc_i,
        !           314:                          struct tme_stp222x_reg *reg)
        !           315: {
        !           316:   struct tme_stp222x_stc *stc;
        !           317:   tme_uint32_t reggroup_0_3;
        !           318:   tme_uint32_t reggroup_index;
        !           319: 
        !           320:   /* get the streaming cache: */
        !           321:   stc = &stp222x->tme_stp222x_stcs[stc_i];
        !           322: 
        !           323:   /* get the register: */
        !           324:   reggroup_0_3 = TME_STP222X_REGGROUP_WHICH(reg->tme_stp222x_reg_address) & 0xf;
        !           325:   reggroup_index = TME_STP222X_REGGROUP_INDEX(reg->tme_stp222x_reg_address);
        !           326: 
        !           327:   /* if this is a write: */
        !           328:   if (reg->tme_stp222x_reg_write) {
        !           329: 
        !           330:     abort();
        !           331:   }
        !           332: 
        !           333:   /* otherwise, this is a read: */
        !           334:   else {
        !           335: 
        !           336:     switch (reggroup_0_3) {
        !           337:     case 0x8: /* STP2220 0x58, STP2222 0xb4 or 0xc4 */
        !           338:       if (__tme_predict_false(reggroup_index >= TME_STP222X_STC_ENTRY_COUNT)) {
        !           339:        abort();
        !           340:       }
        !           341:       reg->tme_stp222x_reg_value = 0;
        !           342:       break;
        !           343:     default:
        !           344:       abort();
        !           345:     }
        !           346:   }
        !           347: 
        !           348:   /* this register access has been completed: */
        !           349:   reg->tme_stp222x_reg_completed = TRUE;
        !           350: }
        !           351: 
        !           352: /* this initializes a streaming cache: */
        !           353: void
        !           354: tme_stp222x_stc_init(struct tme_stp222x_stc *stc)
        !           355: {
        !           356: 
        !           357:   /* initialize the flushsync TLB: */
        !           358:   tme_token_init(&stc->tme_stp222x_stc_flushsync_tlb_token);
        !           359:   stc->tme_stp222x_stc_flushsync_tlb.tme_bus_tlb_token = &stc->tme_stp222x_stc_flushsync_tlb_token;
        !           360: }

unix.superglobalmegacorp.com

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