|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.