|
|
1.1 ! root 1: /* $Id: sun-obie.c,v 1.2 2005/02/17 12:37:25 fredette Exp $ */ ! 2: ! 3: /* machine/sun/sun-obie.c - classic Sun onboard Intel Ethernet implementation: */ ! 4: ! 5: /* ! 6: * Copyright (c) 2004 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-obie.c,v 1.2 2005/02/17 12:37:25 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: #include <tme/machine/sun.h> ! 48: ! 49: /* macros: */ ! 50: ! 51: /* register offsets and sizes: */ ! 52: #define TME_SUN_OBIE_REG_CSR (0) ! 53: #define TME_SUN_OBIE_SIZ_CSR (sizeof(tme_uint16_t)) ! 54: #define TME_SUN_OBIE_SIZ_REGS (TME_SUN_OBIE_REG_CSR + TME_SUN_OBIE_SIZ_CSR) ! 55: ! 56: /* the bits in the Control/Status Register: */ ! 57: #define TME_SUN_OBIE_CSR_NORESET (0x8000) ! 58: #define TME_SUN_OBIE_CSR_NOLOOP (0x4000) ! 59: #define TME_SUN_OBIE_CSR_CA (0x2000) ! 60: #define TME_SUN_OBIE_CSR_IE (0x1000) ! 61: /* 0x0800 unused */ ! 62: #define TME_SUN_OBIE_CSR_LEVEL2 (0x0400) ! 63: #define TME_SUN_OBIE_CSR_BUSERR (0x0200) ! 64: #define TME_SUN_OBIE_CSR_INTR (0x0100) ! 65: #define TME_SUN_OBIE_CSR_READONLY (0x0800 \ ! 66: | TME_SUN_OBIE_CSR_LEVEL2 \ ! 67: | TME_SUN_OBIE_CSR_BUSERR \ ! 68: | TME_SUN_OBIE_CSR_INTR) ! 69: ! 70: /* these get and put the CSR: */ ! 71: #define TME_SUN_OBIE_CSR_GET(sun_obie) \ ! 72: tme_betoh_u16(*((tme_uint16_t *) &(sun_obie)->tme_sun_obie_regs[TME_SUN_OBIE_REG_CSR])) ! 73: #define TME_SUN_OBIE_CSR_PUT(sun_obie, csr) \ ! 74: (*((tme_uint16_t *) &(sun_obie)->tme_sun_obie_regs[TME_SUN_OBIE_REG_CSR]) = tme_htobe_u16(csr)) ! 75: ! 76: /* the callout flags: */ ! 77: #define TME_SUN_OBIE_CALLOUT_CHECK (0) ! 78: #define TME_SUN_OBIE_CALLOUT_RUNNING TME_BIT(0) ! 79: #define TME_SUN_OBIE_CALLOUTS_MASK (-2) ! 80: #define TME_SUN_OBIE_CALLOUT_SIGNALS TME_BIT(1) ! 81: #define TME_SUN_OBIE_CALLOUT_INT TME_BIT(2) ! 82: ! 83: /* structures: */ ! 84: ! 85: /* the card: */ ! 86: struct tme_sun_obie { ! 87: ! 88: /* backpointer to our element: */ ! 89: struct tme_element *tme_sun_obie_element; ! 90: ! 91: /* the mutex protecting the card: */ ! 92: tme_mutex_t tme_sun_obie_mutex; ! 93: ! 94: /* the rwlock protecting the card: */ ! 95: tme_rwlock_t tme_sun_obie_rwlock; ! 96: ! 97: /* the bus connection for the card's registers: */ ! 98: struct tme_bus_connection *tme_sun_obie_conn_regs; ! 99: ! 100: /* the bus connection for the card's memory: */ ! 101: struct tme_bus_connection *tme_sun_obie_conn_memory; ! 102: ! 103: /* the bus connection for the card's i825x6 chip: */ ! 104: struct tme_bus_connection *tme_sun_obie_conn_i825x6; ! 105: ! 106: /* the callout flags: */ ! 107: int tme_sun_obie_callout_flags; ! 108: ! 109: /* if our interrupt line is currently asserted: */ ! 110: int tme_sun_obie_int_asserted; ! 111: ! 112: /* it's easiest to just model the board registers as a chunk of memory: */ ! 113: tme_uint8_t tme_sun_obie_regs[TME_SUN_OBIE_SIZ_REGS]; ! 114: ! 115: /* the i825x6 image of the CSR: */ ! 116: tme_uint16_t tme_sun_obie_csr_i825x6; ! 117: ! 118: #ifndef TME_NO_LOG ! 119: tme_uint16_t tme_sun_obie_last_log_csr; ! 120: #endif /* !TME_NO_LOG */ ! 121: }; ! 122: ! 123: /* a sun_obie internal bus connection: */ ! 124: struct tme_sun_obie_connection { ! 125: ! 126: /* the external bus connection: */ ! 127: struct tme_bus_connection tme_sun_obie_connection; ! 128: ! 129: /* this is nonzero if a TME_CONNECTION_BUS_GENERIC chip connection ! 130: is for the registers: */ ! 131: tme_uint8_t tme_sun_obie_connection_regs; ! 132: }; ! 133: ! 134: /* globals: */ ! 135: ! 136: /* our bus signals sets: */ ! 137: static const struct tme_bus_signals _tme_sun_obie_bus_signals_generic = TME_BUS_SIGNALS_GENERIC; ! 138: static const struct tme_bus_signals _tme_sun_obie_bus_signals_i825x6 = TME_BUS_SIGNALS_I825X6; ! 139: ! 140: /* the sun_obie callout function. it must be called with the mutex locked: */ ! 141: static void ! 142: _tme_sun_obie_callout(struct tme_sun_obie *sun_obie, int new_callouts) ! 143: { ! 144: struct tme_bus_connection *conn_i825x6; ! 145: struct tme_bus_connection *conn_bus; ! 146: tme_uint16_t csr, csr_diff; ! 147: unsigned int signal, level; ! 148: int callouts, later_callouts; ! 149: int rc; ! 150: int int_asserted; ! 151: ! 152: /* add in any new callouts: */ ! 153: sun_obie->tme_sun_obie_callout_flags |= new_callouts; ! 154: ! 155: /* if this function is already running in another thread, simply ! 156: return now. the other thread will do our work: */ ! 157: if (sun_obie->tme_sun_obie_callout_flags & TME_SUN_OBIE_CALLOUT_RUNNING) { ! 158: return; ! 159: } ! 160: ! 161: /* callouts are now running: */ ! 162: sun_obie->tme_sun_obie_callout_flags |= TME_SUN_OBIE_CALLOUT_RUNNING; ! 163: ! 164: /* assume that we won't need any later callouts: */ ! 165: later_callouts = 0; ! 166: ! 167: /* loop while callouts are needed: */ ! 168: for (; (callouts = sun_obie->tme_sun_obie_callout_flags) & TME_SUN_OBIE_CALLOUTS_MASK; ) { ! 169: ! 170: /* clear the needed callouts: */ ! 171: sun_obie->tme_sun_obie_callout_flags = callouts & ~TME_SUN_OBIE_CALLOUTS_MASK; ! 172: callouts &= TME_SUN_OBIE_CALLOUTS_MASK; ! 173: ! 174: /* if we need to call out one or more signals to the i825x6: */ ! 175: if (callouts & TME_SUN_OBIE_CALLOUT_SIGNALS) { ! 176: ! 177: /* get the current CSR value: */ ! 178: csr = TME_SUN_OBIE_CSR_GET(sun_obie); ! 179: ! 180: /* get the next signal to call out to the i825x6: */ ! 181: csr_diff = ((csr ! 182: ^ sun_obie->tme_sun_obie_csr_i825x6) ! 183: & (TME_SUN_OBIE_CSR_NORESET ! 184: | TME_SUN_OBIE_CSR_NOLOOP ! 185: | TME_SUN_OBIE_CSR_CA)); ! 186: csr_diff = (csr_diff ^ (csr_diff - 1)) & csr_diff; ! 187: ! 188: /* if there is a signal to call out: */ ! 189: if (csr_diff != 0) { ! 190: ! 191: /* assume that if the signal's bit is set in the CSR, it will ! 192: be asserted: */ ! 193: level = csr & csr_diff; ! 194: ! 195: /* assume that we're calling out an i825x6 signal: */ ! 196: signal = (_tme_sun_obie_bus_signals_generic.tme_bus_signals_first ! 197: + TME_BUS_SIGNAL_X(_tme_sun_obie_bus_signals_generic.tme_bus_signals_count)); ! 198: ! 199: /* dispatch on the CSR bit: */ ! 200: switch (csr_diff) { ! 201: default: ! 202: assert (FALSE); ! 203: case TME_SUN_OBIE_CSR_NORESET: ! 204: signal = TME_BUS_SIGNAL_RESET; ! 205: level = !level; ! 206: break; ! 207: case TME_SUN_OBIE_CSR_NOLOOP: ! 208: signal += TME_I825X6_SIGNAL_LOOP; ! 209: level = !level; ! 210: break; ! 211: case TME_SUN_OBIE_CSR_CA: ! 212: signal += TME_I825X6_SIGNAL_CA; ! 213: break; ! 214: } ! 215: ! 216: /* create a real signal level value: */ ! 217: level = (level ! 218: ? TME_BUS_SIGNAL_LEVEL_ASSERTED ! 219: : TME_BUS_SIGNAL_LEVEL_NEGATED); ! 220: ! 221: /* get this card's i825x6 connection: */ ! 222: conn_i825x6 = sun_obie->tme_sun_obie_conn_i825x6; ! 223: ! 224: /* unlock the mutex: */ ! 225: tme_mutex_unlock(&sun_obie->tme_sun_obie_mutex); ! 226: ! 227: /* do the callout: */ ! 228: rc = (conn_i825x6 != NULL ! 229: ? ((*conn_i825x6->tme_bus_signal) ! 230: (conn_i825x6, ! 231: signal | level)) ! 232: : TME_OK); ! 233: ! 234: /* lock the mutex: */ ! 235: tme_mutex_lock(&sun_obie->tme_sun_obie_mutex); ! 236: ! 237: /* if the callout was unsuccessful, remember that at some later ! 238: time this callout should be attempted again: */ ! 239: if (rc != TME_OK) { ! 240: later_callouts |= TME_SUN_OBIE_CALLOUT_SIGNALS; ! 241: } ! 242: ! 243: /* otherwise, the callout was successful: */ ! 244: else { ! 245: ! 246: /* update the i825x6 image of the CSR: */ ! 247: sun_obie->tme_sun_obie_csr_i825x6 = ! 248: ((sun_obie->tme_sun_obie_csr_i825x6 & ~csr_diff) ! 249: | (csr & csr_diff)); ! 250: ! 251: /* there may be more signals to call out, so attempt this ! 252: callout again now: */ ! 253: sun_obie->tme_sun_obie_callout_flags |= TME_SUN_OBIE_CALLOUT_SIGNALS; ! 254: } ! 255: } ! 256: } ! 257: ! 258: /* if we need to call out a possible change to our interrupt ! 259: signal: */ ! 260: if (callouts & TME_SUN_OBIE_CALLOUT_INT) { ! 261: ! 262: /* get the current CSR value: */ ! 263: csr = TME_SUN_OBIE_CSR_GET(sun_obie); ! 264: ! 265: /* see if the interrupt signal should be asserted or negated: */ ! 266: int_asserted = ((csr & (TME_SUN_OBIE_CSR_IE ! 267: | TME_SUN_OBIE_CSR_INTR)) ! 268: == (TME_SUN_OBIE_CSR_IE ! 269: | TME_SUN_OBIE_CSR_INTR)); ! 270: ! 271: /* if the interrupt signal doesn't already have the right state: */ ! 272: if (!int_asserted != !sun_obie->tme_sun_obie_int_asserted) { ! 273: ! 274: /* get our bus connection: */ ! 275: conn_bus = sun_obie->tme_sun_obie_conn_regs; ! 276: ! 277: /* unlock our mutex: */ ! 278: tme_mutex_unlock(&sun_obie->tme_sun_obie_mutex); ! 279: ! 280: /* call out the bus interrupt signal edge: */ ! 281: rc = (conn_bus != NULL ! 282: ? ((*conn_bus->tme_bus_signal) ! 283: (conn_bus, ! 284: TME_BUS_SIGNAL_INT_UNSPEC ! 285: | (int_asserted ! 286: ? TME_BUS_SIGNAL_LEVEL_ASSERTED ! 287: : TME_BUS_SIGNAL_LEVEL_NEGATED))) ! 288: : TME_OK); ! 289: ! 290: /* lock our mutex: */ ! 291: tme_mutex_lock(&sun_obie->tme_sun_obie_mutex); ! 292: ! 293: /* if this callout was successful, note the new state of the ! 294: interrupt signal: */ ! 295: if (rc == TME_OK) { ! 296: sun_obie->tme_sun_obie_int_asserted = int_asserted; ! 297: } ! 298: ! 299: /* otherwise, remember that at some later time this callout ! 300: should be attempted again: */ ! 301: else { ! 302: later_callouts |= TME_SUN_OBIE_CALLOUT_INT; ! 303: } ! 304: } ! 305: } ! 306: } ! 307: ! 308: /* put in any later callouts, and clear that callouts are running: */ ! 309: sun_obie->tme_sun_obie_callout_flags = later_callouts; ! 310: } ! 311: ! 312: /* the sun_obie bus cycle handler for the board registers: */ ! 313: static int ! 314: _tme_sun_obie_bus_cycle_regs(void *_sun_obie, ! 315: struct tme_bus_cycle *cycle_init) ! 316: { ! 317: struct tme_sun_obie *sun_obie; ! 318: tme_uint16_t csr_old, csr_new, csr_diff; ! 319: int new_callouts; ! 320: ! 321: /* recover our data structure: */ ! 322: sun_obie = (struct tme_sun_obie *) _sun_obie; ! 323: ! 324: /* assume we won't need any new callouts: */ ! 325: new_callouts = 0; ! 326: ! 327: /* lock the mutex: */ ! 328: tme_mutex_lock(&sun_obie->tme_sun_obie_mutex); ! 329: ! 330: /* get the previous CSR value: */ ! 331: csr_old = TME_SUN_OBIE_CSR_GET(sun_obie); ! 332: ! 333: /* run the cycle: */ ! 334: tme_bus_cycle_xfer_memory(cycle_init, ! 335: sun_obie->tme_sun_obie_regs, ! 336: TME_SUN_OBIE_SIZ_REGS - 1); ! 337: ! 338: /* get the current CSR value, and put back any bits that ! 339: software can't change: */ ! 340: csr_new = ((TME_SUN_OBIE_CSR_GET(sun_obie) ! 341: & ~TME_SUN_OBIE_CSR_READONLY) ! 342: | (csr_old ! 343: & TME_SUN_OBIE_CSR_READONLY)); ! 344: TME_SUN_OBIE_CSR_PUT(sun_obie, csr_new); ! 345: ! 346: /* get the sets of CSR bits that have changed: */ ! 347: csr_diff = (csr_old ^ csr_new); ! 348: ! 349: /* if this is a NORESET, NOLOOP or CA change, possibly call out the ! 350: appropriate signal change to the i825x6: */ ! 351: if (csr_diff & (TME_SUN_OBIE_CSR_NORESET ! 352: | TME_SUN_OBIE_CSR_NOLOOP ! 353: | TME_SUN_OBIE_CSR_CA)) { ! 354: new_callouts |= TME_SUN_OBIE_CALLOUT_SIGNALS; ! 355: } ! 356: ! 357: /* if this is an interrupt mask change, possibly call out an ! 358: interrupt signal change to the bus: */ ! 359: if (csr_diff & TME_SUN_OBIE_CSR_IE) { ! 360: new_callouts |= TME_SUN_OBIE_CALLOUT_INT; ! 361: } ! 362: ! 363: #ifndef TME_NO_LOG ! 364: if (csr_new != sun_obie->tme_sun_obie_last_log_csr) { ! 365: sun_obie->tme_sun_obie_last_log_csr = csr_new; ! 366: tme_log(&sun_obie->tme_sun_obie_element->tme_element_log_handle, ! 367: 1000, TME_OK, ! 368: (&sun_obie->tme_sun_obie_element->tme_element_log_handle, ! 369: "csr now 0x%04x", ! 370: csr_new)); ! 371: } ! 372: #endif /* !TME_NO_LOG */ ! 373: ! 374: /* make any new callouts: */ ! 375: _tme_sun_obie_callout(sun_obie, new_callouts); ! 376: ! 377: /* unlock the mutex: */ ! 378: tme_mutex_unlock(&sun_obie->tme_sun_obie_mutex); ! 379: ! 380: /* no faults: */ ! 381: return (TME_OK); ! 382: } ! 383: ! 384: /* the sun_obie bus signal handler: */ ! 385: static int ! 386: _tme_sun_obie_bus_signal(struct tme_bus_connection *conn_bus, ! 387: unsigned int signal) ! 388: { ! 389: struct tme_sun_obie *sun_obie; ! 390: ! 391: /* return now if this is not a generic bus signal: */ ! 392: if (TME_BUS_SIGNAL_INDEX(signal) ! 393: > _tme_sun_obie_bus_signals_generic.tme_bus_signals_count) { ! 394: return (TME_OK); ! 395: } ! 396: ! 397: /* recover our data structures: */ ! 398: sun_obie = conn_bus->tme_bus_connection.tme_connection_element->tme_element_private; ! 399: ! 400: /* pass the i825x6's signal through to the obio bus: */ ! 401: conn_bus = sun_obie->tme_sun_obie_conn_regs; ! 402: return (conn_bus != NULL ! 403: ? (*conn_bus->tme_bus_signal)(conn_bus, signal) ! 404: : ENXIO); ! 405: } ! 406: ! 407: /* the sun_obie bus signals adder for the i825x6: */ ! 408: static int ! 409: _tme_sun_obie_bus_signals_add(struct tme_bus_connection *conn_bus, ! 410: struct tme_bus_signals *bus_signals_caller) ! 411: { ! 412: const struct tme_bus_signals *bus_signals; ! 413: tme_uint32_t signal_first; ! 414: ! 415: /* we only support the generic and i825x6 bus signals: */ ! 416: switch (bus_signals_caller->tme_bus_signals_id) { ! 417: case TME_BUS_SIGNALS_ID_GENERIC: ! 418: bus_signals = &_tme_sun_obie_bus_signals_generic; ! 419: signal_first = _tme_sun_obie_bus_signals_generic.tme_bus_signals_first; ! 420: break; ! 421: case TME_BUS_SIGNALS_ID_I825X6: ! 422: bus_signals = &_tme_sun_obie_bus_signals_i825x6; ! 423: signal_first = (_tme_sun_obie_bus_signals_generic.tme_bus_signals_first ! 424: + TME_BUS_SIGNAL_X(_tme_sun_obie_bus_signals_generic.tme_bus_signals_count)); ! 425: break; ! 426: default: ! 427: return (ENOENT); ! 428: } ! 429: ! 430: /* XXX we should check versions here: */ ! 431: *bus_signals_caller = *bus_signals; ! 432: bus_signals_caller->tme_bus_signals_first = signal_first; ! 433: return (TME_OK); ! 434: } ! 435: ! 436: /* the sun_obie TLB allocator for the i825x6: */ ! 437: static int ! 438: _tme_sun_obie_tlb_set_allocate(struct tme_bus_connection *conn_bus, ! 439: unsigned int count, unsigned int sizeof_one, ! 440: TME_ATOMIC_POINTER_TYPE(struct tme_bus_tlb *) _tlbs) ! 441: { ! 442: struct tme_sun_obie *sun_obie; ! 443: ! 444: /* recover our data structures: */ ! 445: sun_obie = conn_bus->tme_bus_connection.tme_connection_element->tme_element_private; ! 446: ! 447: /* pass the i825x6's request through to the mainbus: */ ! 448: conn_bus = sun_obie->tme_sun_obie_conn_memory; ! 449: return (conn_bus != NULL ! 450: ? (*conn_bus->tme_bus_tlb_set_allocate)(conn_bus, ! 451: count, sizeof_one, ! 452: _tlbs) ! 453: : ENXIO); ! 454: } ! 455: ! 456: /* the sun_obie TLB filler for the memory: */ ! 457: static int ! 458: _tme_sun_obie_tlb_fill(struct tme_bus_connection *conn_bus, ! 459: struct tme_bus_tlb *tlb, ! 460: tme_bus_addr_t address, ! 461: unsigned int cycles) ! 462: { ! 463: struct tme_sun_obie *sun_obie; ! 464: ! 465: /* the address must be within range: */ ! 466: assert(address <= 0xffffff); ! 467: ! 468: /* recover our data structures: */ ! 469: sun_obie = conn_bus->tme_bus_connection.tme_connection_element->tme_element_private; ! 470: ! 471: /* pass the i825x6's request through to the mainbus: */ ! 472: conn_bus = sun_obie->tme_sun_obie_conn_memory; ! 473: return (conn_bus != NULL ! 474: ? (*conn_bus->tme_bus_tlb_fill)(conn_bus, ! 475: tlb, ! 476: address, ! 477: cycles) ! 478: : ENXIO); ! 479: } ! 480: ! 481: /* the sun_obie TLB filler for the board registers: */ ! 482: static int ! 483: _tme_sun_obie_tlb_fill_regs(struct tme_bus_connection *conn_bus, ! 484: struct tme_bus_tlb *tlb, ! 485: tme_bus_addr_t address, unsigned int cycles) ! 486: { ! 487: struct tme_sun_obie *sun_obie; ! 488: ! 489: /* recover our data structures: */ ! 490: sun_obie = conn_bus->tme_bus_connection.tme_connection_element->tme_element_private; ! 491: ! 492: /* the address must be within range: */ ! 493: assert(address < TME_SUN_OBIE_SIZ_CSR); ! 494: ! 495: /* initialize the TLB entry: */ ! 496: tme_bus_tlb_initialize(tlb); ! 497: ! 498: /* this address falls in the CSR: */ ! 499: ! 500: /* this TLB entry covers this range: */ ! 501: TME_ATOMIC_WRITE(tme_bus_addr_t, tlb->tme_bus_tlb_addr_first, TME_SUN_OBIE_REG_CSR); ! 502: TME_ATOMIC_WRITE(tme_bus_addr_t, tlb->tme_bus_tlb_addr_last, (TME_SUN_OBIE_REG_CSR ! 503: + TME_SUN_OBIE_SIZ_CSR ! 504: - 1)); ! 505: ! 506: /* this TLB entry allows fast reading: */ ! 507: tlb->tme_bus_tlb_emulator_off_read = sun_obie->tme_sun_obie_regs; ! 508: ! 509: /* allow reading and writing: */ ! 510: tlb->tme_bus_tlb_cycles_ok = TME_BUS_CYCLE_READ | TME_BUS_CYCLE_WRITE; ! 511: ! 512: /* our bus cycle handler: */ ! 513: tlb->tme_bus_tlb_cycle_private = sun_obie; ! 514: tlb->tme_bus_tlb_cycle = _tme_sun_obie_bus_cycle_regs; ! 515: ! 516: return (TME_OK); ! 517: } ! 518: ! 519: /* this scores a new connection: */ ! 520: static int ! 521: _tme_sun_obie_connection_score(struct tme_connection *conn, unsigned int *_score) ! 522: { ! 523: struct tme_sun_obie *sun_obie; ! 524: struct tme_sun_obie_connection *conn_sun_obie; ! 525: ! 526: /* both sides must be generic bus connections: */ ! 527: assert(conn->tme_connection_type == TME_CONNECTION_BUS_GENERIC); ! 528: assert(conn->tme_connection_other->tme_connection_type ! 529: == conn->tme_connection_type); ! 530: ! 531: /* recover our data structures: */ ! 532: sun_obie = conn->tme_connection_element->tme_element_private; ! 533: conn_sun_obie = (struct tme_sun_obie_connection *)conn; ! 534: ! 535: /* this is a generic bus connection, so just score it nonzero and ! 536: return. note that there's no good way to differentiate a ! 537: connection to a bus from a connection to just another chip, so we ! 538: always return a nonzero score here: */ ! 539: *_score = 1; ! 540: return (TME_OK); ! 541: } ! 542: ! 543: /* this makes a new connection: */ ! 544: static int ! 545: _tme_sun_obie_connection_make(struct tme_connection *conn, unsigned int state) ! 546: { ! 547: struct tme_sun_obie *sun_obie; ! 548: struct tme_sun_obie_connection *conn_sun_obie; ! 549: struct tme_bus_connection *conn_bus; ! 550: ! 551: /* both sides must be generic bus connections: */ ! 552: assert(conn->tme_connection_type == TME_CONNECTION_BUS_GENERIC); ! 553: assert(conn->tme_connection_other->tme_connection_type ! 554: == conn->tme_connection_type); ! 555: ! 556: /* recover our data structures: */ ! 557: sun_obie = conn->tme_connection_element->tme_element_private; ! 558: conn_sun_obie = (struct tme_sun_obie_connection *)conn; ! 559: conn_bus = &conn_sun_obie->tme_sun_obie_connection; ! 560: ! 561: /* we're always set up to answer calls across the connection, so we ! 562: only have to do work when the connection has gone full, namely ! 563: taking the other side of the connection: */ ! 564: if (state == TME_CONNECTION_FULL) { ! 565: ! 566: /* lock our mutex: */ ! 567: tme_mutex_lock(&sun_obie->tme_sun_obie_mutex); ! 568: ! 569: /* save our connection: */ ! 570: if (conn_bus->tme_bus_signals_add != NULL) { ! 571: sun_obie->tme_sun_obie_conn_i825x6 = (struct tme_bus_connection *) conn->tme_connection_other; ! 572: } ! 573: else if (conn_sun_obie->tme_sun_obie_connection_regs) { ! 574: sun_obie->tme_sun_obie_conn_regs = (struct tme_bus_connection *) conn->tme_connection_other; ! 575: } ! 576: else { ! 577: sun_obie->tme_sun_obie_conn_memory = (struct tme_bus_connection *) conn->tme_connection_other; ! 578: } ! 579: ! 580: /* unlock our mutex: */ ! 581: tme_mutex_unlock(&sun_obie->tme_sun_obie_mutex); ! 582: } ! 583: ! 584: return (TME_OK); ! 585: } ! 586: ! 587: /* this breaks a connection: */ ! 588: static int ! 589: _tme_sun_obie_connection_break(struct tme_connection *conn, unsigned int state) ! 590: { ! 591: abort(); ! 592: } ! 593: ! 594: /* this makes a new connection side for a sun_obie: */ ! 595: static int ! 596: _tme_sun_obie_connections_new(struct tme_element *element, ! 597: const char * const *args, ! 598: struct tme_connection **_conns, ! 599: char **_output) ! 600: { ! 601: struct tme_sun_obie *sun_obie; ! 602: struct tme_sun_obie_connection *conn_sun_obie; ! 603: struct tme_bus_connection *conn_bus; ! 604: struct tme_connection *conn; ! 605: unsigned int i825x6; ! 606: tme_uint8_t regs; ! 607: int usage; ! 608: int rc; ! 609: ! 610: /* recover our data structure: */ ! 611: sun_obie = (struct tme_sun_obie *) element->tme_element_private; ! 612: ! 613: /* we don't bother locking the mutex simply to check if connections ! 614: already exist: */ ! 615: ! 616: /* check our arguments: */ ! 617: usage = FALSE; ! 618: rc = 0; ! 619: i825x6 = FALSE; ! 620: regs = FALSE; ! 621: ! 622: /* if this connection is for the registers: */ ! 623: if (TME_ARG_IS(args[1], "csr")) { ! 624: ! 625: /* if we already have a register connection, complain: */ ! 626: if (sun_obie->tme_sun_obie_conn_regs != NULL) { ! 627: rc = EEXIST; ! 628: } ! 629: ! 630: /* otherwise, make the new connection: */ ! 631: else { ! 632: regs = TRUE; ! 633: } ! 634: } ! 635: ! 636: /* else, if this connection is for the memory: */ ! 637: else if (TME_ARG_IS(args[1], "memory")) { ! 638: ! 639: /* if we already have a memory connection, complain: */ ! 640: if (sun_obie->tme_sun_obie_conn_memory != NULL) { ! 641: rc = EEXIST; ! 642: } ! 643: } ! 644: ! 645: /* else, the connection must be for the i825x6: */ ! 646: else if (args[1] == NULL) { ! 647: ! 648: /* if we already have an i825x6 connection, complain: */ ! 649: if (sun_obie->tme_sun_obie_conn_i825x6 != NULL) { ! 650: rc = EEXIST; ! 651: } ! 652: ! 653: /* otherwise, make the new conection: */ ! 654: else { ! 655: i825x6 = TRUE; ! 656: } ! 657: } ! 658: ! 659: /* otherwise, this is a bad argument: */ ! 660: else { ! 661: tme_output_append_error(_output, ! 662: "%s %s, ", ! 663: args[1], ! 664: _("unexpected")); ! 665: usage = TRUE; ! 666: } ! 667: ! 668: if (usage) { ! 669: tme_output_append_error(_output, ! 670: "%s %s [ csr | memory ]", ! 671: _("usage:"), ! 672: args[0]); ! 673: rc = EINVAL; ! 674: } ! 675: ! 676: if (rc) { ! 677: return (rc); ! 678: } ! 679: ! 680: /* make a new connection: */ ! 681: conn_sun_obie = tme_new0(struct tme_sun_obie_connection, 1); ! 682: conn_bus = &conn_sun_obie->tme_sun_obie_connection; ! 683: conn = &conn_bus->tme_bus_connection; ! 684: ! 685: /* fill in the generic connection: */ ! 686: conn->tme_connection_next = *_conns; ! 687: conn->tme_connection_type = TME_CONNECTION_BUS_GENERIC; ! 688: conn->tme_connection_score = _tme_sun_obie_connection_score; ! 689: conn->tme_connection_make = _tme_sun_obie_connection_make; ! 690: conn->tme_connection_break = _tme_sun_obie_connection_break; ! 691: ! 692: /* fill in the generic bus connection: */ ! 693: conn_bus->tme_bus_subregions.tme_bus_subregion_address_first = 0; ! 694: conn_bus->tme_bus_subregions.tme_bus_subregion_next = NULL; ! 695: if (i825x6) { ! 696: conn_bus->tme_bus_subregions.tme_bus_subregion_address_last = 0xffffff; ! 697: conn_bus->tme_bus_signals_add = _tme_sun_obie_bus_signals_add; ! 698: conn_bus->tme_bus_signal = _tme_sun_obie_bus_signal; ! 699: conn_bus->tme_bus_tlb_set_allocate = _tme_sun_obie_tlb_set_allocate; ! 700: conn_bus->tme_bus_tlb_fill = _tme_sun_obie_tlb_fill; ! 701: } ! 702: else if (regs) { ! 703: conn_bus->tme_bus_subregions.tme_bus_subregion_address_last = TME_SUN_OBIE_SIZ_REGS - 1; ! 704: conn_bus->tme_bus_tlb_fill = _tme_sun_obie_tlb_fill_regs; ! 705: } ! 706: else { ! 707: conn_bus->tme_bus_subregions.tme_bus_subregion_address_last = 0; ! 708: } ! 709: ! 710: /* fill in the internal information: */ ! 711: conn_sun_obie->tme_sun_obie_connection_regs = regs; ! 712: ! 713: /* return the connection side possibility: */ ! 714: *_conns = conn; ! 715: return (TME_OK); ! 716: } ! 717: ! 718: /* the new sun_obie function: */ ! 719: int ! 720: tme_sun_obie(struct tme_element *element, const char * const *args, char **_output) ! 721: { ! 722: struct tme_sun_obie *sun_obie; ! 723: int arg_i; ! 724: int usage; ! 725: ! 726: /* check our arguments: */ ! 727: usage = 0; ! 728: arg_i = 1; ! 729: for (;;) { ! 730: ! 731: if (0) { ! 732: } ! 733: ! 734: /* if we ran out of arguments: */ ! 735: else if (args[arg_i] == NULL) { ! 736: ! 737: break; ! 738: } ! 739: ! 740: /* otherwise this is a bad argument: */ ! 741: else { ! 742: tme_output_append_error(_output, ! 743: "%s %s, ", ! 744: args[arg_i], ! 745: _("unexpected")); ! 746: usage = TRUE; ! 747: break; ! 748: } ! 749: } ! 750: ! 751: if (usage) { ! 752: tme_output_append_error(_output, ! 753: "%s %s", ! 754: _("usage:"), ! 755: args[0]); ! 756: return (EINVAL); ! 757: } ! 758: ! 759: /* start the sun_obie structure: */ ! 760: sun_obie = tme_new0(struct tme_sun_obie, 1); ! 761: sun_obie->tme_sun_obie_element = element; ! 762: TME_SUN_OBIE_CSR_PUT(sun_obie, ! 763: (TME_SUN_OBIE_CSR_NORESET ! 764: | TME_SUN_OBIE_CSR_NOLOOP)); ! 765: tme_mutex_init(&sun_obie->tme_sun_obie_mutex); ! 766: tme_rwlock_init(&sun_obie->tme_sun_obie_rwlock); ! 767: ! 768: /* fill the element: */ ! 769: element->tme_element_private = sun_obie; ! 770: element->tme_element_connections_new = _tme_sun_obie_connections_new; ! 771: ! 772: return (TME_OK); ! 773: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.