|
|
1.1 ! root 1: /* $Id: stp222x-mdu.c,v 1.5 2010/06/05 18:59:29 fredette Exp $ */ ! 2: ! 3: /* ic/stp222x-mdu.c - emulation of the Mondo Dispatch Unit of the UPA ! 4: to SBus interface controller (STP2220) and the UPA to PCI interface ! 5: controller (STP2222): */ ! 6: ! 7: /* ! 8: * Copyright (c) 2009 Matt Fredette ! 9: * All rights reserved. ! 10: * ! 11: * Redistribution and use in source and binary forms, with or without ! 12: * modification, are permitted provided that the following conditions ! 13: * are met: ! 14: * 1. Redistributions of source code must retain the above copyright ! 15: * notice, this list of conditions and the following disclaimer. ! 16: * 2. Redistributions in binary form must reproduce the above copyright ! 17: * notice, this list of conditions and the following disclaimer in the ! 18: * documentation and/or other materials provided with the distribution. ! 19: * 3. All advertising materials mentioning features or use of this software ! 20: * must display the following acknowledgement: ! 21: * This product includes software developed by Matt Fredette. ! 22: * 4. The name of the author may not be used to endorse or promote products ! 23: * derived from this software without specific prior written permission. ! 24: * ! 25: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR ! 26: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ! 27: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ! 28: * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, ! 29: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ! 30: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ! 31: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 32: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, ! 33: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ! 34: * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ! 35: * POSSIBILITY OF SUCH DAMAGE. ! 36: */ ! 37: ! 38: #include <tme/common.h> ! 39: _TME_RCSID("$Id: stp222x-mdu.c,v 1.5 2010/06/05 18:59:29 fredette Exp $"); ! 40: ! 41: /* includes: */ ! 42: #include "stp222x-impl.h" ! 43: ! 44: /* macros: */ ! 45: ! 46: /* an interrupt mapping register: */ ! 47: #define TME_STP222X_MDU_IMR_INR ((2 << 10) - (1 << 0)) ! 48: #define TME_STP222X_MDU_IMR_TID ((2 << 30) - (tme_uint32_t) (1 << 26)) ! 49: #define TME_STP222X_MDU_IMR_V TME_BIT(31) ! 50: ! 51: /* interrupt states: */ ! 52: #define TME_STP222X_MDU_STATE_IDLE (0) ! 53: #define TME_STP222X_MDU_STATE_RECEIVED (1) ! 54: #define TME_STP222X_MDU_STATE_PENDING (3) ! 55: ! 56: /* the interrupt retry timer register: */ ! 57: #define TME_STP222X_MDU_RETRY_TIMER_LIMIT ((2 << 19) - (1 << 0)) ! 58: ! 59: /* dispatch states: */ ! 60: #define TME_STP222X_MDU_DISPATCH_NOW (0) ! 61: #define TME_STP222X_MDU_DISPATCH_RETRY(n) (1 + (n)) ! 62: ! 63: /* priorities: */ ! 64: #define TME_STP222X_MDU_PRIORITY_NULL (9) ! 65: ! 66: /* this updates an IDI's bit in the received or pending sets: */ ! 67: #define TME_STP222X_MDU_IDIS_UPDATE(field, op, idi) \ ! 68: do { \ ! 69: field[(idi) \ ! 70: / (sizeof(tme_stp222x_idis_t) * 8)] \ ! 71: op (((tme_stp222x_idis_t) 1) \ ! 72: << ((idi) \ ! 73: % (sizeof(tme_stp222x_idis_t) * 8))); \ ! 74: } while (/* CONSTCOND */ 0) ! 75: ! 76: /* this tests an IDI's bit in an IDI set: */ ! 77: #define TME_STP222X_MDU_IDI_TEST(field, idi) \ ! 78: (field[(idi) \ ! 79: / (sizeof(tme_stp222x_idis_t) * 8)] \ ! 80: & (((tme_stp222x_idis_t) 1) \ ! 81: << ((idi) \ ! 82: % (sizeof(tme_stp222x_idis_t) * 8)))) ! 83: ! 84: /* globals: */ ! 85: ! 86: /* the stp2220 obio interrupt priorities: */ ! 87: static const tme_uint8_t _tme_stp2220_mdu_idi_obio_priority[] = { ! 88: /* TME_STP222X_IDI_SCSI */ 3, ! 89: /* TME_STP222X_IDI_ETHER */ 3, ! 90: /* TME_STP222X_IDI_BPP */ 2, ! 91: /* TME_STP2220_IDI_AUDIO */ 8, ! 92: /* TME_STP2220_IDI_POWER */ 8, ! 93: /* TME_STP2220_IDI_ZS0_ZS1 */ 7, ! 94: /* TME_STP2220_IDI_FD */ 8, ! 95: /* TME_STP2220_IDI_THERM */ 8, ! 96: /* TME_STP2220_IDI_KBD */ 4, ! 97: /* TME_STP2220_IDI_MOUSE */ 4, ! 98: /* TME_STP2220_IDI_SERIAL */ 7, ! 99: /* TME_STP2220_IDI_TIMER(0) */ 6, ! 100: /* TME_STP2220_IDI_TIMER(1) */ 6, ! 101: /* TME_STP2220_IDI_UE */ 8, ! 102: /* TME_STP2220_IDI_CE */ 8, ! 103: /* TME_STP2220_IDI_SBUS_ASYNC */ 8, ! 104: /* TME_STP2220_IDI_POWER_MANAGE */ 1, ! 105: /* TME_STP2220_IDI_UPA */ 5, ! 106: /* TME_STP2220_IDI_RESERVED */ 5, ! 107: }; ! 108: ! 109: /* this maps a register group index into an IDI for an obio ! 110: interrupt: */ ! 111: static tme_uint32_t ! 112: _tme_stp222x_reggroup_index_to_obio_idi(struct tme_stp222x *stp222x, ! 113: tme_uint32_t reggroup_index) ! 114: { ! 115: tme_uint32_t idi; ! 116: ! 117: /* assume that the register group index maps directly to IDI: */ ! 118: idi = TME_STP222X_IDI0_OBIO + reggroup_index; ! 119: ! 120: /* if this is an stp2220: */ ! 121: if (TME_STP222X_IS_2220(stp222x)) { ! 122: ! 123: /* there is a one-register gap before the first timer interrupt: */ ! 124: if (idi > TME_STP2220_IDI_TIMER(0)) { ! 125: idi--; ! 126: } ! 127: } ! 128: ! 129: return (idi); ! 130: } ! 131: ! 132: /* the stp222x interrupt retry thread: */ ! 133: static void ! 134: _tme_stp222x_mdu_retry_th(void *_stp222x) ! 135: { ! 136: struct tme_stp222x *stp222x; ! 137: struct timeval *sleep; ! 138: signed long buffer_i; ! 139: unsigned int dispatch_state; ! 140: ! 141: /* recover our data structures: */ ! 142: stp222x = (struct tme_stp222x *) _stp222x; ! 143: ! 144: /* enter: */ ! 145: tme_stp22xx_enter(&stp222x->tme_stp222x); ! 146: ! 147: /* loop forever: */ ! 148: for (;;) { ! 149: ! 150: /* assume that we can block forever: */ ! 151: sleep = NULL; ! 152: ! 153: /* loop over the dispatch buffers: */ ! 154: buffer_i = TME_STP222X_MDU_BUFFER_COUNT - 1; ! 155: do { ! 156: ! 157: /* if this dispatch buffer is valid: */ ! 158: if (stp222x->tme_stp222x_mdu_dispatch_imr[buffer_i] != !TME_STP222X_MDU_IMR_V) { ! 159: ! 160: /* if this dispatch buffer is retrying: */ ! 161: dispatch_state = stp222x->tme_stp222x_mdu_dispatch_state[buffer_i]; ! 162: if (dispatch_state != TME_STP222X_MDU_DISPATCH_NOW) { ! 163: ! 164: /* NB: we sleep three times for each buffer before retrying ! 165: it. since the sleep time is half of the retry interval, ! 166: this means that the maximum delay is one a half times the ! 167: retry interval, which is the expected value of the delay. ! 168: the minimum delay is exactly the retry interval, and this ! 169: happens only on the stp2222, when the other buffer needs ! 170: a retry right at the beginning of one of the sleeps for ! 171: this buffer. ! 172: ! 173: it's impossible for more than one of the three sleeps a ! 174: buffer does to be interrupted in this way, because there ! 175: is not more than one other buffer: */ ! 176: ! 177: /* if this dispatch buffer has slept three times: */ ! 178: if (dispatch_state == TME_STP222X_MDU_DISPATCH_RETRY(3)) { ! 179: ! 180: /* it's time to try this buffer again: */ ! 181: dispatch_state = TME_STP222X_MDU_DISPATCH_NOW; ! 182: } ! 183: ! 184: /* otherwise, we need to sleep for this buffer: */ ! 185: else { ! 186: ! 187: /* advance the retry state: */ ! 188: dispatch_state++; ! 189: ! 190: /* sleep: */ ! 191: sleep = &stp222x->tme_stp222x_mdu_retry_sleep; ! 192: } ! 193: ! 194: /* update this buffer's dispatch state: */ ! 195: stp222x->tme_stp222x_mdu_dispatch_state[buffer_i] = dispatch_state; ! 196: } ! 197: } ! 198: } while (--buffer_i >= 0); ! 199: ! 200: /* block: */ ! 201: tme_stp22xx_cond_sleep_yield(&stp222x->tme_stp222x, ! 202: &stp222x->tme_stp222x_mdu_retry_cond, ! 203: sleep); ! 204: } ! 205: /* NOTREACHED */ ! 206: } ! 207: ! 208: /* this decodes and arbitrates interrupts: */ ! 209: static void ! 210: _tme_stp222x_mdu_decode_arbitrate(struct tme_stp222x *stp222x) ! 211: { ! 212: signed long buffer_i; ! 213: tme_uint32_t chosen_idi[2]; ! 214: tme_uint32_t chosen_imr[2]; ! 215: unsigned int chosen_priority[2]; ! 216: signed long idis_i; ! 217: tme_stp222x_idis_t idis_arbitrate; ! 218: tme_uint32_t idi; ! 219: tme_uint32_t imr; ! 220: unsigned int priority; ! 221: ! 222: /* start with no chosen interrupts for any CPU buffer, but poison ! 223: any full CPU buffer with an impossibly high priority, to avoid ! 224: overwriting a dispatching interrupt: */ ! 225: buffer_i = TME_STP222X_MDU_BUFFER_COUNT - 1; ! 226: do { ! 227: chosen_idi[buffer_i] = TME_STP222X_IDI_NULL; ! 228: chosen_imr[buffer_i] = !TME_STP222X_MDU_IMR_V; ! 229: chosen_priority[buffer_i] ! 230: = (stp222x->tme_stp222x_mdu_dispatch_imr[buffer_i] == !TME_STP222X_MDU_IMR_V ! 231: ? 0 ! 232: : TME_STP222X_MDU_PRIORITY_NULL); ! 233: } while (--buffer_i >= 0); ! 234: ! 235: /* loop over sets of IDIs: */ ! 236: idis_i = TME_ARRAY_ELS(stp222x->tme_stp222x_mdu_idis_received) - 1; ! 237: do { ! 238: ! 239: /* get another set of IDIs that have been received, but are not ! 240: pending: */ ! 241: idis_arbitrate ! 242: = (stp222x->tme_stp222x_mdu_idis_received[idis_i] ! 243: & ~stp222x->tme_stp222x_mdu_idis_pending[idis_i]); ! 244: if (idis_arbitrate != 0) { ! 245: ! 246: /* loop over the IDIs in this set: */ ! 247: idi = idis_i * (sizeof(idis_arbitrate) * 8); ! 248: do { ! 249: for (; (idis_arbitrate & 1) == 0; idi++, idis_arbitrate >>=1); ! 250: ! 251: /* get the IMR for this IDI: */ ! 252: imr = stp222x->tme_stp222x_mdu_imrs[idi]; ! 253: ! 254: /* if this IMR is valid: */ ! 255: if (imr & TME_STP222X_MDU_IMR_V) { ! 256: ! 257: /* if this is an stp2220: */ ! 258: if (TME_STP222X_IS_2220(stp222x)) { ! 259: ! 260: /* if this is a card IDI: */ ! 261: if (idi < TME_STP222X_IDI0_OBIO) { ! 262: ! 263: /* the SBus priority is our priority: */ ! 264: priority = idi % TME_SBUS_SLOT_INTS; ! 265: } ! 266: ! 267: /* otherwise, this is an obio IDI: */ ! 268: else { ! 269: ! 270: /* get the priority for this obio IDI: */ ! 271: assert ((idi - TME_STP222X_IDI0_OBIO) ! 272: < TME_ARRAY_ELS(_tme_stp2220_mdu_idi_obio_priority)); ! 273: priority = _tme_stp2220_mdu_idi_obio_priority[idi - TME_STP222X_IDI0_OBIO]; ! 274: } ! 275: ! 276: /* all stp2220 interrupts use buffer zero: */ ! 277: buffer_i = 0; ! 278: } ! 279: ! 280: /* otherwise, this is an stp2222: */ ! 281: else { ! 282: abort(); ! 283: } ! 284: ! 285: /* update the chosen IDI: */ ! 286: if (priority > chosen_priority[buffer_i]) { ! 287: chosen_idi[buffer_i] = idi; ! 288: chosen_imr[buffer_i] = imr; ! 289: chosen_priority[buffer_i] = priority; ! 290: } ! 291: } ! 292: ! 293: /* otherwise, this IMR is not valid: */ ! 294: else { ! 295: ! 296: /* clear this IDI's received bit: */ ! 297: /* XXX FIXME - is this right? shouldn't it stay received, ! 298: but just never be pending? */ ! 299: TME_STP222X_MDU_IDIS_UPDATE(stp222x->tme_stp222x_mdu_idis_received, &= ~, idi); ! 300: } ! 301: ! 302: /* advance: */ ! 303: idi++; ! 304: idis_arbitrate >>= 1; ! 305: } while (idis_arbitrate != 0); ! 306: } ! 307: } while (--idis_i >= 0); ! 308: ! 309: /* update the dispatching interrupts: */ ! 310: buffer_i = TME_STP222X_MDU_BUFFER_COUNT - 1; ! 311: do { ! 312: imr = chosen_imr[buffer_i]; ! 313: if (imr != !TME_STP222X_MDU_IMR_V) { ! 314: stp222x->tme_stp222x_mdu_dispatch_idi[buffer_i] = chosen_idi[buffer_i]; ! 315: stp222x->tme_stp222x_mdu_dispatch_imr[buffer_i] = imr; ! 316: assert (stp222x->tme_stp222x_mdu_dispatch_state[buffer_i] == TME_STP222X_MDU_DISPATCH_NOW); ! 317: } ! 318: } while (--buffer_i >= 0); ! 319: } ! 320: ! 321: /* this completes dispatch of an interrupt: */ ! 322: static void ! 323: _tme_stp222x_mdu_dispatch_complete(struct tme_stp22xx *stp22xx, ! 324: struct tme_completion *completion, ! 325: void *arg) ! 326: { ! 327: struct tme_stp222x *stp222x; ! 328: signed long buffer_i; ! 329: int error; ! 330: tme_uint32_t idi; ! 331: ! 332: /* recover our data structure: */ ! 333: stp222x = (struct tme_stp222x *) stp22xx; ! 334: ! 335: /* get the interrupt buffer that was dispatched: */ ! 336: buffer_i = stp222x->tme_stp222x_mdu_dispatch_buffer; ! 337: assert (stp222x->tme_stp222x_mdu_dispatch_imr[buffer_i] != !TME_STP222X_MDU_IMR_V); ! 338: assert (stp222x->tme_stp222x_mdu_dispatch_state[buffer_i] == TME_STP222X_MDU_DISPATCH_NOW); ! 339: ! 340: /* get any error code: */ ! 341: error = completion->tme_completion_error; ! 342: ! 343: /* if this interrupt was ACKed: */ ! 344: if (error == TME_OK) { ! 345: ! 346: /* clear the dispatched interrupt: */ ! 347: stp222x->tme_stp222x_mdu_dispatch_imr[buffer_i] = !TME_STP222X_MDU_IMR_V; ! 348: ! 349: /* get the IDI that was dispatched: */ ! 350: idi = stp222x->tme_stp222x_mdu_dispatch_idi[buffer_i]; ! 351: ! 352: /* if the dispatched interrupt is pulse-driven: */ ! 353: /* XXX FIXME - we assume that TME_STP2220_IDI_RESERVED is pulse-driven: */ ! 354: if (TME_STP222X_IS_2220(stp222x) ! 355: ? (idi == TME_STP2220_IDI_UPA ! 356: || idi == TME_STP2220_IDI_RESERVED) ! 357: : (idi == TME_STP2222_IDI_FFB0 ! 358: || idi == TME_STP2222_IDI_FFB1)) { ! 359: ! 360: /* nothing to do */ ! 361: } ! 362: ! 363: /* otherwise, the dispatched interrupt is level-driven: */ ! 364: else { ! 365: ! 366: /* set this IDI's pending bit: */ ! 367: TME_STP222X_MDU_IDIS_UPDATE(stp222x->tme_stp222x_mdu_idis_pending, |= , idi); ! 368: } ! 369: ! 370: /* decode and arbitrate again: */ ! 371: _tme_stp222x_mdu_decode_arbitrate(stp222x); ! 372: } ! 373: ! 374: /* otherwise, if interrupt was NACKed: */ ! 375: else if (error == EAGAIN) { ! 376: ! 377: /* we need to retry this interrupt buffer later: */ ! 378: stp222x->tme_stp222x_mdu_dispatch_state[buffer_i] = TME_STP222X_MDU_DISPATCH_RETRY(0); ! 379: ! 380: /* wake up the retry thread: */ ! 381: tme_stp22xx_cond_notify(&stp222x->tme_stp222x_mdu_retry_cond); ! 382: } ! 383: ! 384: /* the interrupt target must not exist: */ ! 385: else { ! 386: assert (error == ENOENT); ! 387: ! 388: /* XXX FIXME - what happens in this case? */ ! 389: abort(); ! 390: } ! 391: ! 392: /* round-robin the interrupt buffer to dispatch: */ ! 393: buffer_i = (buffer_i + 1) % TME_STP222X_MDU_BUFFER_COUNT; ! 394: stp222x->tme_stp222x_mdu_dispatch_buffer = buffer_i; ! 395: ! 396: /* unused: */ ! 397: arg = 0; ! 398: } ! 399: ! 400: /* this dispatches an interrupt: */ ! 401: int ! 402: tme_stp222x_mdu_dispatch(struct tme_stp222x *stp222x) ! 403: { ! 404: unsigned long buffer_i; ! 405: struct tme_upa_bus_connection *conn_upa; ! 406: struct tme_completion *completion; ! 407: tme_uint32_t imr; ! 408: tme_uint32_t mid; ! 409: tme_uint64_t interrupt_data[8]; ! 410: struct tme_upa_bus_connection *conn_upa_other; ! 411: ! 412: /* find a full interrupt buffer: */ ! 413: buffer_i = stp222x->tme_stp222x_mdu_dispatch_buffer; ! 414: for (;;) { ! 415: ! 416: /* if this interrupt buffer is full, and can be dispatched now: */ ! 417: if (stp222x->tme_stp222x_mdu_dispatch_imr[buffer_i] != !TME_STP222X_MDU_IMR_V ! 418: && stp222x->tme_stp222x_mdu_dispatch_state[buffer_i] == TME_STP222X_MDU_DISPATCH_NOW) { ! 419: break; ! 420: } ! 421: ! 422: /* round-robin to the next interrupt buffer: */ ! 423: buffer_i = (buffer_i + 1) % TME_STP222X_MDU_BUFFER_COUNT; ! 424: ! 425: /* if all interrupt buffers are empty: */ ! 426: if (buffer_i == stp222x->tme_stp222x_mdu_dispatch_buffer) { ! 427: ! 428: /* we didn't dispatch an interrupt: */ ! 429: return (FALSE); ! 430: } ! 431: } ! 432: stp222x->tme_stp222x_mdu_dispatch_buffer = buffer_i; ! 433: ! 434: /* busy the UPA bus connection: */ ! 435: conn_upa = tme_stp222x_busy_upa(stp222x); ! 436: ! 437: /* allocate a completion: */ ! 438: completion ! 439: = tme_stp222x_completion_alloc(stp222x, ! 440: _tme_stp222x_mdu_dispatch_complete, ! 441: (void *) NULL); ! 442: ! 443: /* get the interrupt information: */ ! 444: imr = stp222x->tme_stp222x_mdu_dispatch_imr[buffer_i]; ! 445: mid = TME_FIELD_MASK_EXTRACTU(imr, TME_STP222X_MDU_IMR_TID); ! 446: memset(interrupt_data, 0, sizeof(interrupt_data)); ! 447: interrupt_data[0] = tme_htobe_u64(TME_FIELD_MASK_EXTRACTU(imr, TME_STP222X_MDU_IMR_INR)); ! 448: ! 449: /* leave: */ ! 450: tme_stp222x_leave(stp222x); ! 451: ! 452: /* call out the interrupt: */ ! 453: conn_upa_other = (struct tme_upa_bus_connection *) conn_upa->tme_upa_bus_connection.tme_bus_connection.tme_connection_other; ! 454: (*conn_upa_other->tme_upa_bus_interrupt) ! 455: (conn_upa_other, ! 456: mid, ! 457: interrupt_data, ! 458: completion); ! 459: ! 460: /* reenter: */ ! 461: stp222x = tme_stp222x_enter_bus(&conn_upa->tme_upa_bus_connection); ! 462: ! 463: /* unbusy the UPA bus connection: */ ! 464: tme_stp222x_unbusy_bus(stp222x, &conn_upa->tme_upa_bus_connection); ! 465: ! 466: /* we dispatched an interrupt: */ ! 467: return (TRUE); ! 468: } ! 469: ! 470: /* this receives an interrupt: */ ! 471: void ! 472: tme_stp222x_mdu_receive(struct tme_stp222x *stp222x, ! 473: tme_uint32_t idi) ! 474: { ! 475: ! 476: /* set this IDI's received bit: */ ! 477: TME_STP222X_MDU_IDIS_UPDATE(stp222x->tme_stp222x_mdu_idis_received, |= , idi); ! 478: ! 479: /* decode and arbitrate again: */ ! 480: _tme_stp222x_mdu_decode_arbitrate(stp222x); ! 481: } ! 482: ! 483: /* this updates the interrupt concentrator: */ ! 484: void ! 485: tme_stp222x_mdu_intcon(struct tme_stp222x *stp222x, ! 486: tme_uint32_t idi, ! 487: tme_uint32_t level) ! 488: { ! 489: ! 490: /* NB: the interrupt concentrator is really in the RIC chip ! 491: (STP2210): */ ! 492: ! 493: /* if this is an stp2220, and this is the zs0/zs1 IDI: */ ! 494: if (TME_STP222X_IS_2220(stp222x) ! 495: && idi == TME_STP2220_IDI_ZS0_ZS1) { ! 496: ! 497: /* the interrupt signals from zs0 and zs1 are wired together ! 498: somewhere in a real system, probably inside the sym89c105 ! 499: (which is apparently not identical to an ncr89c105, because the ! 500: latter doesn't even have output pins for its individual ! 501: functions' interrupts). we have to mimic this wiring here: */ ! 502: ! 503: /* if the interrupt signal is being asserted, increase the active ! 504: count, otherwise decrease the active count. the active count ! 505: (which is unsigned) can never be greater than two: */ ! 506: assert (level == TME_BUS_SIGNAL_LEVEL_ASSERTED ! 507: || level == TME_BUS_SIGNAL_LEVEL_NEGATED); ! 508: stp222x->tme_stp2220_mdu_idi_zs0_zs1_active ! 509: += (level == TME_BUS_SIGNAL_LEVEL_ASSERTED ! 510: ? 1 ! 511: : -1); ! 512: assert (stp222x->tme_stp2220_mdu_idi_zs0_zs1_active <= 2); ! 513: ! 514: /* if the interrupt signal is being asserted, but the active count ! 515: was already one, or if the interrupt signal is being negated, ! 516: but the active count is still one: */ ! 517: if ((level == TME_BUS_SIGNAL_LEVEL_ASSERTED) ! 518: != stp222x->tme_stp2220_mdu_idi_zs0_zs1_active) { ! 519: ! 520: /* the state of the interrupt signal at the RIC chip is ! 521: unchanged: */ ! 522: return; ! 523: } ! 524: } ! 525: ! 526: /* if this interrupt signal is being asserted: */ ! 527: if (level == TME_BUS_SIGNAL_LEVEL_ASSERTED) { ! 528: ! 529: /* set this IDI's active bit: */ ! 530: TME_STP222X_MDU_IDIS_UPDATE(stp222x->tme_stp222x_mdu_idis_active, |= , idi); ! 531: ! 532: /* receive this interrupt: */ ! 533: tme_stp222x_mdu_receive(stp222x, idi); ! 534: } ! 535: ! 536: /* otherwise, this interrupt signal must be being negated: */ ! 537: else { ! 538: assert (level == TME_BUS_SIGNAL_LEVEL_NEGATED); ! 539: ! 540: /* clear this IDI's active bit: */ ! 541: TME_STP222X_MDU_IDIS_UPDATE(stp222x->tme_stp222x_mdu_idis_active, &= ~, idi); ! 542: } ! 543: } ! 544: ! 545: /* this recalculates the interrupt retry period: */ ! 546: static void ! 547: _tme_stp222x_mdu_retry_set(struct tme_stp222x *stp222x) ! 548: { ! 549: tme_uint64_t sleep_usec; ! 550: ! 551: /* the retry timer has a period of 15.7ms at the maximum limit of ! 552: 2^20 ticks. calculate half of the period of the retry timer for ! 553: _tme_stp222x_mdu_retry_th(): */ ! 554: sleep_usec = TME_FIELD_MASK_EXTRACTU(stp222x->tme_stp222x_mdu_retry, TME_STP222X_MDU_RETRY_TIMER_LIMIT) + 1; ! 555: sleep_usec *= 15700; ! 556: #if (TME_STP222X_MDU_RETRY_TIMER_LIMIT & 1) == 0 ! 557: #error "TME_STP222X_MDU_RETRY_TIMER_LIMIT changed" ! 558: #endif ! 559: sleep_usec = (sleep_usec + TME_STP222X_MDU_RETRY_TIMER_LIMIT) / (TME_STP222X_MDU_RETRY_TIMER_LIMIT + 1); ! 560: stp222x->tme_stp222x_mdu_retry_sleep.tv_sec = 0; ! 561: stp222x->tme_stp222x_mdu_retry_sleep.tv_usec = sleep_usec; ! 562: } ! 563: ! 564: /* the MDU IMR and retry register handler: */ ! 565: void ! 566: tme_stp222x_mdu_regs_imr_retry(struct tme_stp222x *stp222x, ! 567: struct tme_stp222x_reg *reg) ! 568: { ! 569: tme_uint32_t reggroup; ! 570: tme_uint32_t reggroup_index; ! 571: tme_uint32_t imr_partial; ! 572: tme_uint32_t idi; ! 573: const char *name; ! 574: ! 575: /* get the register: */ ! 576: reggroup = TME_STP222X_REGGROUP_WHICH(reg->tme_stp222x_reg_address); ! 577: reggroup_index = TME_STP222X_REGGROUP_INDEX(reg->tme_stp222x_reg_address); ! 578: ! 579: /* assume that this is a write to a partial IMR, and get a partial ! 580: IMR value: */ ! 581: imr_partial ! 582: = (reg->tme_stp222x_reg_value ! 583: & (TME_STP222X_MDU_IMR_TID ! 584: | TME_STP222X_MDU_IMR_V)); ! 585: ! 586: /* assume that this is a register for an obio interrupt: */ ! 587: idi = _tme_stp222x_reggroup_index_to_obio_idi(stp222x, reggroup_index); ! 588: ! 589: /* dispatch on the register: */ ! 590: name = NULL; ! 591: switch (reggroup) { ! 592: ! 593: /* the stp2220 SBus card IMRs and the retry register: */ ! 594: case 0x2c: ! 595: if (__tme_predict_false(!TME_STP222X_IS_2220(stp222x))) { ! 596: return; ! 597: } ! 598: ! 599: /* if this is an SBus card IMR: */ ! 600: if (reggroup_index < TME_STP2220_SLOTS_CARD) { ! 601: ! 602: /* get the IDI for this card's ipl 0 interrupt. SBus ipl 0 ! 603: doesn't really exist, but the partial IMR for this IDI will ! 604: have zeros in the ipl position, which is what a read must ! 605: return: */ ! 606: idi = reggroup_index * TME_SBUS_SLOT_INTS; ! 607: ! 608: /* if this is a write: */ ! 609: if (reg->tme_stp222x_reg_write) { ! 610: ! 611: /* write the partial IMRs for all of this card's ipls, only ! 612: updating the V and TID fields: */ ! 613: do { ! 614: stp222x->tme_stp222x_mdu_imrs[idi] ! 615: = ((stp222x->tme_stp222x_mdu_imrs[idi] ! 616: & ~(TME_STP222X_MDU_IMR_TID ! 617: | TME_STP222X_MDU_IMR_V)) ! 618: | imr_partial); ! 619: } while (++idi % TME_SBUS_SLOT_INTS); ! 620: idi -= TME_SBUS_SLOT_INTS; ! 621: } ! 622: ! 623: /* otherwise, this is a read: */ ! 624: else { ! 625: ! 626: /* read the partial IMR for this card: */ ! 627: reg->tme_stp222x_reg_value = stp222x->tme_stp222x_mdu_imrs[idi]; ! 628: } ! 629: break; ! 630: } ! 631: /* FALLTHROUGH */ ! 632: ! 633: /* the STP2222 retry register: */ ! 634: case 0x1a: ! 635: if (__tme_predict_false(reg->tme_stp222x_reg_address ! 636: != (TME_STP222X_IS_2220(stp222x) ! 637: ? 0x2c20 ! 638: : 0x1a00))) { ! 639: return; ! 640: } ! 641: if (reg->tme_stp222x_reg_write) { ! 642: stp222x->tme_stp222x_mdu_retry = reg->tme_stp222x_reg_value; ! 643: _tme_stp222x_mdu_retry_set(stp222x); ! 644: } ! 645: else { ! 646: reg->tme_stp222x_reg_value = stp222x->tme_stp222x_mdu_retry; ! 647: } ! 648: name = "RETRY"; ! 649: break; ! 650: ! 651: /* the STP2222 PCI card IMRs: */ ! 652: case 0x0c: ! 653: if (__tme_predict_false(TME_STP222X_IS_2220(stp222x))) { ! 654: return; ! 655: } ! 656: ! 657: /* if this is not a PCI card IMR: */ ! 658: idi = reggroup_index * TME_PCI_SLOT_INTS; ! 659: if (__tme_predict_false((((1 << TME_STP2222_IDI_CARD(0, 0, 0)) ! 660: | (1 << TME_STP2222_IDI_CARD(0, 1, 0)) ! 661: | (1 << TME_STP2222_IDI_CARD(1, 0, 0)) ! 662: | (1 << TME_STP2222_IDI_CARD(1, 1, 0)) ! 663: | (1 << TME_STP2222_IDI_CARD(1, 2, 0)) ! 664: | (1 << TME_STP2222_IDI_CARD(1, 3, 0))) ! 665: & (1 << idi)) == 0)) { ! 666: return; ! 667: } ! 668: ! 669: /* if this is a write: */ ! 670: if (reg->tme_stp222x_reg_write) { ! 671: ! 672: /* write the partial IMRs for all of this PCI card's INTx, only ! 673: updating the V and TID fields: */ ! 674: do { ! 675: stp222x->tme_stp222x_mdu_imrs[idi] ! 676: = ((stp222x->tme_stp222x_mdu_imrs[idi] ! 677: & ~(TME_STP222X_MDU_IMR_TID ! 678: | TME_STP222X_MDU_IMR_V)) ! 679: | imr_partial); ! 680: } while (++idi % TME_PCI_SLOT_INTS); ! 681: idi -= TME_PCI_SLOT_INTS; ! 682: } ! 683: ! 684: /* otherwise, this is a read: */ ! 685: else { ! 686: ! 687: /* read the partial IMR for this PCI card's INTA: */ ! 688: reg->tme_stp222x_reg_value = stp222x->tme_stp222x_mdu_imrs[idi]; ! 689: } ! 690: break; ! 691: ! 692: /* the STP2222 alternate FFB0 and FFB1 IMRs: */ ! 693: case 0x60: ! 694: case 0x80: ! 695: idi = (reggroup == 0x60 ? TME_STP2222_IDI_FFB0 : TME_STP2222_IDI_FFB1); ! 696: reggroup = 0x10; ! 697: /* FALLTHROUGH */ ! 698: ! 699: /* the obio IMRs: */ ! 700: default: ! 701: ! 702: /* if this is the wrong obio IMR register group for this part, or ! 703: if this is not an obio IMR, return failure: */ ! 704: if (TME_STP222X_IS_2220(stp222x)) { ! 705: if (__tme_predict_false(reggroup != 0x30 ! 706: || idi > TME_STP2220_IDI_RESERVED)) { ! 707: return; ! 708: } ! 709: } ! 710: else { ! 711: if (__tme_predict_false(reggroup != 0x10 ! 712: || idi > TME_STP2222_IDI_FFB1)) { ! 713: return; ! 714: } ! 715: } ! 716: ! 717: /* if this is an obio IMR write: */ ! 718: if (reg->tme_stp222x_reg_write) { ! 719: ! 720: /* if this is a obio full IMR write: */ ! 721: if (TME_STP222X_IS_2220(stp222x) ! 722: ? (idi == TME_STP2220_IDI_UPA ! 723: || idi == TME_STP2220_IDI_RESERVED) ! 724: : (idi == TME_STP2222_IDI_FFB0 ! 725: || idi == TME_STP2222_IDI_FFB1)) { ! 726: ! 727: /* do the obio full IMR write: */ ! 728: stp222x->tme_stp222x_mdu_imrs[idi] ! 729: = (reg->tme_stp222x_reg_value ! 730: & (TME_STP222X_MDU_IMR_INR ! 731: | TME_STP222X_MDU_IMR_TID ! 732: | TME_STP222X_MDU_IMR_V)); ! 733: } ! 734: ! 735: /* otherwise, this is a obio partial IMR write: */ ! 736: else { ! 737: ! 738: /* do the obio partial IMR write: */ ! 739: stp222x->tme_stp222x_mdu_imrs[idi] ! 740: = ((stp222x->tme_stp222x_mdu_imrs[idi] ! 741: & ~(TME_STP222X_MDU_IMR_TID ! 742: | TME_STP222X_MDU_IMR_V)) ! 743: | imr_partial); ! 744: } ! 745: } ! 746: ! 747: /* otherwise, read the obio IMR: */ ! 748: else { ! 749: reg->tme_stp222x_reg_value = stp222x->tme_stp222x_mdu_imrs[idi]; ! 750: } ! 751: break; ! 752: } ! 753: ! 754: if (name == NULL) { ! 755: tme_log(TME_STP222X_LOG_HANDLE(stp222x), 2000, TME_OK, ! 756: (TME_STP222X_LOG_HANDLE(stp222x), ! 757: _("MDU IMR[0x%x] %s 0x%" TME_PRIx64), ! 758: idi, ! 759: (reg->tme_stp222x_reg_write ! 760: ? "<-" ! 761: : "->"), ! 762: reg->tme_stp222x_reg_value)); ! 763: } ! 764: else { ! 765: tme_log(TME_STP222X_LOG_HANDLE(stp222x), 2000, TME_OK, ! 766: (TME_STP222X_LOG_HANDLE(stp222x), ! 767: _("MDU %s %s 0x%" TME_PRIx64), ! 768: name, ! 769: (reg->tme_stp222x_reg_write ! 770: ? "<-" ! 771: : "->"), ! 772: reg->tme_stp222x_reg_value)); ! 773: } ! 774: ! 775: /* this register access has been completed: */ ! 776: reg->tme_stp222x_reg_completed = TRUE; ! 777: } ! 778: ! 779: /* the MDU clear register handler: */ ! 780: void ! 781: tme_stp222x_mdu_regs_clear(struct tme_stp222x *stp222x, ! 782: struct tme_stp222x_reg *reg) ! 783: { ! 784: tme_uint32_t reggroup; ! 785: tme_uint32_t reggroup_index; ! 786: tme_uint32_t idi; ! 787: tme_uint32_t mdu_state; ! 788: tme_uint32_t imr; ! 789: unsigned long buffer_i; ! 790: ! 791: /* get the register: */ ! 792: reggroup = TME_STP222X_REGGROUP_WHICH(reg->tme_stp222x_reg_address); ! 793: reggroup_index = TME_STP222X_REGGROUP_INDEX(reg->tme_stp222x_reg_address); ! 794: ! 795: /* assume that this is a register for an obio interrupt: */ ! 796: idi = _tme_stp222x_reggroup_index_to_obio_idi(stp222x, reggroup_index); ! 797: ! 798: /* dispatch on the register: */ ! 799: switch (reggroup) { ! 800: ! 801: /* the STP2220 SBus and obio card clears: */ ! 802: case 0x34: ! 803: idi = reggroup_index; ! 804: /* FALLTHROUGH */ ! 805: case 0x38: ! 806: if (__tme_predict_false(!TME_STP222X_IS_2220(stp222x))) { ! 807: return; ! 808: } ! 809: if (__tme_predict_false(idi > TME_STP2220_IDI_POWER_MANAGE)) { ! 810: return; ! 811: } ! 812: break; ! 813: ! 814: /* the STP2222 PCI card clears: */ ! 815: case 0x14: ! 816: if (__tme_predict_false(TME_STP222X_IS_2220(stp222x))) { ! 817: return; ! 818: } ! 819: ! 820: /* if this is not a PCI card clear register: */ ! 821: idi = reggroup_index; ! 822: if (idi >= TME_STP2222_IDI_CARD(0, 2, 0) ! 823: && idi < TME_STP2222_IDI_CARD(1, 0, 0)) { ! 824: return; ! 825: } ! 826: break; ! 827: ! 828: /* the STP2222 obio clears: */ ! 829: default: ! 830: assert (reggroup == 0x10); ! 831: if (__tme_predict_false(TME_STP222X_IS_2220(stp222x))) { ! 832: return; ! 833: } ! 834: if (__tme_predict_false(idi > TME_STP2222_IDI_POWER_MANAGE)) { ! 835: return; ! 836: } ! 837: break; ! 838: } ! 839: ! 840: /* if this is a write: */ ! 841: if (reg->tme_stp222x_reg_write) { ! 842: ! 843: /* update the MDU state for this IDI: */ ! 844: mdu_state = reg->tme_stp222x_reg_value; ! 845: if ((mdu_state & TME_STP222X_MDU_STATE_RECEIVED) ! 846: || TME_STP222X_MDU_IDI_TEST(stp222x->tme_stp222x_mdu_idis_active, idi)) { ! 847: TME_STP222X_MDU_IDIS_UPDATE(stp222x->tme_stp222x_mdu_idis_received, |= , idi); ! 848: } ! 849: else { ! 850: TME_STP222X_MDU_IDIS_UPDATE(stp222x->tme_stp222x_mdu_idis_received, &= ~, idi); ! 851: } ! 852: if (mdu_state == TME_STP222X_MDU_STATE_PENDING) { ! 853: TME_STP222X_MDU_IDIS_UPDATE(stp222x->tme_stp222x_mdu_idis_pending, |= , idi); ! 854: } ! 855: else { ! 856: TME_STP222X_MDU_IDIS_UPDATE(stp222x->tme_stp222x_mdu_idis_pending, &= ~, idi); ! 857: ! 858: /* get the IMR for this IDI: */ ! 859: imr = stp222x->tme_stp222x_mdu_imrs[idi]; ! 860: ! 861: /* loop over the interrupt dispatch buffers: */ ! 862: for (buffer_i = 0; buffer_i < TME_STP222X_MDU_BUFFER_COUNT; buffer_i++) { ! 863: ! 864: /* if this interrupt dispatch buffer has the same V and TID ! 865: values as the IMR for this IDI: */ ! 866: if (((stp222x->tme_stp222x_mdu_dispatch_imr[buffer_i] ! 867: ^ imr) ! 868: & (TME_STP222X_MDU_IMR_V ! 869: + TME_STP222X_MDU_IMR_TID)) == 0) { ! 870: ! 871: /* assume that this interrupt buffer has its V bit set, and ! 872: force it to dispatch now (if its V bit is clear, this ! 873: should not change its dispatch state): */ ! 874: /* NB: this is a hack to improve interrupt latency when the ! 875: retry thread has high latency (due to poor ! 876: tme_cond_sleep_yield() sleep resolution): whenever a CPU ! 877: writes an MDU state other than pending for an IDI, assume ! 878: that the CPU can accept another interrupt and force any ! 879: interrupt waiting to dispatch to that CPU to dispatch ! 880: immediately: */ ! 881: assert ((imr & TME_STP222X_MDU_IMR_V) ! 882: || (stp222x->tme_stp222x_mdu_dispatch_state[buffer_i] ! 883: == TME_STP222X_MDU_DISPATCH_NOW)); ! 884: stp222x->tme_stp222x_mdu_dispatch_state[buffer_i] = TME_STP222X_MDU_DISPATCH_NOW; ! 885: } ! 886: } ! 887: } ! 888: ! 889: /* decode and arbitrate again: */ ! 890: _tme_stp222x_mdu_decode_arbitrate(stp222x); ! 891: ! 892: tme_log(TME_STP222X_LOG_HANDLE(stp222x), 2000, TME_OK, ! 893: (TME_STP222X_LOG_HANDLE(stp222x), ! 894: _("MDU clear[0x%x] <- 0x%" TME_PRIx32), ! 895: idi, ! 896: mdu_state)); ! 897: } ! 898: ! 899: /* otherwise, this is a read: */ ! 900: else { ! 901: reg->tme_stp222x_reg_value = 0; ! 902: } ! 903: ! 904: /* this register access has been completed: */ ! 905: reg->tme_stp222x_reg_completed = TRUE; ! 906: } ! 907: ! 908: /* the MDU diagnostic register handler: */ ! 909: void ! 910: tme_stp222x_mdu_regs_diag(struct tme_stp222x *stp222x, ! 911: struct tme_stp222x_reg *reg) ! 912: { ! 913: unsigned long idis_i; ! 914: tme_stp222x_idis_t idis_received; ! 915: tme_stp222x_idis_t idis_pending; ! 916: tme_uint32_t bit; ! 917: tme_uint32_t value_32_63; ! 918: tme_uint32_t value_0_31; ! 919: ! 920: /* check the register and cycle type: */ ! 921: assert (sizeof(tme_stp222x_idis_t) == sizeof(tme_uint32_t)); ! 922: idis_i = TME_STP222X_REGGROUP_INDEX(reg->tme_stp222x_reg_address); ! 923: if (__tme_predict_false(idis_i > TME_ARRAY_ELS(stp222x->tme_stp222x_mdu_idis_received))) { ! 924: return; ! 925: } ! 926: if (__tme_predict_false(reg->tme_stp222x_reg_write)) { ! 927: return; ! 928: } ! 929: ! 930: /* get the selected internal received and pending registers: */ ! 931: idis_received = stp222x->tme_stp222x_mdu_idis_received[idis_i]; ! 932: idis_pending = stp222x->tme_stp222x_mdu_idis_pending[idis_i]; ! 933: ! 934: /* if this diagnostic register covers the obio interrupts: */ ! 935: if (idis_i == 1) { ! 936: ! 937: /* both parts have two pulse-driven interrupts at the end of the ! 938: diagnostic register, using only one bit each instead of the two ! 939: bits each that the level-driven interrupts use. we move the ! 940: received bit of the last pulse-driven interrupt into the ! 941: pending bit for the next to last pulse-driven interrupt, to ! 942: make the two pulse-driven interrupts look like a single ! 943: level-driven interrupt: */ ! 944: if (TME_STP222X_IS_2220(stp222x)) { ! 945: idis_pending ! 946: |= ((idis_received & (1 << (TME_STP2220_IDI_RESERVED - TME_STP222X_IDI0_OBIO))) ! 947: >> (TME_STP2220_IDI_RESERVED - TME_STP2220_IDI_UPA)); ! 948: idis_received &= ~ (tme_uint32_t) (1 << (TME_STP2220_IDI_RESERVED - TME_STP222X_IDI0_OBIO)); ! 949: } ! 950: else { ! 951: idis_pending ! 952: |= ((idis_received & (1 << (TME_STP2222_IDI_FFB1 - TME_STP222X_IDI0_OBIO))) ! 953: >> (TME_STP2222_IDI_FFB1 - TME_STP2222_IDI_FFB0)); ! 954: idis_received &= ~ (tme_uint32_t) (1 << (TME_STP2222_IDI_FFB1 - TME_STP222X_IDI0_OBIO)); ! 955: } ! 956: } ! 957: ! 958: /* make bits 32..63 of the value: */ ! 959: bit = ((tme_uint32_t) 1) << 31; ! 960: value_32_63 = 0; ! 961: do { ! 962: if (idis_pending & (((tme_uint32_t) 1) << 31)) { ! 963: value_32_63 += bit; ! 964: } ! 965: idis_pending <<= 1; ! 966: bit >>= 1; ! 967: if (idis_received & (((tme_uint32_t) 1) << 31)) { ! 968: value_32_63 += bit; ! 969: } ! 970: idis_received <<= 1; ! 971: bit >>= 1; ! 972: } while (bit != 0); ! 973: ! 974: /* make bits 0..31 of the value: */ ! 975: value_0_31 = 0; ! 976: bit = ((tme_uint32_t) 1) << 31; ! 977: do { ! 978: if (idis_pending & (((tme_uint32_t) 1) << 31)) { ! 979: value_0_31 += bit; ! 980: } ! 981: idis_pending <<= 1; ! 982: bit >>= 1; ! 983: if (idis_received & (((tme_uint32_t) 1) << 31)) { ! 984: value_0_31 += bit; ! 985: } ! 986: idis_received <<= 1; ! 987: bit >>= 1; ! 988: } while (bit != 0); ! 989: ! 990: reg->tme_stp222x_reg_value ! 991: = ((((tme_uint64_t) value_32_63) << 32) ! 992: | value_0_31); ! 993: ! 994: tme_log(TME_STP222X_LOG_HANDLE(stp222x), 2000, TME_OK, ! 995: (TME_STP222X_LOG_HANDLE(stp222x), ! 996: _("MDU DIAG -> 0x%" TME_PRIx64), ! 997: reg->tme_stp222x_reg_value)); ! 998: ! 999: /* this register access has been completed: */ ! 1000: reg->tme_stp222x_reg_completed = TRUE; ! 1001: } ! 1002: ! 1003: /* this updates the IGN for the partial IMRs: */ ! 1004: void ! 1005: tme_stp222x_mdu_ign_update(struct tme_stp222x *stp222x, ! 1006: tme_uint32_t ign) ! 1007: { ! 1008: tme_uint32_t idi; ! 1009: tme_uint32_t ino; ! 1010: ! 1011: /* loop over all IDIs: */ ! 1012: for (idi = 0; idi < TME_STP222X_IDI_NULL; idi++) { ! 1013: ! 1014: /* if this IDI has a partial IMR: */ ! 1015: if (TME_STP222X_IS_2220(stp222x) ! 1016: ? (idi != TME_STP2220_IDI_UPA ! 1017: && idi != TME_STP2220_IDI_RESERVED) ! 1018: : (idi != TME_STP2222_IDI_FFB0 ! 1019: && idi != TME_STP2222_IDI_FFB1)) { ! 1020: ! 1021: /* assume that the IDI is also the INO: */ ! 1022: ino = idi; ! 1023: ! 1024: /* if this is an stp2220 obio interrupt: */ ! 1025: if (TME_STP222X_IS_2220(stp222x) ! 1026: && idi >= TME_STP222X_IDI0_OBIO) { ! 1027: ! 1028: /* the stp2220 obio interrupt to INO mapping is not regular: */ ! 1029: switch (idi) { ! 1030: case TME_STP222X_IDI_SCSI: ino = 0x20; break; ! 1031: case TME_STP222X_IDI_ETHER: ino = 0x21; break; ! 1032: case TME_STP222X_IDI_BPP: ino = 0x22; break; ! 1033: case TME_STP2220_IDI_AUDIO: ino = 0x24; break; ! 1034: case TME_STP2220_IDI_POWER: ino = 0x25; break; ! 1035: case TME_STP2220_IDI_ZS0_ZS1: ino = 0x28; break; ! 1036: case TME_STP2220_IDI_FD: ino = 0x29; break; ! 1037: case TME_STP2220_IDI_THERM: ino = 0x2a; break; ! 1038: case TME_STP2220_IDI_KBD: ino = 0x2b; break; ! 1039: case TME_STP2220_IDI_MOUSE: ino = 0x2c; break; ! 1040: case TME_STP2220_IDI_SERIAL: ino = 0x2d; break; ! 1041: case TME_STP2220_IDI_TIMER(0): ino = 0x30; break; ! 1042: case TME_STP2220_IDI_TIMER(1): ino = 0x31; break; ! 1043: case TME_STP2220_IDI_UE: ino = 0x34; break; ! 1044: case TME_STP2220_IDI_CE: ino = 0x35; break; ! 1045: case TME_STP2220_IDI_SBUS_ASYNC: ino = 0x36; break; ! 1046: case TME_STP2220_IDI_POWER_MANAGE: ino = 0x37; break; ! 1047: case TME_STP2220_IDI_UPA: ino = 0x38; break; ! 1048: case TME_STP2220_IDI_RESERVED: ino = 0x39; break; ! 1049: default: break; ! 1050: } ! 1051: } ! 1052: ! 1053: /* update the INR in the IDI's IMR: */ ! 1054: stp222x->tme_stp222x_mdu_imrs[idi] ! 1055: = ((stp222x->tme_stp222x_mdu_imrs[idi] ! 1056: & ~TME_STP222X_MDU_IMR_INR) ! 1057: + (ign * TME_STP222X_IDI_NULL) ! 1058: + ino); ! 1059: } ! 1060: } ! 1061: } ! 1062: ! 1063: /* this initializes the MDU: */ ! 1064: void ! 1065: tme_stp222x_mdu_init(struct tme_stp222x *stp222x) ! 1066: { ! 1067: ! 1068: /* initialize the IMRs: */ ! 1069: memset(stp222x->tme_stp222x_mdu_imrs, 0, sizeof(stp222x->tme_stp222x_mdu_imrs)); ! 1070: tme_stp222x_mdu_ign_update(stp222x, 0); ! 1071: ! 1072: /* initialize the retry timer: */ ! 1073: stp222x->tme_stp222x_mdu_retry = 0; ! 1074: _tme_stp222x_mdu_retry_set(stp222x); ! 1075: ! 1076: /* initialize the retry condition: */ ! 1077: tme_stp22xx_cond_init(&stp222x->tme_stp222x_mdu_retry_cond); ! 1078: ! 1079: /* start the retry thread: */ ! 1080: tme_thread_create(_tme_stp222x_mdu_retry_th, stp222x); ! 1081: } ! 1082:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.