|
|
1.1.1.2 ! root 1: /* $Id: sun-obie.c,v 1.4 2007/08/25 20:44:11 fredette Exp $ */ 1.1 root 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> 1.1.1.2 ! root 37: _TME_RCSID("$Id: sun-obie.c,v 1.4 2007/08/25 20:44:11 fredette Exp $"); 1.1 root 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; 1.1.1.2 ! root 390: tme_uint16_t csr; ! 391: int new_callouts; 1.1 root 392: 393: /* return now if this is not a generic bus signal: */ 394: if (TME_BUS_SIGNAL_INDEX(signal) 395: > _tme_sun_obie_bus_signals_generic.tme_bus_signals_count) { 396: return (TME_OK); 397: } 398: 399: /* recover our data structures: */ 400: sun_obie = conn_bus->tme_bus_connection.tme_connection_element->tme_element_private; 401: 1.1.1.2 ! root 402: /* assume that we won't need any new callouts: */ ! 403: new_callouts = TME_SUN_OBIE_CALLOUT_CHECK; ! 404: ! 405: /* lock the mutex: */ ! 406: tme_mutex_lock(&sun_obie->tme_sun_obie_mutex); ! 407: ! 408: /* get the current CSR value: */ ! 409: csr = TME_SUN_OBIE_CSR_GET(sun_obie); ! 410: ! 411: /* if this bus signal is from the i825x6: */ ! 412: if (conn_bus->tme_bus_connection.tme_connection_other ! 413: == &sun_obie->tme_sun_obie_conn_i825x6->tme_bus_connection) { ! 414: ! 415: /* this must be the unspecified interrupt signal: */ ! 416: assert (TME_BUS_SIGNAL_WHICH(signal) == TME_BUS_SIGNAL_INT_UNSPEC); ! 417: ! 418: /* update the CSR value: */ ! 419: csr ! 420: = ((csr ! 421: & ~TME_SUN_OBIE_CSR_INTR) ! 422: | (((signal & TME_BUS_SIGNAL_LEVEL_MASK) ! 423: == TME_BUS_SIGNAL_LEVEL_ASSERTED) ! 424: ? TME_SUN_OBIE_CSR_INTR ! 425: : 0)); ! 426: ! 427: /* possibly call out an interrupt change to obio: */ ! 428: new_callouts = TME_SUN_OBIE_CALLOUT_INT; ! 429: } ! 430: ! 431: /* otherwise, this bus signal must be from obio: */ ! 432: else { ! 433: assert (conn_bus->tme_bus_connection.tme_connection_other ! 434: == &sun_obie->tme_sun_obie_conn_regs->tme_bus_connection); ! 435: ! 436: /* if this is the negating edge of the reset signal: */ ! 437: if (TME_BUS_SIGNAL_WHICH(signal) == TME_BUS_SIGNAL_RESET ! 438: && (signal & TME_BUS_SIGNAL_LEVEL_MASK) == TME_BUS_SIGNAL_LEVEL_NEGATED) { ! 439: ! 440: /* update the CSR value: */ ! 441: csr &= TME_SUN_OBIE_CSR_NOLOOP; ! 442: ! 443: /* possibly call out bus signal changes to the i825x6: */ ! 444: new_callouts = TME_SUN_OBIE_CALLOUT_SIGNALS; ! 445: } ! 446: } ! 447: ! 448: /* put the new CSR value: */ ! 449: TME_SUN_OBIE_CSR_PUT(sun_obie, csr); ! 450: ! 451: /* make any new callouts: */ ! 452: if (new_callouts != TME_SUN_OBIE_CALLOUT_CHECK) { ! 453: _tme_sun_obie_callout(sun_obie, new_callouts); ! 454: } ! 455: ! 456: /* unlock the mutex: */ ! 457: tme_mutex_unlock(&sun_obie->tme_sun_obie_mutex); ! 458: ! 459: return (TME_OK); 1.1 root 460: } 461: 462: /* the sun_obie bus signals adder for the i825x6: */ 463: static int 464: _tme_sun_obie_bus_signals_add(struct tme_bus_connection *conn_bus, 465: struct tme_bus_signals *bus_signals_caller) 466: { 467: const struct tme_bus_signals *bus_signals; 468: tme_uint32_t signal_first; 469: 470: /* we only support the generic and i825x6 bus signals: */ 471: switch (bus_signals_caller->tme_bus_signals_id) { 472: case TME_BUS_SIGNALS_ID_GENERIC: 473: bus_signals = &_tme_sun_obie_bus_signals_generic; 474: signal_first = _tme_sun_obie_bus_signals_generic.tme_bus_signals_first; 475: break; 476: case TME_BUS_SIGNALS_ID_I825X6: 477: bus_signals = &_tme_sun_obie_bus_signals_i825x6; 478: signal_first = (_tme_sun_obie_bus_signals_generic.tme_bus_signals_first 479: + TME_BUS_SIGNAL_X(_tme_sun_obie_bus_signals_generic.tme_bus_signals_count)); 480: break; 481: default: 482: return (ENOENT); 483: } 484: 485: /* XXX we should check versions here: */ 486: *bus_signals_caller = *bus_signals; 487: bus_signals_caller->tme_bus_signals_first = signal_first; 488: return (TME_OK); 489: } 490: 491: /* the sun_obie TLB allocator for the i825x6: */ 492: static int 493: _tme_sun_obie_tlb_set_allocate(struct tme_bus_connection *conn_bus, 494: unsigned int count, unsigned int sizeof_one, 1.1.1.2 ! root 495: struct tme_bus_tlb * tme_shared *_tlbs, ! 496: tme_rwlock_t *_tlbs_rwlock) 1.1 root 497: { 498: struct tme_sun_obie *sun_obie; 499: 500: /* recover our data structures: */ 501: sun_obie = conn_bus->tme_bus_connection.tme_connection_element->tme_element_private; 502: 503: /* pass the i825x6's request through to the mainbus: */ 504: conn_bus = sun_obie->tme_sun_obie_conn_memory; 505: return (conn_bus != NULL 506: ? (*conn_bus->tme_bus_tlb_set_allocate)(conn_bus, 507: count, sizeof_one, 1.1.1.2 ! root 508: _tlbs, _tlbs_rwlock) 1.1 root 509: : ENXIO); 510: } 511: 512: /* the sun_obie TLB filler for the memory: */ 513: static int 514: _tme_sun_obie_tlb_fill(struct tme_bus_connection *conn_bus, 515: struct tme_bus_tlb *tlb, 516: tme_bus_addr_t address, 517: unsigned int cycles) 518: { 519: struct tme_sun_obie *sun_obie; 520: 521: /* the address must be within range: */ 522: assert(address <= 0xffffff); 523: 524: /* recover our data structures: */ 525: sun_obie = conn_bus->tme_bus_connection.tme_connection_element->tme_element_private; 526: 527: /* pass the i825x6's request through to the mainbus: */ 528: conn_bus = sun_obie->tme_sun_obie_conn_memory; 529: return (conn_bus != NULL 530: ? (*conn_bus->tme_bus_tlb_fill)(conn_bus, 531: tlb, 532: address, 533: cycles) 534: : ENXIO); 535: } 536: 537: /* the sun_obie TLB filler for the board registers: */ 538: static int 539: _tme_sun_obie_tlb_fill_regs(struct tme_bus_connection *conn_bus, 540: struct tme_bus_tlb *tlb, 541: tme_bus_addr_t address, unsigned int cycles) 542: { 543: struct tme_sun_obie *sun_obie; 544: 545: /* recover our data structures: */ 546: sun_obie = conn_bus->tme_bus_connection.tme_connection_element->tme_element_private; 547: 548: /* the address must be within range: */ 549: assert(address < TME_SUN_OBIE_SIZ_CSR); 550: 551: /* initialize the TLB entry: */ 552: tme_bus_tlb_initialize(tlb); 553: 554: /* this address falls in the CSR: */ 555: 556: /* this TLB entry covers this range: */ 1.1.1.2 ! root 557: tlb->tme_bus_tlb_addr_first = TME_SUN_OBIE_REG_CSR; ! 558: tlb->tme_bus_tlb_addr_last = TME_SUN_OBIE_REG_CSR + TME_SUN_OBIE_SIZ_CSR - 1; 1.1 root 559: 560: /* this TLB entry allows fast reading: */ 561: tlb->tme_bus_tlb_emulator_off_read = sun_obie->tme_sun_obie_regs; 562: 563: /* allow reading and writing: */ 564: tlb->tme_bus_tlb_cycles_ok = TME_BUS_CYCLE_READ | TME_BUS_CYCLE_WRITE; 565: 566: /* our bus cycle handler: */ 567: tlb->tme_bus_tlb_cycle_private = sun_obie; 568: tlb->tme_bus_tlb_cycle = _tme_sun_obie_bus_cycle_regs; 569: 570: return (TME_OK); 571: } 572: 573: /* this scores a new connection: */ 574: static int 575: _tme_sun_obie_connection_score(struct tme_connection *conn, unsigned int *_score) 576: { 577: struct tme_sun_obie *sun_obie; 578: struct tme_sun_obie_connection *conn_sun_obie; 579: 580: /* both sides must be generic bus connections: */ 581: assert(conn->tme_connection_type == TME_CONNECTION_BUS_GENERIC); 582: assert(conn->tme_connection_other->tme_connection_type 583: == conn->tme_connection_type); 584: 585: /* recover our data structures: */ 586: sun_obie = conn->tme_connection_element->tme_element_private; 587: conn_sun_obie = (struct tme_sun_obie_connection *)conn; 588: 589: /* this is a generic bus connection, so just score it nonzero and 590: return. note that there's no good way to differentiate a 591: connection to a bus from a connection to just another chip, so we 592: always return a nonzero score here: */ 593: *_score = 1; 594: return (TME_OK); 595: } 596: 597: /* this makes a new connection: */ 598: static int 599: _tme_sun_obie_connection_make(struct tme_connection *conn, unsigned int state) 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: 605: /* both sides must be generic bus connections: */ 606: assert(conn->tme_connection_type == TME_CONNECTION_BUS_GENERIC); 607: assert(conn->tme_connection_other->tme_connection_type 608: == conn->tme_connection_type); 609: 610: /* recover our data structures: */ 611: sun_obie = conn->tme_connection_element->tme_element_private; 612: conn_sun_obie = (struct tme_sun_obie_connection *)conn; 613: conn_bus = &conn_sun_obie->tme_sun_obie_connection; 614: 615: /* we're always set up to answer calls across the connection, so we 616: only have to do work when the connection has gone full, namely 617: taking the other side of the connection: */ 618: if (state == TME_CONNECTION_FULL) { 619: 620: /* lock our mutex: */ 621: tme_mutex_lock(&sun_obie->tme_sun_obie_mutex); 622: 623: /* save our connection: */ 624: if (conn_bus->tme_bus_signals_add != NULL) { 625: sun_obie->tme_sun_obie_conn_i825x6 = (struct tme_bus_connection *) conn->tme_connection_other; 626: } 627: else if (conn_sun_obie->tme_sun_obie_connection_regs) { 628: sun_obie->tme_sun_obie_conn_regs = (struct tme_bus_connection *) conn->tme_connection_other; 629: } 630: else { 631: sun_obie->tme_sun_obie_conn_memory = (struct tme_bus_connection *) conn->tme_connection_other; 632: } 633: 634: /* unlock our mutex: */ 635: tme_mutex_unlock(&sun_obie->tme_sun_obie_mutex); 636: } 637: 638: return (TME_OK); 639: } 640: 641: /* this breaks a connection: */ 642: static int 643: _tme_sun_obie_connection_break(struct tme_connection *conn, unsigned int state) 644: { 645: abort(); 646: } 647: 648: /* this makes a new connection side for a sun_obie: */ 649: static int 650: _tme_sun_obie_connections_new(struct tme_element *element, 651: const char * const *args, 652: struct tme_connection **_conns, 653: char **_output) 654: { 655: struct tme_sun_obie *sun_obie; 656: struct tme_sun_obie_connection *conn_sun_obie; 657: struct tme_bus_connection *conn_bus; 658: struct tme_connection *conn; 659: unsigned int i825x6; 660: tme_uint8_t regs; 661: int usage; 662: int rc; 663: 664: /* recover our data structure: */ 665: sun_obie = (struct tme_sun_obie *) element->tme_element_private; 666: 667: /* we don't bother locking the mutex simply to check if connections 668: already exist: */ 669: 670: /* check our arguments: */ 671: usage = FALSE; 672: rc = 0; 673: i825x6 = FALSE; 674: regs = FALSE; 675: 676: /* if this connection is for the registers: */ 677: if (TME_ARG_IS(args[1], "csr")) { 678: 679: /* if we already have a register connection, complain: */ 680: if (sun_obie->tme_sun_obie_conn_regs != NULL) { 681: rc = EEXIST; 682: } 683: 684: /* otherwise, make the new connection: */ 685: else { 686: regs = TRUE; 687: } 688: } 689: 690: /* else, if this connection is for the memory: */ 691: else if (TME_ARG_IS(args[1], "memory")) { 692: 693: /* if we already have a memory connection, complain: */ 694: if (sun_obie->tme_sun_obie_conn_memory != NULL) { 695: rc = EEXIST; 696: } 697: } 698: 699: /* else, the connection must be for the i825x6: */ 700: else if (args[1] == NULL) { 701: 702: /* if we already have an i825x6 connection, complain: */ 703: if (sun_obie->tme_sun_obie_conn_i825x6 != NULL) { 704: rc = EEXIST; 705: } 706: 707: /* otherwise, make the new conection: */ 708: else { 709: i825x6 = TRUE; 710: } 711: } 712: 713: /* otherwise, this is a bad argument: */ 714: else { 715: tme_output_append_error(_output, 716: "%s %s, ", 717: args[1], 718: _("unexpected")); 719: usage = TRUE; 720: } 721: 722: if (usage) { 723: tme_output_append_error(_output, 724: "%s %s [ csr | memory ]", 725: _("usage:"), 726: args[0]); 727: rc = EINVAL; 728: } 729: 730: if (rc) { 731: return (rc); 732: } 733: 734: /* make a new connection: */ 735: conn_sun_obie = tme_new0(struct tme_sun_obie_connection, 1); 736: conn_bus = &conn_sun_obie->tme_sun_obie_connection; 737: conn = &conn_bus->tme_bus_connection; 738: 739: /* fill in the generic connection: */ 740: conn->tme_connection_next = *_conns; 741: conn->tme_connection_type = TME_CONNECTION_BUS_GENERIC; 742: conn->tme_connection_score = _tme_sun_obie_connection_score; 743: conn->tme_connection_make = _tme_sun_obie_connection_make; 744: conn->tme_connection_break = _tme_sun_obie_connection_break; 745: 746: /* fill in the generic bus connection: */ 747: conn_bus->tme_bus_subregions.tme_bus_subregion_address_first = 0; 748: conn_bus->tme_bus_subregions.tme_bus_subregion_next = NULL; 749: if (i825x6) { 750: conn_bus->tme_bus_subregions.tme_bus_subregion_address_last = 0xffffff; 751: conn_bus->tme_bus_signals_add = _tme_sun_obie_bus_signals_add; 752: conn_bus->tme_bus_signal = _tme_sun_obie_bus_signal; 753: conn_bus->tme_bus_tlb_set_allocate = _tme_sun_obie_tlb_set_allocate; 754: conn_bus->tme_bus_tlb_fill = _tme_sun_obie_tlb_fill; 755: } 756: else if (regs) { 757: conn_bus->tme_bus_subregions.tme_bus_subregion_address_last = TME_SUN_OBIE_SIZ_REGS - 1; 1.1.1.2 ! root 758: conn_bus->tme_bus_signal = _tme_sun_obie_bus_signal; 1.1 root 759: conn_bus->tme_bus_tlb_fill = _tme_sun_obie_tlb_fill_regs; 760: } 761: else { 762: conn_bus->tme_bus_subregions.tme_bus_subregion_address_last = 0; 763: } 764: 765: /* fill in the internal information: */ 766: conn_sun_obie->tme_sun_obie_connection_regs = regs; 767: 768: /* return the connection side possibility: */ 769: *_conns = conn; 770: return (TME_OK); 771: } 772: 773: /* the new sun_obie function: */ 774: int 775: tme_sun_obie(struct tme_element *element, const char * const *args, char **_output) 776: { 777: struct tme_sun_obie *sun_obie; 778: int arg_i; 779: int usage; 780: 781: /* check our arguments: */ 782: usage = 0; 783: arg_i = 1; 784: for (;;) { 785: 786: if (0) { 787: } 788: 789: /* if we ran out of arguments: */ 790: else if (args[arg_i] == NULL) { 791: 792: break; 793: } 794: 795: /* otherwise this is a bad argument: */ 796: else { 797: tme_output_append_error(_output, 798: "%s %s, ", 799: args[arg_i], 800: _("unexpected")); 801: usage = TRUE; 802: break; 803: } 804: } 805: 806: if (usage) { 807: tme_output_append_error(_output, 808: "%s %s", 809: _("usage:"), 810: args[0]); 811: return (EINVAL); 812: } 813: 814: /* start the sun_obie structure: */ 815: sun_obie = tme_new0(struct tme_sun_obie, 1); 816: sun_obie->tme_sun_obie_element = element; 817: TME_SUN_OBIE_CSR_PUT(sun_obie, 818: (TME_SUN_OBIE_CSR_NORESET 819: | TME_SUN_OBIE_CSR_NOLOOP)); 820: tme_mutex_init(&sun_obie->tme_sun_obie_mutex); 821: tme_rwlock_init(&sun_obie->tme_sun_obie_rwlock); 822: 823: /* fill the element: */ 824: element->tme_element_private = sun_obie; 825: element->tme_element_connections_new = _tme_sun_obie_connections_new; 826: 827: return (TME_OK); 828: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.