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