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