|
|
1.1 ! root 1: /* $Id: bus-el.c,v 1.7 2003/05/16 21:48:08 fredette Exp $ */ ! 2: ! 3: /* generic/gen-bus-el.c - a real generic bus element: */ ! 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: bus-el.c,v 1.7 2003/05/16 21:48:08 fredette Exp $"); ! 38: ! 39: /* includes: */ ! 40: #include <tme/generic/bus.h> ! 41: #include <stdlib.h> ! 42: #include <string.h> ! 43: ! 44: /* macros: */ ! 45: ! 46: /* structures: */ ! 47: ! 48: /* this handles a bus connection signal edge: */ ! 49: static int ! 50: _tme_bus_signal(struct tme_bus_connection *conn_bus_edger, unsigned int signal) ! 51: { ! 52: struct tme_bus *bus; ! 53: struct tme_bus_connection_int *conn_bus_int_edger; ! 54: struct tme_bus_connection_int *conn_bus_int; ! 55: unsigned int level_edge; ! 56: struct tme_bus_connection *conn_bus; ! 57: struct tme_bus_connection *conn_bus_other; ! 58: int signal_asserted, need_propagate; ! 59: unsigned int signal_index; ! 60: tme_uint8_t signal_mask; ! 61: int rc; ! 62: int deadlocked; ! 63: ! 64: /* recover our bus: */ ! 65: bus = conn_bus_edger->tme_bus_connection.tme_connection_element->tme_element_private; ! 66: conn_bus_int_edger = (struct tme_bus_connection_int *) conn_bus_edger; ! 67: ! 68: /* take out the level and edge: */ ! 69: level_edge = signal & (TME_BUS_SIGNAL_LEVEL_MASK ! 70: | TME_BUS_SIGNAL_EDGE); ! 71: signal &= ~(TME_BUS_SIGNAL_LEVEL_MASK ! 72: | TME_BUS_SIGNAL_EDGE); ! 73: ! 74: /* lock the bus for writing: */ ! 75: rc = tme_rwlock_timedwrlock(&bus->tme_bus_rwlock, TME_THREAD_TIMEDLOCK); ! 76: if (TME_THREADS_ERRNO(rc) != TME_OK) { ! 77: return (TME_THREADS_ERRNO(rc)); ! 78: } ! 79: ! 80: /* if this device doesn't know its interrupt signal, fix it: */ ! 81: if (signal == TME_BUS_SIGNAL_INT_UNSPEC) { ! 82: signal = conn_bus_int_edger->tme_bus_connection_int_signal_int; ! 83: if (signal == TME_BUS_SIGNAL_INT_UNSPEC) { ! 84: /* this bus connection is misconfigured: */ ! 85: if (!conn_bus_int_edger->tme_bus_connection_int_logged_int) { ! 86: conn_bus_int_edger->tme_bus_connection_int_logged_int = TRUE; ! 87: /* XXX diagnostic */ ! 88: abort(); ! 89: } ! 90: tme_rwlock_unlock(&bus->tme_bus_rwlock); ! 91: return (TME_OK); ! 92: } ! 93: } ! 94: ! 95: /* assume we don't need to propagate this signal across the bus: */ ! 96: need_propagate = FALSE; ! 97: ! 98: /* if this is a random bus-specific signal, just propagate it: */ ! 99: if (TME_BUS_SIGNAL_IS_X(signal)) { ! 100: need_propagate = TRUE; ! 101: } ! 102: ! 103: /* otherwise, this is a generic bus signal: */ ! 104: else { ! 105: ! 106: /* decide whether the device is asserting or negating this signal: */ ! 107: /* XXX we currently assume that for all bus signals handled by this ! 108: function, low implies assertion, and signals are always ORed ! 109: together. this could be configurable, possibly even per-signal: */ ! 110: signal_asserted = TRUE; ! 111: switch (level_edge & TME_BUS_SIGNAL_LEVEL_MASK) { ! 112: case TME_BUS_SIGNAL_LEVEL_LOW: ! 113: case TME_BUS_SIGNAL_LEVEL_ASSERTED: ! 114: break; ! 115: case TME_BUS_SIGNAL_LEVEL_HIGH: ! 116: case TME_BUS_SIGNAL_LEVEL_NEGATED: ! 117: signal_asserted = FALSE; ! 118: break; ! 119: } ! 120: level_edge = ((level_edge & TME_BUS_SIGNAL_EDGE) ! 121: | (signal_asserted ! 122: ? TME_BUS_SIGNAL_LEVEL_ASSERTED ! 123: : TME_BUS_SIGNAL_LEVEL_NEGATED)); ! 124: ! 125: /* get the index and mask of this signal in signal byte arrays: */ ! 126: signal_index = TME_BUS_SIGNAL_BIT_INDEX(signal); ! 127: signal_mask = TME_BUS_SIGNAL_BIT_MASK(signal); ! 128: ! 129: /* if this signal is being asserted: */ ! 130: if (signal_asserted) { ! 131: ! 132: /* if this device wasn't already asserting this signal: */ ! 133: if (!(conn_bus_int_edger->tme_bus_connection_int_signals[signal_index] ! 134: & signal_mask)) { ! 135: ! 136: /* it is now asserting this signal: */ ! 137: conn_bus_int_edger->tme_bus_connection_int_signals[signal_index] ! 138: |= signal_mask; ! 139: bus->tme_bus_signal_asserts[TME_BUS_SIGNAL_WHICH(signal)]++; ! 140: ! 141: /* if this is the only device asserting this signal, ! 142: propagate the change across the bus: */ ! 143: if (bus->tme_bus_signal_asserts[TME_BUS_SIGNAL_WHICH(signal)] == 1) { ! 144: need_propagate = TRUE; ! 145: } ! 146: } ! 147: ! 148: /* otherwise, this device was already asserting this signal: */ ! 149: else { ! 150: assert(bus->tme_bus_signal_asserts[TME_BUS_SIGNAL_WHICH(signal)] > 0); ! 151: } ! 152: } ! 153: ! 154: /* otherwise, this signal is being negated: */ ! 155: else { ! 156: ! 157: /* if this device was asserting this signal: */ ! 158: if (conn_bus_int_edger->tme_bus_connection_int_signals[signal_index] ! 159: & signal_mask) { ! 160: ! 161: /* it is no longer asserting this signal: */ ! 162: conn_bus_int_edger->tme_bus_connection_int_signals[signal_index] ! 163: &= ~signal_mask; ! 164: assert(bus->tme_bus_signal_asserts[TME_BUS_SIGNAL_WHICH(signal)] > 0); ! 165: bus->tme_bus_signal_asserts[TME_BUS_SIGNAL_WHICH(signal)]--; ! 166: } ! 167: ! 168: /* we always propagate across the bus a signal that some device ! 169: has negated, because often code will lazily only send ! 170: negating edges, or other devices might still be asserting it, ! 171: we assume these signals are always ORed together, and it ! 172: kicks (even though this signal isn't edging) emulated ! 173: circuitry that is meant to do things like interrupt ! 174: arbitration, etc.: */ ! 175: if (bus->tme_bus_signal_asserts[TME_BUS_SIGNAL_WHICH(signal)] > 0) { ! 176: level_edge = TME_BUS_SIGNAL_LEVEL_ASSERTED; ! 177: } ! 178: need_propagate = TRUE; ! 179: } ! 180: } ! 181: ! 182: /* if we're propagating this signal across the bus: */ ! 183: rc = TME_OK; ! 184: if (need_propagate) { ! 185: ! 186: /* put the level and edge back in: */ ! 187: signal |= level_edge; ! 188: ! 189: /* assume that we won't deadlock: */ ! 190: deadlocked = FALSE; ! 191: ! 192: /* propagate the signal to each connection to the bus: */ ! 193: for (conn_bus_int = bus->tme_bus_connections; ! 194: conn_bus_int != NULL; ! 195: conn_bus_int = ! 196: (struct tme_bus_connection_int *) ! 197: conn_bus_int->tme_bus_connection_int ! 198: .tme_bus_connection ! 199: .tme_connection_next) { ! 200: conn_bus = &conn_bus_int->tme_bus_connection_int; ! 201: conn_bus_other = ! 202: (struct tme_bus_connection *) ! 203: conn_bus->tme_bus_connection.tme_connection_other; ! 204: ! 205: /* skip this device if it edged the line to begin with: */ ! 206: if (conn_bus == conn_bus_edger) { ! 207: continue; ! 208: } ! 209: ! 210: /* skip this device if it doesn't care about bus signals: */ ! 211: if (conn_bus_other->tme_bus_signal == NULL) { ! 212: continue; ! 213: } ! 214: ! 215: /* give the edge to this connection: */ ! 216: rc = (*conn_bus_other->tme_bus_signal)(conn_bus_other, signal); ! 217: ! 218: /* if we deadlocked, remember to tell the caller: */ ! 219: if (rc == TME_EDEADLK) { ! 220: deadlocked = TRUE; ! 221: } ! 222: } ! 223: rc = (deadlocked ? TME_EDEADLK : TME_OK); ! 224: } ! 225: ! 226: /* unlock the bus: */ ! 227: tme_rwlock_unlock(&bus->tme_bus_rwlock); ! 228: ! 229: /* done: */ ! 230: return (rc); ! 231: } ! 232: ! 233: /* this handles a bus interrupt acknowledge: */ ! 234: static int ! 235: _tme_bus_intack(struct tme_bus_connection *conn_bus_acker, unsigned int signal, int *vector) ! 236: { ! 237: struct tme_bus *bus; ! 238: struct tme_bus_connection_int *conn_bus_int; ! 239: struct tme_bus_connection *conn_bus; ! 240: struct tme_bus_connection *conn_bus_other; ! 241: unsigned int signal_index; ! 242: tme_uint8_t signal_mask; ! 243: int rc; ! 244: ! 245: /* recover our bus: */ ! 246: bus = conn_bus_acker->tme_bus_connection.tme_connection_element->tme_element_private; ! 247: ! 248: /* get rid of any level and edge: */ ! 249: signal &= ~(TME_BUS_SIGNAL_LEVEL_MASK ! 250: | TME_BUS_SIGNAL_EDGE); ! 251: ! 252: /* this must be an interrupt signal: */ ! 253: assert(TME_BUS_SIGNAL_IS_INT(signal)); ! 254: ! 255: /* lock the bus for writing: */ ! 256: rc = tme_rwlock_timedwrlock(&bus->tme_bus_rwlock, TME_THREAD_TIMEDLOCK); ! 257: if (TME_THREADS_ERRNO(rc) != TME_OK) { ! 258: return (TME_THREADS_ERRNO(rc)); ! 259: } ! 260: ! 261: /* get the index and mask of this signal in signal byte arrays: */ ! 262: signal_index = TME_BUS_SIGNAL_BIT_INDEX(signal); ! 263: signal_mask = TME_BUS_SIGNAL_BIT_MASK(signal); ! 264: ! 265: /* find the first connection to the bus that is asserting this ! 266: interrupt signal. if no connection is asserting the signal, ! 267: return ENOENT: */ ! 268: rc = ENOENT; ! 269: for (conn_bus_int = bus->tme_bus_connections; ! 270: conn_bus_int != NULL; ! 271: conn_bus_int = ! 272: (struct tme_bus_connection_int *) ! 273: conn_bus_int->tme_bus_connection_int ! 274: .tme_bus_connection ! 275: .tme_connection_next) { ! 276: conn_bus = &conn_bus_int->tme_bus_connection_int; ! 277: conn_bus_other = ! 278: (struct tme_bus_connection *) ! 279: conn_bus->tme_bus_connection.tme_connection_other; ! 280: ! 281: /* if this device is asserting this interrupt signal: */ ! 282: if (conn_bus_int->tme_bus_connection_int_signals[signal_index] ! 283: & signal_mask) { ! 284: ! 285: /* if this device doesn't acknowledge interrupts, ! 286: return an undefined vector: */ ! 287: if (conn_bus_other->tme_bus_intack == NULL) { ! 288: *vector = TME_BUS_INTERRUPT_VECTOR_UNDEF; ! 289: rc = TME_OK; ! 290: } ! 291: ! 292: /* otherwise, run the interrupt acknowledge with this connection: */ ! 293: else { ! 294: rc = (*conn_bus_other->tme_bus_intack)(conn_bus_other, signal, vector); ! 295: } ! 296: ! 297: /* stop: */ ! 298: break; ! 299: } ! 300: } ! 301: ! 302: /* unlock the bus: */ ! 303: tme_rwlock_unlock(&bus->tme_bus_rwlock); ! 304: ! 305: /* done: */ ! 306: return (rc); ! 307: } ! 308: ! 309: static int ! 310: _tme_bus_fault(void *junk0, struct tme_bus_cycle *junk1) ! 311: { ! 312: return (ENOENT); ! 313: } ! 314: ! 315: /* this fills a TLB entry: */ ! 316: static int ! 317: _tme_bus_tlb_fill(struct tme_bus_connection *conn_bus_asker, ! 318: struct tme_bus_tlb *tlb, ! 319: tme_bus_addr_t address, ! 320: unsigned int cycles) ! 321: { ! 322: struct tme_bus *bus; ! 323: struct tme_bus_connection_int *conn_int; ! 324: int rc; ! 325: ! 326: /* recover our bus and our connection to the asker: */ ! 327: bus = conn_bus_asker->tme_bus_connection.tme_connection_element->tme_element_private; ! 328: conn_int = (struct tme_bus_connection_int *) conn_bus_asker; ! 329: ! 330: /* put our fault handler in the TLB entry: */ ! 331: tlb->tme_bus_tlb_cycle_private = NULL; ! 332: tlb->tme_bus_tlb_cycle = _tme_bus_fault; ! 333: ! 334: /* lock the bus for reading: */ ! 335: rc = tme_rwlock_timedrdlock(&bus->tme_bus_rwlock, TME_THREAD_TIMEDLOCK); ! 336: if (TME_THREADS_ERRNO(rc) != TME_OK) { ! 337: return (TME_THREADS_ERRNO(rc)); ! 338: } ! 339: ! 340: /* call the generic bus support function: */ ! 341: rc = tme_bus_tlb_fill(bus, ! 342: conn_int, ! 343: tlb, address, cycles); ! 344: ! 345: /* unlock the bus: */ ! 346: tme_rwlock_unlock(&bus->tme_bus_rwlock); ! 347: ! 348: /* done: */ ! 349: return (rc); ! 350: } ! 351: ! 352: /* this allocates a new TLB set: */ ! 353: static int ! 354: _tme_bus_tlb_set_allocate(struct tme_bus_connection *conn_bus_asker, ! 355: unsigned int count, unsigned int sizeof_one, ! 356: TME_ATOMIC_POINTER_TYPE(struct tme_bus_tlb **) _tlbs) ! 357: { ! 358: struct tme_bus *bus; ! 359: struct tme_bus_connection_int *conn_int; ! 360: int rc; ! 361: ! 362: /* recover our bus and our connection to the asker: */ ! 363: bus = conn_bus_asker->tme_bus_connection.tme_connection_element->tme_element_private; ! 364: conn_int = (struct tme_bus_connection_int *) conn_bus_asker; ! 365: ! 366: /* lock the bus for reading: */ ! 367: rc = tme_rwlock_timedrdlock(&bus->tme_bus_rwlock, TME_THREAD_TIMEDLOCK); ! 368: if (TME_THREADS_ERRNO(rc) != TME_OK) { ! 369: return (TME_THREADS_ERRNO(rc)); ! 370: } ! 371: ! 372: /* call the generic bus support function: */ ! 373: rc = tme_bus_tlb_set_allocate(bus, ! 374: conn_int, ! 375: count, sizeof_one, ! 376: _tlbs); ! 377: ! 378: /* unlock the bus: */ ! 379: tme_rwlock_unlock(&bus->tme_bus_rwlock); ! 380: ! 381: /* done: */ ! 382: return (rc); ! 383: } ! 384: ! 385: /* this scores a new connection: */ ! 386: static int ! 387: _tme_bus_connection_score(struct tme_connection *conn, unsigned int *_score) ! 388: { ! 389: struct tme_bus *bus; ! 390: struct tme_bus_connection_int *conn_int; ! 391: int rc, ok; ! 392: ! 393: /* both sides must be generic bus connections: */ ! 394: assert(conn->tme_connection_type == TME_CONNECTION_BUS_GENERIC); ! 395: assert(conn->tme_connection_other->tme_connection_type == TME_CONNECTION_BUS_GENERIC); ! 396: ! 397: /* recover our bus and our internal connection side: */ ! 398: bus = conn->tme_connection_element->tme_element_private; ! 399: conn_int = (struct tme_bus_connection_int *) conn; ! 400: ! 401: /* get the address mask from the other side: */ ! 402: conn_int->tme_bus_connection_int_address_last = ! 403: ((struct tme_bus_connection *) conn->tme_connection_other)->tme_bus_address_last; ! 404: ! 405: /* lock the bus for reading: */ ! 406: rc = tme_rwlock_timedrdlock(&bus->tme_bus_rwlock, TME_THREAD_TIMEDLOCK); ! 407: if (TME_THREADS_ERRNO(rc) != TME_OK) { ! 408: return (TME_THREADS_ERRNO(rc)); ! 409: } ! 410: ! 411: /* call the generic bus support function: */ ! 412: ok = tme_bus_connection_ok(bus, ! 413: conn_int); ! 414: ! 415: /* unlock the bus: */ ! 416: tme_rwlock_unlock(&bus->tme_bus_rwlock); ! 417: ! 418: /* return the score: */ ! 419: *_score = (ok ? 1 : 0); ! 420: return (TME_OK); ! 421: } ! 422: ! 423: /* this makes a new connection: */ ! 424: static int ! 425: _tme_bus_connection_make(struct tme_connection *conn, unsigned int state) ! 426: { ! 427: struct tme_bus *bus; ! 428: struct tme_bus_connection_int *conn_int; ! 429: int rc; ! 430: ! 431: /* both sides must be generic bus connections: */ ! 432: assert(conn->tme_connection_type == TME_CONNECTION_BUS_GENERIC); ! 433: assert(conn->tme_connection_other->tme_connection_type == TME_CONNECTION_BUS_GENERIC); ! 434: ! 435: /* recover our bus and our internal connection side: */ ! 436: bus = conn->tme_connection_element->tme_element_private; ! 437: conn_int = (struct tme_bus_connection_int *) conn; ! 438: ! 439: /* lock the bus for writing: */ ! 440: rc = tme_rwlock_timedwrlock(&bus->tme_bus_rwlock, TME_THREAD_TIMEDLOCK); ! 441: if (TME_THREADS_ERRNO(rc) != TME_OK) { ! 442: return (TME_THREADS_ERRNO(rc)); ! 443: } ! 444: ! 445: /* call the generic bus support function: */ ! 446: rc = tme_bus_connection_make(bus, ! 447: conn_int, ! 448: state); ! 449: ! 450: /* unlock the bus: */ ! 451: tme_rwlock_unlock(&bus->tme_bus_rwlock); ! 452: ! 453: return (rc); ! 454: } ! 455: ! 456: /* this breaks a connection: */ ! 457: static int ! 458: _tme_bus_connection_break(struct tme_connection *conn, unsigned int state) ! 459: { ! 460: abort(); ! 461: } ! 462: ! 463: /* this returns the new connections possible: */ ! 464: static int ! 465: _tme_bus_connections_new(struct tme_element *element, ! 466: const char * const *args, ! 467: struct tme_connection **_conns, ! 468: char **_output) ! 469: { ! 470: const struct tme_bus *bus; ! 471: struct tme_bus_connection_int *conn_int; ! 472: struct tme_bus_connection *conn_bus; ! 473: struct tme_connection *conn; ! 474: int ipl; ! 475: int arg_i; ! 476: int usage; ! 477: ! 478: /* recover our bus. we only read the address mask, so we don't lock ! 479: the rwlock: */ ! 480: bus = element->tme_element_private; ! 481: ! 482: /* allocate the new connection side: */ ! 483: conn_int = tme_new0(struct tme_bus_connection_int, 1); ! 484: conn_bus = &conn_int->tme_bus_connection_int; ! 485: conn = &conn_bus->tme_bus_connection; ! 486: ! 487: /* loop reading our arguments: */ ! 488: usage = FALSE; ! 489: arg_i = 1; ! 490: for (;;) { ! 491: ! 492: /* the address of this connection: */ ! 493: if (TME_ARG_IS(args[arg_i + 0], "addr")) { ! 494: conn_int->tme_bus_connection_int_addressable = TRUE; ! 495: conn_int->tme_bus_connection_int_address = tme_bus_addr_parse_any(args[arg_i + 1], &usage); ! 496: if (usage ! 497: || (conn_int->tme_bus_connection_int_address ! 498: > bus->tme_bus_address_mask)) { ! 499: usage = TRUE; ! 500: break; ! 501: } ! 502: arg_i += 2; ! 503: } ! 504: ! 505: /* the interrupt signal for this connection: */ ! 506: else if (TME_ARG_IS(args[arg_i + 0], "ipl") ! 507: && args[arg_i + 1] != NULL ! 508: && (ipl = atoi(args[arg_i + 1])) > 0) { ! 509: conn_int->tme_bus_connection_int_signal_int = TME_BUS_SIGNAL_INT(ipl); ! 510: arg_i += 2; ! 511: } ! 512: ! 513: /* if we've run out of arguments: */ ! 514: else if (args[arg_i + 0] == NULL) { ! 515: break; ! 516: } ! 517: ! 518: /* this is a bad argument: */ ! 519: else { ! 520: tme_output_append_error(_output, ! 521: "%s %s, ", ! 522: args[arg_i], ! 523: _("unexpected")); ! 524: usage = TRUE; ! 525: break; ! 526: } ! 527: } ! 528: ! 529: if (usage) { ! 530: tme_output_append_error(_output, ! 531: "%s %s [ addr %s ] [ ipl %s ]", ! 532: _("usage:"), ! 533: args[0], ! 534: _("BUS-ADDRESS"), ! 535: _("INTERRUPT-LEVEL")); ! 536: tme_free(conn_int); ! 537: return (EINVAL); ! 538: } ! 539: ! 540: /* fill in the bus connection: */ ! 541: conn_bus->tme_bus_address_last = bus->tme_bus_address_mask; ! 542: conn_bus->tme_bus_signal = _tme_bus_signal; ! 543: conn_bus->tme_bus_intack = _tme_bus_intack; ! 544: conn_bus->tme_bus_tlb_set_allocate = _tme_bus_tlb_set_allocate; ! 545: conn_bus->tme_bus_tlb_fill = _tme_bus_tlb_fill; ! 546: ! 547: /* fill in the generic connection: */ ! 548: conn->tme_connection_next = *_conns; ! 549: conn->tme_connection_type = TME_CONNECTION_BUS_GENERIC; ! 550: conn->tme_connection_score = _tme_bus_connection_score; ! 551: conn->tme_connection_make = _tme_bus_connection_make; ! 552: conn->tme_connection_break = _tme_bus_connection_break; ! 553: ! 554: /* return the new connection side: */ ! 555: *_conns = conn; ! 556: return (TME_OK); ! 557: } ! 558: ! 559: /* this creates a new bus element: */ ! 560: TME_ELEMENT_SUB_NEW_DECL(tme_generic,bus) { ! 561: struct tme_bus *bus; ! 562: tme_bus_addr_t bus_size; ! 563: int failed; ! 564: ! 565: /* our arguments must include the bus size, and the ! 566: bus size must be a power of two: */ ! 567: failed = TRUE; ! 568: bus_size = 0; ! 569: if (TME_ARG_IS(args[1], "size")) { ! 570: bus_size = tme_bus_addr_parse_any(args[2], &failed); ! 571: if (bus_size & (bus_size - 1)) { ! 572: failed = TRUE; ! 573: } ! 574: } ! 575: if (failed) { ! 576: tme_output_append_error(_output, ! 577: "%s %s size %s", ! 578: _("usage:"), ! 579: args[0], ! 580: _("SIZE")); ! 581: return (EINVAL); ! 582: } ! 583: ! 584: /* allocate and initialize the new bus: */ ! 585: bus = tme_new0(struct tme_bus, 1); ! 586: tme_rwlock_init(&bus->tme_bus_rwlock); ! 587: bus->tme_bus_address_mask = bus_size - 1; ! 588: bus->tme_bus_addressables_count = 0; ! 589: bus->tme_bus_addressables_size = 1; ! 590: bus->tme_bus_addressables = tme_new(struct tme_bus_connection_int *, ! 591: bus->tme_bus_addressables_size); ! 592: ! 593: /* fill the element: */ ! 594: element->tme_element_private = bus; ! 595: element->tme_element_connections_new = _tme_bus_connections_new; ! 596: ! 597: return (TME_OK); ! 598: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.