|
|
1.1 ! root 1: /* $Id: sun-mie.c,v 1.2 2005/02/18 02:50:44 fredette Exp $ */ ! 2: ! 3: /* bus/multibus/sun_mie.c - implementation of the Sun Intel Ethernet Multibus emulation: */ ! 4: ! 5: /* ! 6: * Copyright (c) 2003 Matt Fredette ! 7: * All rights reserved. ! 8: * ! 9: * Redistribution and use in source and binary forms, with or without ! 10: * modification, are permitted provided that the following conditions ! 11: * are met: ! 12: * 1. Redistributions of source code must retain the above copyright ! 13: * notice, this list of conditions and the following disclaimer. ! 14: * 2. Redistributions in binary form must reproduce the above copyright ! 15: * notice, this list of conditions and the following disclaimer in the ! 16: * documentation and/or other materials provided with the distribution. ! 17: * 3. All advertising materials mentioning features or use of this software ! 18: * must display the following acknowledgement: ! 19: * This product includes software developed by Matt Fredette. ! 20: * 4. The name of the author may not be used to endorse or promote products ! 21: * derived from this software without specific prior written permission. ! 22: * ! 23: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR ! 24: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ! 25: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ! 26: * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, ! 27: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ! 28: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ! 29: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 30: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, ! 31: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ! 32: * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ! 33: * POSSIBILITY OF SUCH DAMAGE. ! 34: */ ! 35: ! 36: #include <tme/common.h> ! 37: _TME_RCSID("$Id: sun-mie.c,v 1.2 2005/02/18 02:50:44 fredette Exp $"); ! 38: ! 39: /* includes: */ ! 40: #include <tme/element.h> ! 41: #undef TME_BUS_VERSION ! 42: #define TME_BUS_VERSION TME_X_VERSION(0, 0) ! 43: #include <tme/generic/bus.h> ! 44: #undef TME_I825X6_VERSION ! 45: #define TME_I825X6_VERSION TME_X_VERSION(0, 0) ! 46: #include <tme/ic/i825x6.h> ! 47: ! 48: /* macros: */ ! 49: ! 50: /* the amount of memory on the board: */ ! 51: #define TME_SUN_MIE_MEMSIZE (256 * 1024) ! 52: ! 53: /* the board page size: */ ! 54: #define TME_SUN_MIE_PAGESIZE (1024) ! 55: ! 56: /* the number of page map entries: */ ! 57: #define TME_SUN_MIE_PGMAP_COUNT (1024) ! 58: ! 59: /* the number of active TLB entries we can have per page map entry: */ ! 60: #define TME_SUN_MIE_PGMAP_TLBS (4) ! 61: ! 62: /* register offsets and sizes: */ ! 63: #define TME_SUN_MIE_REG_PGMAP (0) ! 64: #define TME_SUN_MIE_SIZ_PGMAP (TME_SUN_MIE_PGMAP_COUNT * sizeof(tme_uint16_t)) ! 65: #define TME_SUN_MIE_REG_PROM (TME_SUN_MIE_REG_PGMAP + TME_SUN_MIE_SIZ_PGMAP) ! 66: #define TME_SUN_MIE_SIZ_PROM (32 * sizeof(tme_uint16_t)) ! 67: #define TME_SUN_MIE_REG_CSR (TME_SUN_MIE_REG_PROM + TME_SUN_MIE_SIZ_PROM) ! 68: #define TME_SUN_MIE_SIZ_CSR (sizeof(tme_uint16_t)) ! 69: #define TME_SUN_MIE_REG_PCR (TME_SUN_MIE_REG_CSR + TME_SUN_MIE_SIZ_CSR + sizeof(tme_uint16_t)) ! 70: #define TME_SUN_MIE_SIZ_PCR (sizeof(tme_uint16_t)) ! 71: #define TME_SUN_MIE_REG_PE_ALO (TME_SUN_MIE_REG_PCR + TME_SUN_MIE_SIZ_PCR) ! 72: #define TME_SUN_MIE_SIZ_PE_ALO (sizeof(tme_uint16_t)) ! 73: #define TME_SUN_MIE_SIZ_REGS (TME_SUN_MIE_REG_PE_ALO + TME_SUN_MIE_SIZ_PE_ALO) ! 74: ! 75: /* the bits in a pagemap entry: */ ! 76: #define TME_SUN_MIE_PGMAP_SWAB (0x8000) ! 77: /* 0x4000 unused */ ! 78: #define TME_SUN_MIE_PGMAP_P2MEM (0x2000) ! 79: /* 0x1000 unused */ ! 80: #define TME_SUN_MIE_PGMAP_PFNUM (0x0fff) ! 81: ! 82: /* the bits in the Control/Status Register: */ ! 83: #define TME_SUN_MIE_CSR_RESET (0x8000) ! 84: #define TME_SUN_MIE_CSR_NOLOOP (0x4000) ! 85: #define TME_SUN_MIE_CSR_CA (0x2000) ! 86: #define TME_SUN_MIE_CSR_IE (0x1000) ! 87: #define TME_SUN_MIE_CSR_PIE (0x0800) ! 88: /* 0x0400 unused */ ! 89: #define TME_SUN_MIE_CSR_PE (0x0200) ! 90: #define TME_SUN_MIE_CSR_INTR (0x0100) ! 91: /* 0x0080 unused */ ! 92: /* 0x0040 unused */ ! 93: #define TME_SUN_MIE_CSR_P2MEM (0x0020) ! 94: #define TME_SUN_MIE_CSR_BIGRAM (0x0010) ! 95: #define TME_SUN_MIE_CSR_MPMHI (0x000f) ! 96: #define TME_SUN_MIE_CSR_READONLY (0x0400 \ ! 97: | TME_SUN_MIE_CSR_PE \ ! 98: | TME_SUN_MIE_CSR_INTR \ ! 99: | 0x0080 \ ! 100: | 0x0040 \ ! 101: | TME_SUN_MIE_CSR_BIGRAM\ ! 102: | TME_SUN_MIE_CSR_MPMHI) ! 103: ! 104: /* the bits in the Parity Control Register: */ ! 105: #define TME_SUN_MIE_PCR_PEACK (0x0100) ! 106: #define TME_SUN_MIE_PCR_PESRC (0x0080) ! 107: #define TME_SUN_MIE_PCR_PEBYTE (0x0040) ! 108: /* 0x0020 unused */ ! 109: /* 0x0010 unused */ ! 110: #define TME_SUN_MIE_PCR_PE_AHI (0x000f) ! 111: #define TME_SUN_MIE_PCR_READONLY (~TME_SUN_MIE_PCR_PEACK) ! 112: ! 113: /* the size of the memory port: */ ! 114: #define TME_SUN_MIE_SIZ_MBM (0x10000) ! 115: ! 116: /* these get and put the CSR: */ ! 117: #define TME_SUN_MIE_CSR_GET(sun_mie) \ ! 118: tme_betoh_u16(*((tme_uint16_t *) &(sun_mie)->tme_sun_mie_regs[TME_SUN_MIE_REG_CSR])) ! 119: #define TME_SUN_MIE_CSR_PUT(sun_mie, csr) \ ! 120: (*((tme_uint16_t *) &(sun_mie)->tme_sun_mie_regs[TME_SUN_MIE_REG_CSR]) = tme_htobe_u16(csr)) ! 121: ! 122: /* these get and put the PCR: */ ! 123: #define TME_SUN_MIE_PCR_GET(sun_mie) \ ! 124: tme_betoh_u16(*((tme_uint16_t *) &(sun_mie)->tme_sun_mie_regs[TME_SUN_MIE_REG_PCR])) ! 125: #define TME_SUN_MIE_PCR_PUT(sun_mie, pcr) \ ! 126: (*((tme_uint16_t *) &(sun_mie)->tme_sun_mie_regs[TME_SUN_MIE_REG_PCR]) = tme_htobe_u16(pcr)) ! 127: ! 128: /* the callout flags: */ ! 129: #define TME_SUN_MIE_CALLOUT_CHECK (0) ! 130: #define TME_SUN_MIE_CALLOUT_RUNNING TME_BIT(0) ! 131: #define TME_SUN_MIE_CALLOUTS_MASK (-2) ! 132: #define TME_SUN_MIE_CALLOUT_SIGNALS TME_BIT(1) ! 133: #define TME_SUN_MIE_CALLOUT_INT TME_BIT(2) ! 134: ! 135: /* structures: */ ! 136: ! 137: /* the card: */ ! 138: struct tme_sun_mie { ! 139: ! 140: /* backpointer to our element: */ ! 141: struct tme_element *tme_sun_mie_element; ! 142: ! 143: /* the mutex protecting the card: */ ! 144: tme_mutex_t tme_sun_mie_mutex; ! 145: ! 146: /* the rwlock protecting the card: */ ! 147: tme_rwlock_t tme_sun_mie_rwlock; ! 148: ! 149: /* the bus connection for the card's registers: */ ! 150: struct tme_bus_connection *tme_sun_mie_conn_regs; ! 151: ! 152: /* the bus connection for the card's memory: */ ! 153: struct tme_bus_connection *tme_sun_mie_conn_memory; ! 154: ! 155: /* the bus connection for the card's i825x6 chip: */ ! 156: struct tme_bus_connection *tme_sun_mie_conn_i825x6; ! 157: ! 158: /* the callout flags: */ ! 159: int tme_sun_mie_callout_flags; ! 160: ! 161: /* if our interrupt line is currently asserted: */ ! 162: int tme_sun_mie_int_asserted; ! 163: ! 164: /* it's easiest to just model the board registers as a chunk of memory: */ ! 165: tme_uint8_t tme_sun_mie_regs[TME_SUN_MIE_SIZ_REGS]; ! 166: ! 167: /* the board memory really is a chunk of memory: */ ! 168: tme_uint8_t tme_sun_mie_memory[TME_SUN_MIE_MEMSIZE]; ! 169: ! 170: /* the active TLB entries for each page map entry on the board: */ ! 171: struct tme_bus_tlb *tme_sun_mie_tlbs[TME_SUN_MIE_PGMAP_COUNT * TME_SUN_MIE_PGMAP_TLBS]; ! 172: unsigned int tme_sun_mie_tlb_head[TME_SUN_MIE_PGMAP_COUNT]; ! 173: ! 174: /* the i825x6 image of the CSR: */ ! 175: tme_uint16_t tme_sun_mie_csr_i825x6; ! 176: ! 177: #ifndef TME_NO_LOG ! 178: tme_uint16_t tme_sun_mie_last_log_csr; ! 179: #endif /* !TME_NO_LOG */ ! 180: }; ! 181: ! 182: /* a sun_mie internal bus connection: */ ! 183: struct tme_sun_mie_connection { ! 184: ! 185: /* the external bus connection: */ ! 186: struct tme_bus_connection tme_sun_mie_connection; ! 187: ! 188: /* this is nonzero if a TME_CONNECTION_BUS_GENERIC chip connection ! 189: is for the registers: */ ! 190: tme_uint8_t tme_sun_mie_connection_regs; ! 191: ! 192: /* if this connection is for the memory port, this is the high ! 193: nibble (A19..A16) of that port's connection: */ ! 194: tme_uint8_t tme_sun_mie_connection_mpmhi; ! 195: }; ! 196: ! 197: /* globals: */ ! 198: ! 199: /* our bus signals sets: */ ! 200: static const struct tme_bus_signals _tme_sun_mie_bus_signals_generic = TME_BUS_SIGNALS_GENERIC; ! 201: static const struct tme_bus_signals _tme_sun_mie_bus_signals_i825x6 = TME_BUS_SIGNALS_I825X6; ! 202: ! 203: /* the sun_mie callout function. it must be called with the mutex locked: */ ! 204: static void ! 205: _tme_sun_mie_callout(struct tme_sun_mie *sun_mie, int new_callouts) ! 206: { ! 207: struct tme_bus_connection *conn_i825x6; ! 208: struct tme_bus_connection *conn_bus; ! 209: tme_uint16_t csr, csr_diff; ! 210: unsigned int signal, level; ! 211: int callouts, later_callouts; ! 212: int rc; ! 213: int int_asserted; ! 214: ! 215: /* add in any new callouts: */ ! 216: sun_mie->tme_sun_mie_callout_flags |= new_callouts; ! 217: ! 218: /* if this function is already running in another thread, simply ! 219: return now. the other thread will do our work: */ ! 220: if (sun_mie->tme_sun_mie_callout_flags & TME_SUN_MIE_CALLOUT_RUNNING) { ! 221: return; ! 222: } ! 223: ! 224: /* callouts are now running: */ ! 225: sun_mie->tme_sun_mie_callout_flags |= TME_SUN_MIE_CALLOUT_RUNNING; ! 226: ! 227: /* assume that we won't need any later callouts: */ ! 228: later_callouts = 0; ! 229: ! 230: /* loop while callouts are needed: */ ! 231: for (; (callouts = sun_mie->tme_sun_mie_callout_flags) & TME_SUN_MIE_CALLOUTS_MASK; ) { ! 232: ! 233: /* clear the needed callouts: */ ! 234: sun_mie->tme_sun_mie_callout_flags = callouts & ~TME_SUN_MIE_CALLOUTS_MASK; ! 235: callouts &= TME_SUN_MIE_CALLOUTS_MASK; ! 236: ! 237: /* if we need to call out one or more signals to the i825x6: */ ! 238: if (callouts & TME_SUN_MIE_CALLOUT_SIGNALS) { ! 239: ! 240: /* get the current CSR value: */ ! 241: csr = TME_SUN_MIE_CSR_GET(sun_mie); ! 242: ! 243: /* get the next signal to call out to the i825x6: */ ! 244: csr_diff = ((csr ! 245: ^ sun_mie->tme_sun_mie_csr_i825x6) ! 246: & (TME_SUN_MIE_CSR_RESET ! 247: | TME_SUN_MIE_CSR_NOLOOP ! 248: | TME_SUN_MIE_CSR_CA)); ! 249: csr_diff = (csr_diff ^ (csr_diff - 1)) & csr_diff; ! 250: ! 251: /* if there is a signal to call out: */ ! 252: if (csr_diff != 0) { ! 253: ! 254: /* assume that if the signal's bit is set in the CSR, it will ! 255: be asserted: */ ! 256: level = csr & csr_diff; ! 257: ! 258: /* assume that we're calling out an i825x6 signal: */ ! 259: signal = (_tme_sun_mie_bus_signals_generic.tme_bus_signals_first ! 260: + TME_BUS_SIGNAL_X(_tme_sun_mie_bus_signals_generic.tme_bus_signals_count)); ! 261: ! 262: /* dispatch on the CSR bit: */ ! 263: switch (csr_diff) { ! 264: default: ! 265: assert (FALSE); ! 266: case TME_SUN_MIE_CSR_RESET: ! 267: signal = TME_BUS_SIGNAL_RESET; ! 268: break; ! 269: case TME_SUN_MIE_CSR_NOLOOP: ! 270: signal += TME_I825X6_SIGNAL_LOOP; ! 271: level = !level; ! 272: break; ! 273: case TME_SUN_MIE_CSR_CA: ! 274: signal += TME_I825X6_SIGNAL_CA; ! 275: break; ! 276: } ! 277: ! 278: /* create a real signal level value: */ ! 279: level = (level ! 280: ? TME_BUS_SIGNAL_LEVEL_ASSERTED ! 281: : TME_BUS_SIGNAL_LEVEL_NEGATED); ! 282: ! 283: /* get this card's i825x6 connection: */ ! 284: conn_i825x6 = sun_mie->tme_sun_mie_conn_i825x6; ! 285: ! 286: /* unlock the mutex: */ ! 287: tme_mutex_unlock(&sun_mie->tme_sun_mie_mutex); ! 288: ! 289: /* do the callout: */ ! 290: rc = (conn_i825x6 != NULL ! 291: ? ((*conn_i825x6->tme_bus_signal) ! 292: (conn_i825x6, ! 293: signal | level)) ! 294: : TME_OK); ! 295: ! 296: /* lock the mutex: */ ! 297: tme_mutex_lock(&sun_mie->tme_sun_mie_mutex); ! 298: ! 299: /* if the callout was unsuccessful, remember that at some later ! 300: time this callout should be attempted again: */ ! 301: if (rc != TME_OK) { ! 302: later_callouts |= TME_SUN_MIE_CALLOUT_SIGNALS; ! 303: } ! 304: ! 305: /* otherwise, the callout was successful: */ ! 306: else { ! 307: ! 308: /* update the i825x6 image of the CSR: */ ! 309: sun_mie->tme_sun_mie_csr_i825x6 = ! 310: ((sun_mie->tme_sun_mie_csr_i825x6 & ~csr_diff) ! 311: | (csr & csr_diff)); ! 312: ! 313: /* there may be more signals to call out, so attempt this ! 314: callout again now: */ ! 315: sun_mie->tme_sun_mie_callout_flags |= TME_SUN_MIE_CALLOUT_SIGNALS; ! 316: } ! 317: } ! 318: } ! 319: ! 320: /* if we need to call out a possible change to our interrupt ! 321: signal: */ ! 322: if (callouts & TME_SUN_MIE_CALLOUT_INT) { ! 323: ! 324: /* get the current CSR value: */ ! 325: csr = TME_SUN_MIE_CSR_GET(sun_mie); ! 326: ! 327: /* see if the interrupt signal should be asserted or negated: */ ! 328: int_asserted = ((csr & (TME_SUN_MIE_CSR_IE ! 329: | TME_SUN_MIE_CSR_INTR)) ! 330: == (TME_SUN_MIE_CSR_IE ! 331: | TME_SUN_MIE_CSR_INTR)); ! 332: ! 333: /* if the interrupt signal doesn't already have the right state: */ ! 334: if (!int_asserted != !sun_mie->tme_sun_mie_int_asserted) { ! 335: ! 336: /* get our bus connection: */ ! 337: conn_bus = sun_mie->tme_sun_mie_conn_regs; ! 338: ! 339: /* unlock our mutex: */ ! 340: tme_mutex_unlock(&sun_mie->tme_sun_mie_mutex); ! 341: ! 342: /* call out the bus interrupt signal edge: */ ! 343: rc = (conn_bus != NULL ! 344: ? ((*conn_bus->tme_bus_signal) ! 345: (conn_bus, ! 346: TME_BUS_SIGNAL_INT_UNSPEC ! 347: | (int_asserted ! 348: ? TME_BUS_SIGNAL_LEVEL_ASSERTED ! 349: : TME_BUS_SIGNAL_LEVEL_NEGATED))) ! 350: : TME_OK); ! 351: ! 352: /* lock our mutex: */ ! 353: tme_mutex_lock(&sun_mie->tme_sun_mie_mutex); ! 354: ! 355: /* if this callout was successful, note the new state of the ! 356: interrupt signal: */ ! 357: if (rc == TME_OK) { ! 358: sun_mie->tme_sun_mie_int_asserted = int_asserted; ! 359: } ! 360: ! 361: /* otherwise, remember that at some later time this callout ! 362: should be attempted again: */ ! 363: else { ! 364: later_callouts |= TME_SUN_MIE_CALLOUT_INT; ! 365: } ! 366: } ! 367: } ! 368: } ! 369: ! 370: /* put in any later callouts, and clear that callouts are running: */ ! 371: sun_mie->tme_sun_mie_callout_flags = later_callouts; ! 372: } ! 373: ! 374: /* the sun_mie bus cycle handler for the board memory: */ ! 375: static int ! 376: _tme_sun_mie_bus_cycle(void *_sun_mie, ! 377: struct tme_bus_cycle *cycle_init) ! 378: { ! 379: struct tme_sun_mie *sun_mie; ! 380: ! 381: /* recover our data structure: */ ! 382: sun_mie = (struct tme_sun_mie *) _sun_mie; ! 383: ! 384: /* run the cycle: */ ! 385: tme_bus_cycle_xfer_memory(cycle_init, ! 386: sun_mie->tme_sun_mie_memory, ! 387: TME_SUN_MIE_MEMSIZE - 1); ! 388: ! 389: /* no faults: */ ! 390: return (TME_OK); ! 391: } ! 392: ! 393: /* the sun_mie bus cycle handler for the board registers: */ ! 394: static int ! 395: _tme_sun_mie_bus_cycle_regs(void *_sun_mie, ! 396: struct tme_bus_cycle *cycle_init) ! 397: { ! 398: struct tme_sun_mie *sun_mie; ! 399: unsigned int pgmap_i; ! 400: unsigned int pgmap_j; ! 401: unsigned int tlb_i; ! 402: unsigned int tlb_j; ! 403: tme_uint16_t csr_old, csr_new, csr_diff; ! 404: tme_uint16_t pcr_old, pcr_new, pcr_diff; ! 405: int new_callouts; ! 406: ! 407: /* recover our data structure: */ ! 408: sun_mie = (struct tme_sun_mie *) _sun_mie; ! 409: ! 410: /* assume we won't need any new callouts: */ ! 411: new_callouts = 0; ! 412: ! 413: /* lock the mutex: */ ! 414: tme_mutex_lock(&sun_mie->tme_sun_mie_mutex); ! 415: ! 416: /* if this is a write cycle and the address falls within one or more ! 417: page map entries, invalidate the TLBs associated with those ! 418: entries: */ ! 419: if ((cycle_init->tme_bus_cycle_type ! 420: & TME_BUS_CYCLE_WRITE) ! 421: && (TME_SUN_MIE_REG_PGMAP ! 422: <= cycle_init->tme_bus_cycle_address) ! 423: && (cycle_init->tme_bus_cycle_address ! 424: < (TME_SUN_MIE_REG_PGMAP ! 425: + TME_SUN_MIE_SIZ_PGMAP))) { ! 426: ! 427: /* get the range of page map entries: */ ! 428: pgmap_i ! 429: = (cycle_init->tme_bus_cycle_address ! 430: / sizeof(tme_uint16_t)); ! 431: pgmap_j ! 432: = ((cycle_init->tme_bus_cycle_address ! 433: + cycle_init->tme_bus_cycle_size ! 434: + sizeof(tme_uint16_t) ! 435: - 1) ! 436: / sizeof(tme_uint16_t)); ! 437: pgmap_j = TME_MIN(pgmap_j, TME_SUN_MIE_PGMAP_COUNT); ! 438: ! 439: /* get the range of TLB handles: */ ! 440: tlb_i = pgmap_i * TME_SUN_MIE_PGMAP_TLBS; ! 441: tlb_j = pgmap_j * TME_SUN_MIE_PGMAP_TLBS; ! 442: ! 443: /* invalidate the TLB entries: */ ! 444: for (; tlb_i < tlb_j; tlb_i++) { ! 445: if (sun_mie->tme_sun_mie_tlbs[tlb_i] != NULL) { ! 446: tme_bus_tlb_invalidate(sun_mie->tme_sun_mie_tlbs[tlb_i]); ! 447: sun_mie->tme_sun_mie_tlbs[tlb_i] = NULL; ! 448: } ! 449: } ! 450: } ! 451: ! 452: /* get the previous CSR and PCR values: */ ! 453: csr_old = TME_SUN_MIE_CSR_GET(sun_mie); ! 454: pcr_old = TME_SUN_MIE_PCR_GET(sun_mie); ! 455: ! 456: /* unless this address falls within the PROM, run the cycle: */ ! 457: if ((cycle_init->tme_bus_cycle_address ! 458: < TME_SUN_MIE_REG_PROM) ! 459: || (cycle_init->tme_bus_cycle_address ! 460: >= (TME_SUN_MIE_REG_PROM ! 461: + TME_SUN_MIE_SIZ_PROM))) { ! 462: tme_bus_cycle_xfer_memory(cycle_init, ! 463: sun_mie->tme_sun_mie_regs, ! 464: TME_SUN_MIE_SIZ_REGS - 1); ! 465: } ! 466: ! 467: /* get the current CSR and PCR values, and put back any bits that ! 468: software can't change: */ ! 469: csr_new = ((TME_SUN_MIE_CSR_GET(sun_mie) ! 470: & ~TME_SUN_MIE_CSR_READONLY) ! 471: | (csr_old ! 472: & TME_SUN_MIE_CSR_READONLY)); ! 473: TME_SUN_MIE_CSR_PUT(sun_mie, csr_new); ! 474: pcr_new = ((TME_SUN_MIE_PCR_GET(sun_mie) ! 475: & ~TME_SUN_MIE_PCR_READONLY) ! 476: | (pcr_old ! 477: & TME_SUN_MIE_PCR_READONLY)); ! 478: TME_SUN_MIE_PCR_PUT(sun_mie, pcr_new); ! 479: ! 480: /* get the sets of CSR and PCR bits that have changed: */ ! 481: csr_diff = (csr_old ^ csr_new); ! 482: pcr_diff = (pcr_old ^ pcr_new); ! 483: ! 484: /* if this is a RESET, NOLOOP or CA change, possibly call out the ! 485: appropriate signal change to the i825x6: */ ! 486: if (csr_diff & (TME_SUN_MIE_CSR_RESET ! 487: | TME_SUN_MIE_CSR_NOLOOP ! 488: | TME_SUN_MIE_CSR_CA)) { ! 489: new_callouts |= TME_SUN_MIE_CALLOUT_SIGNALS; ! 490: } ! 491: ! 492: /* if this is an interrupt mask change, possibly call out an ! 493: interrupt signal change to the bus: */ ! 494: if (csr_diff & TME_SUN_MIE_CSR_IE) { ! 495: new_callouts |= TME_SUN_MIE_CALLOUT_INT; ! 496: } ! 497: ! 498: /* abort on any attempt to enable the P2 bus: */ ! 499: if (csr_new & TME_SUN_MIE_CSR_P2MEM) { ! 500: abort (); ! 501: } ! 502: ! 503: /* if this is acknowledging a parity error: */ ! 504: if (pcr_diff & TME_SUN_MIE_PCR_PEACK) { ! 505: /* nothing to do */ ! 506: } ! 507: ! 508: #ifndef TME_NO_LOG ! 509: if (csr_new != sun_mie->tme_sun_mie_last_log_csr) { ! 510: sun_mie->tme_sun_mie_last_log_csr = csr_new; ! 511: tme_log(&sun_mie->tme_sun_mie_element->tme_element_log_handle, ! 512: 1000, TME_OK, ! 513: (&sun_mie->tme_sun_mie_element->tme_element_log_handle, ! 514: "csr now 0x%04x", ! 515: csr_new)); ! 516: } ! 517: #endif /* !TME_NO_LOG */ ! 518: ! 519: /* make any new callouts: */ ! 520: _tme_sun_mie_callout(sun_mie, new_callouts); ! 521: ! 522: /* unlock the mutex: */ ! 523: tme_mutex_unlock(&sun_mie->tme_sun_mie_mutex); ! 524: ! 525: /* no faults: */ ! 526: return (TME_OK); ! 527: } ! 528: ! 529: /* the sun_mie bus signal handler: */ ! 530: static int ! 531: _tme_sun_mie_bus_signal(struct tme_bus_connection *conn_bus, ! 532: unsigned int signal) ! 533: { ! 534: struct tme_sun_mie *sun_mie; ! 535: ! 536: /* return now if this is not a generic bus signal: */ ! 537: if (TME_BUS_SIGNAL_INDEX(signal) ! 538: > _tme_sun_mie_bus_signals_generic.tme_bus_signals_count) { ! 539: return (TME_OK); ! 540: } ! 541: ! 542: /* recover our data structures: */ ! 543: sun_mie = conn_bus->tme_bus_connection.tme_connection_element->tme_element_private; ! 544: ! 545: /* since this function is currently only given to the i825x6, ! 546: just copy its signal through to the Multibus: */ ! 547: conn_bus = sun_mie->tme_sun_mie_conn_regs; ! 548: return ((*conn_bus->tme_bus_signal)(conn_bus, signal)); ! 549: } ! 550: ! 551: /* the sun_mie bus signals adder for the i825x6: */ ! 552: static int ! 553: _tme_sun_mie_bus_signals_add(struct tme_bus_connection *conn_bus, ! 554: struct tme_bus_signals *bus_signals_caller) ! 555: { ! 556: const struct tme_bus_signals *bus_signals; ! 557: tme_uint32_t signal_first; ! 558: ! 559: /* we only support the generic and i825x6 bus signals: */ ! 560: switch (bus_signals_caller->tme_bus_signals_id) { ! 561: case TME_BUS_SIGNALS_ID_GENERIC: ! 562: bus_signals = &_tme_sun_mie_bus_signals_generic; ! 563: signal_first = _tme_sun_mie_bus_signals_generic.tme_bus_signals_first; ! 564: break; ! 565: case TME_BUS_SIGNALS_ID_I825X6: ! 566: bus_signals = &_tme_sun_mie_bus_signals_i825x6; ! 567: signal_first = (_tme_sun_mie_bus_signals_generic.tme_bus_signals_first ! 568: + TME_BUS_SIGNAL_X(_tme_sun_mie_bus_signals_generic.tme_bus_signals_count)); ! 569: break; ! 570: default: ! 571: return (ENOENT); ! 572: } ! 573: ! 574: /* XXX we should check versions here: */ ! 575: *bus_signals_caller = *bus_signals; ! 576: bus_signals_caller->tme_bus_signals_first = signal_first; ! 577: return (TME_OK); ! 578: } ! 579: ! 580: /* the sun_mie TLB allocator for the i825x6: */ ! 581: static int ! 582: _tme_sun_mie_tlb_set_allocate(struct tme_bus_connection *conn_bus, ! 583: unsigned int count, unsigned int sizeof_one, ! 584: TME_ATOMIC_POINTER_TYPE(struct tme_bus_tlb *) _tlbs) ! 585: { ! 586: struct tme_bus_tlb *tlbs, *tlb; ! 587: unsigned int tlb_i; ! 588: ! 589: /* allocate a singleton set: */ ! 590: tlbs = (struct tme_bus_tlb *) tme_malloc(count * sizeof_one); ! 591: tlb = tlbs; ! 592: for (tlb_i = 0; tlb_i < count; tlb_i++) { ! 593: tme_bus_tlb_invalidate(tlb); ! 594: tlb = (struct tme_bus_tlb *) (((tme_uint8_t *) tlb) + sizeof_one); ! 595: } ! 596: TME_ATOMIC_WRITE(struct tme_bus_tlb *, *_tlbs, tlbs); ! 597: ! 598: /* done: */ ! 599: return (TME_OK); ! 600: } ! 601: ! 602: /* the sun_mie TLB filler for the board memory: */ ! 603: static int ! 604: _tme_sun_mie_tlb_fill(struct tme_bus_connection *conn_bus, ! 605: struct tme_bus_tlb *tlb, ! 606: tme_bus_addr_t address, ! 607: unsigned int cycles) ! 608: { ! 609: struct tme_sun_mie *sun_mie; ! 610: unsigned int pgmap_i; ! 611: unsigned int tlb_i; ! 612: tme_uint16_t pgmap; ! 613: ! 614: /* recover our data structures: */ ! 615: sun_mie = conn_bus->tme_bus_connection.tme_connection_element->tme_element_private; ! 616: ! 617: /* the address must be within range: */ ! 618: assert(address <= 0xffffff); ! 619: ! 620: /* mask the address with the board page size: */ ! 621: address &= -TME_SUN_MIE_PAGESIZE; ! 622: ! 623: /* lock our mutex: */ ! 624: tme_mutex_lock(&sun_mie->tme_sun_mie_mutex); ! 625: ! 626: /* get the pagemap entry: */ ! 627: pgmap_i = (address / TME_SUN_MIE_PAGESIZE) & (TME_SUN_MIE_PGMAP_COUNT - 1); ! 628: pgmap = tme_betoh_u16(((tme_uint16_t *) &sun_mie->tme_sun_mie_regs[TME_SUN_MIE_REG_PGMAP])[pgmap_i]); ! 629: ! 630: /* update the head pointer for this page map entry's active TLB ! 631: entry list: */ ! 632: tlb_i = sun_mie->tme_sun_mie_tlb_head[pgmap_i]; ! 633: if (++tlb_i == TME_SUN_MIE_PGMAP_TLBS) { ! 634: tlb_i = 0; ! 635: } ! 636: sun_mie->tme_sun_mie_tlb_head[pgmap_i] = tlb_i; ! 637: tlb_i += pgmap_i * TME_SUN_MIE_PGMAP_TLBS; ! 638: ! 639: /* if the new head pointer already has a TLB entry, and it doesn't ! 640: happen to be the same one that we're filling now, invalidate it: */ ! 641: if (sun_mie->tme_sun_mie_tlbs[tlb_i] != NULL ! 642: && sun_mie->tme_sun_mie_tlbs[tlb_i] != TME_ATOMIC_READ(struct tme_bus_tlb *, ! 643: tlb->tme_bus_tlb_backing_reservation)) { ! 644: tme_bus_tlb_invalidate(sun_mie->tme_sun_mie_tlbs[tlb_i]); ! 645: } ! 646: ! 647: /* initialize the TLB entry: */ ! 648: tme_bus_tlb_initialize(tlb); ! 649: ! 650: /* this TLB entry covers this range: */ ! 651: TME_ATOMIC_WRITE(tme_bus_addr_t, tlb->tme_bus_tlb_addr_first, address); ! 652: TME_ATOMIC_WRITE(tme_bus_addr_t, tlb->tme_bus_tlb_addr_last, address | (TME_SUN_MIE_PAGESIZE - 1)); ! 653: ! 654: /* allow reading and writing: */ ! 655: tlb->tme_bus_tlb_cycles_ok = TME_BUS_CYCLE_READ | TME_BUS_CYCLE_WRITE; ! 656: ! 657: /* our bus cycle handler: */ ! 658: tlb->tme_bus_tlb_cycle_private = sun_mie; ! 659: tlb->tme_bus_tlb_cycle = _tme_sun_mie_bus_cycle; ! 660: ! 661: /* this TLB entry allows fast reading and writing: */ ! 662: tlb->tme_bus_tlb_emulator_off_write = ! 663: (&sun_mie->tme_sun_mie_memory[((pgmap & TME_SUN_MIE_PGMAP_PFNUM) ! 664: * TME_SUN_MIE_PAGESIZE)] ! 665: - address); ! 666: tlb->tme_bus_tlb_emulator_off_read = ! 667: tlb->tme_bus_tlb_emulator_off_write; ! 668: ! 669: /* add this TLB entry to the active list: */ ! 670: sun_mie->tme_sun_mie_tlbs[tlb_i] = ! 671: TME_ATOMIC_READ(struct tme_bus_tlb *, ! 672: tlb->tme_bus_tlb_backing_reservation); ! 673: ! 674: /* unlock our mutex: */ ! 675: tme_mutex_unlock(&sun_mie->tme_sun_mie_mutex); ! 676: ! 677: return (TME_OK); ! 678: } ! 679: ! 680: /* the sun_mie TLB filler for the board registers: */ ! 681: static int ! 682: _tme_sun_mie_tlb_fill_regs(struct tme_bus_connection *conn_bus, ! 683: struct tme_bus_tlb *tlb, ! 684: tme_bus_addr_t address, unsigned int cycles) ! 685: { ! 686: struct tme_sun_mie *sun_mie; ! 687: ! 688: /* recover our data structures: */ ! 689: sun_mie = conn_bus->tme_bus_connection.tme_connection_element->tme_element_private; ! 690: ! 691: /* the address must be within range: */ ! 692: assert(address < TME_SUN_MIE_SIZ_REGS); ! 693: ! 694: /* initialize the TLB entry: */ ! 695: tme_bus_tlb_initialize(tlb); ! 696: ! 697: /* if the address falls in the page map: */ ! 698: if (TME_SUN_MIE_REG_PGMAP <= address ! 699: && address < (TME_SUN_MIE_REG_PGMAP ! 700: + TME_SUN_MIE_SIZ_PGMAP)) { ! 701: ! 702: /* this TLB entry covers this range: */ ! 703: TME_ATOMIC_WRITE(tme_bus_addr_t, tlb->tme_bus_tlb_addr_first, TME_SUN_MIE_REG_PGMAP); ! 704: TME_ATOMIC_WRITE(tme_bus_addr_t, tlb->tme_bus_tlb_addr_last, (TME_SUN_MIE_REG_PGMAP ! 705: + TME_SUN_MIE_SIZ_PGMAP ! 706: - 1)); ! 707: } ! 708: ! 709: /* if this address falls in the PROM: */ ! 710: else if (TME_SUN_MIE_REG_PROM <= address ! 711: && address < (TME_SUN_MIE_REG_PROM ! 712: + TME_SUN_MIE_SIZ_PROM)) { ! 713: ! 714: ! 715: /* this TLB entry covers this range: */ ! 716: TME_ATOMIC_WRITE(tme_bus_addr_t, tlb->tme_bus_tlb_addr_first, TME_SUN_MIE_REG_PROM); ! 717: TME_ATOMIC_WRITE(tme_bus_addr_t, tlb->tme_bus_tlb_addr_last, (TME_SUN_MIE_REG_PROM ! 718: + TME_SUN_MIE_SIZ_PROM ! 719: - 1)); ! 720: } ! 721: ! 722: /* if this address falls in the CSR: */ ! 723: else if (TME_SUN_MIE_REG_CSR <= address ! 724: && address < (TME_SUN_MIE_REG_CSR ! 725: + TME_SUN_MIE_SIZ_CSR)) { ! 726: ! 727: ! 728: /* this TLB entry covers this range: */ ! 729: TME_ATOMIC_WRITE(tme_bus_addr_t, tlb->tme_bus_tlb_addr_first, TME_SUN_MIE_REG_CSR); ! 730: TME_ATOMIC_WRITE(tme_bus_addr_t, tlb->tme_bus_tlb_addr_last, (TME_SUN_MIE_REG_CSR ! 731: + TME_SUN_MIE_SIZ_CSR ! 732: - 1)); ! 733: } ! 734: ! 735: /* otherwise, this address must fall in the unused hole or in the ! 736: parity registers: */ ! 737: else { ! 738: assert (address >= (TME_SUN_MIE_REG_CSR ! 739: + TME_SUN_MIE_SIZ_CSR)); ! 740: ! 741: /* this TLB entry covers this range: */ ! 742: TME_ATOMIC_WRITE(tme_bus_addr_t, tlb->tme_bus_tlb_addr_first, (TME_SUN_MIE_REG_CSR ! 743: + TME_SUN_MIE_SIZ_CSR)); ! 744: TME_ATOMIC_WRITE(tme_bus_addr_t, tlb->tme_bus_tlb_addr_last, (TME_SUN_MIE_REG_PE_ALO ! 745: + TME_SUN_MIE_SIZ_PE_ALO ! 746: - 1)); ! 747: } ! 748: ! 749: /* all address ranges allow fast reading: */ ! 750: tlb->tme_bus_tlb_emulator_off_read = &sun_mie->tme_sun_mie_regs[0]; ! 751: tlb->tme_bus_tlb_rwlock = &sun_mie->tme_sun_mie_rwlock; ! 752: ! 753: /* allow reading and writing: */ ! 754: tlb->tme_bus_tlb_cycles_ok = TME_BUS_CYCLE_READ | TME_BUS_CYCLE_WRITE; ! 755: ! 756: /* our bus cycle handler: */ ! 757: tlb->tme_bus_tlb_cycle_private = sun_mie; ! 758: tlb->tme_bus_tlb_cycle = _tme_sun_mie_bus_cycle_regs; ! 759: ! 760: return (TME_OK); ! 761: } ! 762: ! 763: /* this scores a new connection: */ ! 764: static int ! 765: _tme_sun_mie_connection_score(struct tme_connection *conn, unsigned int *_score) ! 766: { ! 767: struct tme_sun_mie *sun_mie; ! 768: struct tme_sun_mie_connection *conn_sun_mie; ! 769: ! 770: /* both sides must be generic bus connections: */ ! 771: assert(conn->tme_connection_type == TME_CONNECTION_BUS_GENERIC); ! 772: assert(conn->tme_connection_other->tme_connection_type ! 773: == conn->tme_connection_type); ! 774: ! 775: /* recover our data structures: */ ! 776: sun_mie = conn->tme_connection_element->tme_element_private; ! 777: conn_sun_mie = (struct tme_sun_mie_connection *)conn; ! 778: ! 779: /* this is a generic bus connection, so just score it nonzero and ! 780: return. note that there's no good way to differentiate a ! 781: connection to a bus from a connection to just another chip, so we ! 782: always return a nonzero score here: */ ! 783: *_score = 1; ! 784: return (TME_OK); ! 785: } ! 786: ! 787: /* this makes a new connection: */ ! 788: static int ! 789: _tme_sun_mie_connection_make(struct tme_connection *conn, unsigned int state) ! 790: { ! 791: struct tme_sun_mie *sun_mie; ! 792: struct tme_sun_mie_connection *conn_sun_mie; ! 793: struct tme_bus_connection *conn_bus; ! 794: tme_uint16_t csr; ! 795: ! 796: /* both sides must be generic bus connections: */ ! 797: assert(conn->tme_connection_type == TME_CONNECTION_BUS_GENERIC); ! 798: assert(conn->tme_connection_other->tme_connection_type ! 799: == conn->tme_connection_type); ! 800: ! 801: /* recover our data structures: */ ! 802: sun_mie = conn->tme_connection_element->tme_element_private; ! 803: conn_sun_mie = (struct tme_sun_mie_connection *)conn; ! 804: conn_bus = &conn_sun_mie->tme_sun_mie_connection; ! 805: ! 806: /* we're always set up to answer calls across the connection, so we ! 807: only have to do work when the connection has gone full, namely ! 808: taking the other side of the connection: */ ! 809: if (state == TME_CONNECTION_FULL) { ! 810: ! 811: /* lock our mutex: */ ! 812: tme_mutex_lock(&sun_mie->tme_sun_mie_mutex); ! 813: ! 814: /* save our connection: */ ! 815: if (conn_bus->tme_bus_signals_add != NULL) { ! 816: sun_mie->tme_sun_mie_conn_i825x6 = (struct tme_bus_connection *) conn->tme_connection_other; ! 817: } ! 818: else if (conn_sun_mie->tme_sun_mie_connection_regs) { ! 819: sun_mie->tme_sun_mie_conn_regs = (struct tme_bus_connection *) conn->tme_connection_other; ! 820: } ! 821: else { ! 822: sun_mie->tme_sun_mie_conn_memory = (struct tme_bus_connection *) conn->tme_connection_other; ! 823: csr = TME_SUN_MIE_CSR_GET(sun_mie); ! 824: csr &= ~TME_SUN_MIE_CSR_MPMHI; ! 825: csr |= conn_sun_mie->tme_sun_mie_connection_mpmhi; ! 826: TME_SUN_MIE_CSR_PUT(sun_mie, csr); ! 827: } ! 828: ! 829: /* unlock our mutex: */ ! 830: tme_mutex_unlock(&sun_mie->tme_sun_mie_mutex); ! 831: } ! 832: ! 833: return (TME_OK); ! 834: } ! 835: ! 836: /* this breaks a connection: */ ! 837: static int ! 838: _tme_sun_mie_connection_break(struct tme_connection *conn, unsigned int state) ! 839: { ! 840: abort(); ! 841: } ! 842: ! 843: /* this makes a new connection side for a sun_mie: */ ! 844: static int ! 845: _tme_sun_mie_connections_new(struct tme_element *element, ! 846: const char * const *args, ! 847: struct tme_connection **_conns, ! 848: char **_output) ! 849: { ! 850: struct tme_sun_mie *sun_mie; ! 851: struct tme_sun_mie_connection *conn_sun_mie; ! 852: struct tme_bus_connection *conn_bus; ! 853: struct tme_connection *conn; ! 854: unsigned int i825x6; ! 855: tme_uint8_t regs; ! 856: tme_bus_addr_t mpmhi; ! 857: int usage; ! 858: int rc; ! 859: ! 860: /* recover our data structure: */ ! 861: sun_mie = (struct tme_sun_mie *) element->tme_element_private; ! 862: ! 863: /* we don't bother locking the mutex simply to check if connections ! 864: already exist: */ ! 865: ! 866: /* check our arguments: */ ! 867: usage = FALSE; ! 868: rc = 0; ! 869: i825x6 = FALSE; ! 870: regs = FALSE; ! 871: mpmhi = 0; ! 872: ! 873: /* if this connection is for the registers: */ ! 874: if (TME_ARG_IS(args[1], "csr")) { ! 875: ! 876: /* if we already have a register connection, complain: */ ! 877: if (sun_mie->tme_sun_mie_conn_regs != NULL) { ! 878: rc = EEXIST; ! 879: } ! 880: ! 881: /* otherwise, make the new connection: */ ! 882: else { ! 883: regs = TRUE; ! 884: } ! 885: } ! 886: ! 887: /* else, if this connection is for the memory: */ ! 888: else if (TME_ARG_IS(args[1], "memory")) { ! 889: ! 890: /* if we already have a memory connection, complain: */ ! 891: if (sun_mie->tme_sun_mie_conn_memory != NULL) { ! 892: rc = EEXIST; ! 893: } ! 894: ! 895: /* otherwise, check the value after "memory". it must be the low ! 896: 20 bits of the bus address of the board's memory; in our csr we ! 897: have to report the most significant nibble (A19-A16, as A15..A0 ! 898: are expected to be zero) to software so it can find that ! 899: memory: */ ! 900: else { ! 901: mpmhi = tme_bus_addr_parse_any(args[2], &usage); ! 902: if (!usage ! 903: && ((mpmhi > 0xfffff) ! 904: || (mpmhi & (TME_SUN_MIE_SIZ_MBM - 1)))) { ! 905: tme_output_append_error(_output, ! 906: "%s %s, ", ! 907: args[2], ! 908: _(" is not a 20-bit address with A15..A0 zero")); ! 909: usage = TRUE; ! 910: } ! 911: } ! 912: } ! 913: ! 914: /* else, the connection must be for the i825x6: */ ! 915: else if (args[1] == NULL) { ! 916: ! 917: /* if we already have an i825x6 connection, complain: */ ! 918: if (sun_mie->tme_sun_mie_conn_i825x6 != NULL) { ! 919: rc = EEXIST; ! 920: } ! 921: ! 922: /* otherwise, make the new conection: */ ! 923: else { ! 924: i825x6 = TRUE; ! 925: } ! 926: } ! 927: ! 928: /* otherwise, this is a bad argument: */ ! 929: else { ! 930: tme_output_append_error(_output, ! 931: "%s %s, ", ! 932: args[1], ! 933: _("unexpected")); ! 934: usage = TRUE; ! 935: } ! 936: ! 937: if (usage) { ! 938: tme_output_append_error(_output, ! 939: "%s %s [ csr | memory %s ]", ! 940: _("usage:"), ! 941: args[0], ! 942: _("BUS-ADDRESS")); ! 943: rc = EINVAL; ! 944: } ! 945: ! 946: if (rc) { ! 947: return (rc); ! 948: } ! 949: ! 950: /* make a new connection: */ ! 951: conn_sun_mie = tme_new0(struct tme_sun_mie_connection, 1); ! 952: conn_bus = &conn_sun_mie->tme_sun_mie_connection; ! 953: conn = &conn_bus->tme_bus_connection; ! 954: ! 955: /* fill in the generic connection: */ ! 956: conn->tme_connection_next = *_conns; ! 957: conn->tme_connection_type = TME_CONNECTION_BUS_GENERIC; ! 958: conn->tme_connection_score = _tme_sun_mie_connection_score; ! 959: conn->tme_connection_make = _tme_sun_mie_connection_make; ! 960: conn->tme_connection_break = _tme_sun_mie_connection_break; ! 961: ! 962: /* fill in the generic bus connection: */ ! 963: conn_bus->tme_bus_subregions.tme_bus_subregion_address_first = 0; ! 964: conn_bus->tme_bus_subregions.tme_bus_subregion_next = NULL; ! 965: if (i825x6) { ! 966: conn_bus->tme_bus_subregions.tme_bus_subregion_address_last = 0xffffff; ! 967: conn_bus->tme_bus_signals_add = _tme_sun_mie_bus_signals_add; ! 968: conn_bus->tme_bus_signal = _tme_sun_mie_bus_signal; ! 969: conn_bus->tme_bus_tlb_set_allocate = _tme_sun_mie_tlb_set_allocate; ! 970: conn_bus->tme_bus_tlb_fill = _tme_sun_mie_tlb_fill; ! 971: } ! 972: else if (regs) { ! 973: conn_bus->tme_bus_subregions.tme_bus_subregion_address_last = TME_SUN_MIE_SIZ_REGS - 1; ! 974: conn_bus->tme_bus_tlb_fill = _tme_sun_mie_tlb_fill_regs; ! 975: } ! 976: else { ! 977: conn_bus->tme_bus_subregions.tme_bus_subregion_address_last = TME_SUN_MIE_SIZ_MBM - 1; ! 978: conn_bus->tme_bus_tlb_fill = _tme_sun_mie_tlb_fill; ! 979: } ! 980: ! 981: /* fill in the internal information: */ ! 982: conn_sun_mie->tme_sun_mie_connection_regs = regs; ! 983: conn_sun_mie->tme_sun_mie_connection_mpmhi = (mpmhi >> 16); ! 984: ! 985: /* return the connection side possibility: */ ! 986: *_conns = conn; ! 987: return (TME_OK); ! 988: } ! 989: ! 990: /* the new sun_mie function: */ ! 991: TME_ELEMENT_SUB_NEW_DECL(tme_bus_multibus,sun_mie) { ! 992: struct tme_sun_mie *sun_mie; ! 993: int arg_i; ! 994: int usage; ! 995: ! 996: /* check our arguments: */ ! 997: usage = 0; ! 998: arg_i = 1; ! 999: for (;;) { ! 1000: ! 1001: if (0) { ! 1002: } ! 1003: ! 1004: /* if we ran out of arguments: */ ! 1005: else if (args[arg_i] == NULL) { ! 1006: ! 1007: break; ! 1008: } ! 1009: ! 1010: /* otherwise this is a bad argument: */ ! 1011: else { ! 1012: tme_output_append_error(_output, ! 1013: "%s %s, ", ! 1014: args[arg_i], ! 1015: _("unexpected")); ! 1016: usage = TRUE; ! 1017: break; ! 1018: } ! 1019: } ! 1020: ! 1021: if (usage) { ! 1022: tme_output_append_error(_output, ! 1023: "%s %s", ! 1024: _("usage:"), ! 1025: args[0]); ! 1026: return (EINVAL); ! 1027: } ! 1028: ! 1029: /* start the sun_mie structure: */ ! 1030: sun_mie = tme_new0(struct tme_sun_mie, 1); ! 1031: sun_mie->tme_sun_mie_element = element; ! 1032: TME_SUN_MIE_CSR_PUT(sun_mie, ! 1033: (TME_SUN_MIE_CSR_NOLOOP ! 1034: | TME_SUN_MIE_CSR_BIGRAM)); ! 1035: tme_mutex_init(&sun_mie->tme_sun_mie_mutex); ! 1036: tme_rwlock_init(&sun_mie->tme_sun_mie_rwlock); ! 1037: ! 1038: /* fill the element: */ ! 1039: element->tme_element_private = sun_mie; ! 1040: element->tme_element_connections_new = _tme_sun_mie_connections_new; ! 1041: ! 1042: return (TME_OK); ! 1043: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.