|
|
1.1 ! root 1: /* $Id: sun-sc.c,v 1.3 2003/08/07 21:56:37 fredette Exp $ */ ! 2: ! 3: /* bus/multibus/sun-sc.c - implementation of Sun `sc' SCSI Multibus board emulation: */ ! 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: sun-sc.c,v 1.3 2003/08/07 21:56:37 fredette Exp $"); ! 38: ! 39: /* includes: */ ! 40: #include <tme/generic/bus-device.h> ! 41: #include <tme/generic/scsi.h> ! 42: ! 43: /* macros: */ ! 44: ! 45: /* register offsets and sizes: */ ! 46: #define TME_SUN_SC_REG_DATA (0) ! 47: #define TME_SUN_SC_SIZ_DATA (sizeof(tme_uint8_t)) ! 48: #define TME_SUN_SC_REG_CMD_STAT (2) ! 49: #define TME_SUN_SC_SIZ_CMD_STAT (sizeof(tme_uint8_t)) ! 50: #define TME_SUN_SC_REG_ICR (4) ! 51: #define TME_SUN_SC_SIZ_ICR (sizeof(tme_uint16_t)) ! 52: #define TME_SUN_SC_REG_DMA_H (8) ! 53: #define TME_SUN_SC_SIZ_DMA_H (sizeof(tme_uint16_t)) ! 54: #define TME_SUN_SC_REG_DMA_L (10) ! 55: #define TME_SUN_SC_SIZ_DMA_L (sizeof(tme_uint16_t)) ! 56: #define TME_SUN_SC_REG_DMA_LEN (12) ! 57: #define TME_SUN_SC_SIZ_DMA_LEN (sizeof(tme_uint16_t)) ! 58: #define TME_SUN_SC_REG_INTVEC (15) ! 59: #define TME_SUN_SC_SIZ_INTVEC (sizeof(tme_uint8_t)) ! 60: #define TME_SUN_SC_SIZ_CARD (TME_SUN_SC_REG_INTVEC + TME_SUN_SC_SIZ_INTVEC) ! 61: ! 62: /* the bits in the Interface Control Register. bits greater than ! 63: or equal to SUNSCPAL_ICR_BUSY are read-only: */ ! 64: #define _TME_SUN_SC_ICR_RO_BITS (~(TME_SUN_SC_ICR_BUSY - 1)) ! 65: #define TME_SUN_SC_ICR_PARITY_ERROR (0x8000) /* parity error */ ! 66: #define TME_SUN_SC_ICR_BUS_ERROR (0x4000) /* bus error */ ! 67: #define TME_SUN_SC_ICR_ODD_LENGTH (0x2000) /* odd length */ ! 68: #define TME_SUN_SC_ICR_INT_REQUEST (0x1000) /* interrupt request */ ! 69: #define TME_SUN_SC_ICR_REQUEST (0x0800) /* request */ ! 70: #define TME_SUN_SC_ICR_MESSAGE (0x0400) /* message */ ! 71: #define TME_SUN_SC_ICR_COMMAND_DATA (0x0200) /* 1=command, 0=data */ ! 72: #define TME_SUN_SC_ICR_INPUT_OUTPUT (0x0100) /* 1=input (initiator should read), 0=output */ ! 73: #define TME_SUN_SC_ICR_PARITY (0x0080) /* parity */ ! 74: #define TME_SUN_SC_ICR_BUSY (0x0040) /* busy */ ! 75: #define TME_SUN_SC_ICR_SELECT (0x0020) /* select */ ! 76: #define TME_SUN_SC_ICR_RESET (0x0010) /* reset */ ! 77: #define TME_SUN_SC_ICR_PARITY_ENABLE (0x0008) /* enable parity */ ! 78: #define TME_SUN_SC_ICR_WORD_MODE (0x0004) /* word mode */ ! 79: #define TME_SUN_SC_ICR_DMA_ENABLE (0x0002) /* enable DMA */ ! 80: #define TME_SUN_SC_ICR_INT_ENABLE (0x0001) /* enable interrupts */ ! 81: ! 82: /* this gets the current SCSI information transfer bus phase, ! 83: including BSY, from an ICR value: */ ! 84: #define TME_SUN_SC_BUS_PHASE(icr) \ ! 85: ((icr) \ ! 86: & (TME_SUN_SC_ICR_BUSY \ ! 87: | TME_SUN_SC_ICR_MESSAGE \ ! 88: | TME_SUN_SC_ICR_COMMAND_DATA \ ! 89: | TME_SUN_SC_ICR_INPUT_OUTPUT)) ! 90: ! 91: /* these get and put a 16-bit register: */ ! 92: #define TME_SUN_SC_REG16_GET(sun_sc, reg) \ ! 93: tme_betoh_u16(*((tme_uint16_t *) &(sun_sc)->tme_sun_sc_card[reg])) ! 94: #define TME_SUN_SC_REG16_PUT(sun_sc, reg, val) \ ! 95: (*((tme_uint16_t *) &(sun_sc)->tme_sun_sc_card[reg]) = tme_htobe_u16(val)) ! 96: ! 97: /* these get and put the ICR: */ ! 98: #define TME_SUN_SC_ICR_GET(sun_sc) \ ! 99: TME_SUN_SC_REG16_GET(sun_sc, TME_SUN_SC_REG_ICR) ! 100: #define TME_SUN_SC_ICR_PUT(sun_sc, icr) \ ! 101: TME_SUN_SC_REG16_PUT(sun_sc, TME_SUN_SC_REG_ICR, icr) ! 102: ! 103: /* the size of the cycle callout ring buffer: */ ! 104: #define TME_SUN_SC_CYCLE_RING_SIZE (4) ! 105: ! 106: /* the callout flags: */ ! 107: #define TME_SUN_SC_CALLOUT_CHECK (0) ! 108: #define TME_SUN_SC_CALLOUT_RUNNING TME_BIT(0) ! 109: #define TME_SUN_SC_CALLOUTS_MASK (-2) ! 110: #define TME_SUN_SC_CALLOUT_CYCLE TME_BIT(1) ! 111: #define TME_SUN_SC_CALLOUT_TLB_FILL TME_BIT(2) ! 112: #define TME_SUN_SC_CALLOUT_INT TME_BIT(3) ! 113: ! 114: #if 1 ! 115: #define TME_SUN_SC_DEBUG ! 116: #endif ! 117: ! 118: /* structures: */ ! 119: ! 120: /* an entry in the cycle callout ring buffer: */ ! 121: struct tme_sun_sc_cycle { ! 122: ! 123: /* the SCSI control and data signals to assert: */ ! 124: tme_scsi_control_t tme_sun_sc_cycle_control; ! 125: tme_scsi_data_t tme_sun_sc_cycle_data; ! 126: ! 127: /* the SCSI sequence to run: */ ! 128: const struct tme_scsi_sequence *tme_sun_sc_cycle_sequence; ! 129: ! 130: /* a DMA structure needed: */ ! 131: struct tme_scsi_dma tme_sun_sc_cycle_dma; ! 132: ! 133: /* for the cmd_stat DMA, the cmd_stat value: */ ! 134: tme_uint8_t tme_sun_sc_cycle_cmd_stat; ! 135: }; ! 136: ! 137: /* the card: */ ! 138: struct tme_sun_sc { ! 139: ! 140: /* our simple bus device header: */ ! 141: struct tme_bus_device tme_sun_sc_device; ! 142: #define tme_sun_sc_element tme_sun_sc_device.tme_bus_device_element ! 143: ! 144: /* the mutex protecting the card: */ ! 145: tme_mutex_t tme_sun_sc_mutex; ! 146: ! 147: /* the rwlock protecting the card: */ ! 148: tme_rwlock_t tme_sun_sc_rwlock; ! 149: ! 150: /* the SCSI bus connection: */ ! 151: struct tme_scsi_connection *tme_sun_sc_scsi_connection; ! 152: ! 153: /* the callout flags: */ ! 154: int tme_sun_sc_callout_flags; ! 155: ! 156: /* if our interrupt line is currently asserted: */ ! 157: int tme_sun_sc_int_asserted; ! 158: ! 159: /* it's easiest to just model the card as a chunk of memory: */ ! 160: tme_uint8_t tme_sun_sc_card[TME_SUN_SC_SIZ_CARD]; ! 161: ! 162: /* the SCSI sequences: */ ! 163: const struct tme_scsi_sequence *tme_sun_sc_sequence_info_dma_initiator; ! 164: const struct tme_scsi_sequence *tme_sun_sc_sequence_wait_change; ! 165: ! 166: /* the cycle ring buffer: */ ! 167: struct tme_sun_sc_cycle tme_sun_sc_cycles[TME_SUN_SC_CYCLE_RING_SIZE]; ! 168: int tme_sun_sc_cycle_head; ! 169: int tme_sun_sc_cycle_tail; ! 170: ! 171: /* our DMA TLB set: */ ! 172: TME_ATOMIC(struct tme_bus_tlb *, tme_sun_sc_dma_tlb); ! 173: ! 174: /* the internal DMA buffer: */ ! 175: tme_uint8_t tme_sun_sc_int_dma[2]; ! 176: ! 177: #ifndef TME_NO_LOG ! 178: tme_uint16_t tme_sun_sc_last_log_icr; ! 179: #endif /* !TME_NO_LOG */ ! 180: }; ! 181: ! 182: /* globals: */ ! 183: ! 184: /* the Sun sc bus router: */ ! 185: static const tme_bus_lane_t tme_sun_sc_router[TME_BUS_ROUTER_SIZE(TME_BUS16_LOG2) * 2] = { ! 186: ! 187: /* [sc] initiator cycle size: 8 bits ! 188: [gen] responding port size: 8 bits ! 189: [gen] responding port least lane: 0: */ ! 190: /* D7-D0 */ TME_BUS_LANE_ROUTE(0), ! 191: /* D15-D8 */ TME_BUS_LANE_UNDEF, ! 192: ! 193: /* [sc] initiator cycle size: 8 bits ! 194: [gen] responding port size: 8 bits ! 195: [gen] responding port least lane: 1: */ ! 196: /* D7-D0 */ TME_BUS_LANE_ROUTE(0), ! 197: /* D15-D8 */ TME_BUS_LANE_UNDEF | TME_BUS_LANE_WARN, ! 198: ! 199: /* [sc] initiator cycle size: 8 bits ! 200: [gen] responding port size: 16 bits ! 201: [gen] responding port least lane: 0: */ ! 202: /* D7-D0 */ TME_BUS_LANE_ROUTE(0), ! 203: /* D15-D8 */ TME_BUS_LANE_UNDEF | TME_BUS_LANE_WARN, ! 204: ! 205: /* [sc] initiator cycle size: 8 bits ! 206: [gen] responding port size: 16 bits ! 207: [gen] responding port least lane: 1 - invalid, array placeholder: */ ! 208: /* D7-D0 */ TME_BUS_LANE_ABORT, ! 209: /* D15-D8 */ TME_BUS_LANE_ABORT, ! 210: ! 211: /* [sc] initiator cycle size: 16 bits ! 212: [gen] responding port size: 8 bits ! 213: [gen] responding port least lane: 0: */ ! 214: /* D7-D0 */ TME_BUS_LANE_ROUTE(0), ! 215: /* D15-D8 */ TME_BUS_LANE_ROUTE(1) | TME_BUS_LANE_WARN, ! 216: ! 217: /* [sc] initiator cycle size: 16 bits ! 218: [gen] responding port size: 8 bits ! 219: [gen] responding port least lane: 1: */ ! 220: /* D7-D0 */ TME_BUS_LANE_ROUTE(0) | TME_BUS_LANE_WARN, ! 221: /* D15-D8 */ TME_BUS_LANE_ROUTE(1) | TME_BUS_LANE_WARN, ! 222: ! 223: /* [sc] initiator cycle size: 16 bits ! 224: [gen] responding port size: 16 bits ! 225: [gen] responding port least lane: 0: */ ! 226: /* D7-D0 */ TME_BUS_LANE_ROUTE(0), ! 227: /* D15-D8 */ TME_BUS_LANE_ROUTE(1), ! 228: ! 229: /* [sc] initiator cycle size: 16 bits ! 230: [gen] responding port size: 16 bits ! 231: [gen] responding port least lane: 1 - invalid, array placeholder: */ ! 232: /* D7-D0 */ TME_BUS_LANE_ABORT, ! 233: /* D15-D8 */ TME_BUS_LANE_ABORT, ! 234: }; ! 235: ! 236: #ifdef TME_SUN_SC_DEBUG ! 237: void ! 238: _tme_sun_sc_reg16_put(struct tme_sun_sc *sun_sc, ! 239: int reg, ! 240: tme_uint16_t val_new) ! 241: { ! 242: const char *reg_name; ! 243: tme_uint16_t val_old; ! 244: ! 245: val_old = TME_SUN_SC_REG16_GET(sun_sc, reg); ! 246: if (val_old == val_new) { ! 247: return; ! 248: } ! 249: TME_SUN_SC_REG16_PUT(sun_sc, reg, val_new); ! 250: ! 251: switch (reg) { ! 252: case TME_SUN_SC_REG_ICR: ! 253: reg_name = "icr"; ! 254: break; ! 255: case TME_SUN_SC_REG_DMA_H: ! 256: case TME_SUN_SC_REG_DMA_L: ! 257: tme_log(&sun_sc->tme_sun_sc_element->tme_element_log_handle, ! 258: 100, TME_OK, ! 259: (&sun_sc->tme_sun_sc_element->tme_element_log_handle, ! 260: "dvma now 0x%04x%04x (len 0x%04x)", ! 261: TME_SUN_SC_REG16_GET(sun_sc, ! 262: TME_SUN_SC_REG_DMA_H), ! 263: TME_SUN_SC_REG16_GET(sun_sc, ! 264: TME_SUN_SC_REG_DMA_L), ! 265: (TME_SUN_SC_REG16_GET(sun_sc, ! 266: TME_SUN_SC_REG_DMA_LEN) ! 267: ^ 0xffff))); ! 268: return; ! 269: case TME_SUN_SC_REG_DMA_LEN: ! 270: reg_name = "len"; ! 271: val_new ^= 0xffff; ! 272: break; ! 273: default: ! 274: reg_name = "???"; ! 275: break; ! 276: } ! 277: tme_log(&sun_sc->tme_sun_sc_element->tme_element_log_handle, ! 278: 100, TME_OK, ! 279: (&sun_sc->tme_sun_sc_element->tme_element_log_handle, ! 280: "%s now 0x%04x", ! 281: reg_name, ! 282: val_new)); ! 283: } ! 284: #undef TME_SUN_SC_REG16_PUT ! 285: #define TME_SUN_SC_REG16_PUT _tme_sun_sc_reg16_put ! 286: #endif /* TME_SUN_SC_DEBUG */ ! 287: ! 288: /* this allocates the next cycle in the ring buffer: */ ! 289: struct tme_sun_sc_cycle * ! 290: _tme_sun_sc_cycle_new(struct tme_sun_sc *sun_sc, ! 291: const struct tme_scsi_sequence *sequence) ! 292: { ! 293: int old_head; ! 294: struct tme_sun_sc_cycle *sun_sc_cycle; ! 295: const struct tme_sun_sc_cycle *sun_sc_cycle_old; ! 296: ! 297: /* abort if the ring buffer overflows: */ ! 298: old_head = sun_sc->tme_sun_sc_cycle_head; ! 299: sun_sc->tme_sun_sc_cycle_head ! 300: = ((old_head ! 301: + 1) ! 302: & (TME_SUN_SC_CYCLE_RING_SIZE ! 303: - 1)); ! 304: if ((sun_sc->tme_sun_sc_cycle_head ! 305: == sun_sc->tme_sun_sc_cycle_tail) ! 306: && (sun_sc->tme_sun_sc_scsi_connection ! 307: != NULL)) { ! 308: abort(); ! 309: } ! 310: ! 311: /* initialize and return the cycle. we copy the previous cycle's ! 312: control signals, (and data signals too, unless the caller wants ! 313: the DMA sequence), so that callers only have to change the values ! 314: that they know are changing: */ ! 315: sun_sc_cycle ! 316: = &sun_sc->tme_sun_sc_cycles[old_head]; ! 317: memset(sun_sc_cycle, 0, sizeof(*sun_sc_cycle)); ! 318: sun_sc_cycle_old ! 319: = &sun_sc->tme_sun_sc_cycles[((old_head ! 320: - 1) ! 321: & (TME_SUN_SC_CYCLE_RING_SIZE ! 322: - 1))]; ! 323: sun_sc_cycle->tme_sun_sc_cycle_control ! 324: = sun_sc_cycle_old->tme_sun_sc_cycle_control; ! 325: sun_sc_cycle->tme_sun_sc_cycle_data ! 326: = ((sequence ! 327: == sun_sc->tme_sun_sc_sequence_info_dma_initiator) ! 328: ? 0 ! 329: : sun_sc_cycle_old->tme_sun_sc_cycle_data); ! 330: sun_sc_cycle->tme_sun_sc_cycle_sequence ! 331: = sequence; ! 332: /* XXX parity? */ ! 333: sun_sc_cycle->tme_sun_sc_cycle_dma.tme_scsi_dma_flags ! 334: = TME_SCSI_DMA_8BIT; ! 335: return (sun_sc_cycle); ! 336: } ! 337: ! 338: /* this does a bus cycle to read or write into our internal DMA ! 339: buffer: */ ! 340: static int ! 341: _tme_sun_sc_bus_cycle_dma(struct tme_sun_sc *sun_sc, ! 342: struct tme_bus_tlb *tlb, ! 343: tme_uint8_t cycle_type, ! 344: tme_bus_addr_t address, ! 345: int word_mode) ! 346: { ! 347: struct tme_bus_cycle cycle_init; ! 348: int rc; ! 349: ! 350: /* use our internal DMA buffer: */ ! 351: cycle_init.tme_bus_cycle_buffer ! 352: = &sun_sc->tme_sun_sc_int_dma[0]; ! 353: ! 354: /* if we're in word mode, use the 16-bit bus router ! 355: and a 16-bit cycle size: */ ! 356: if (word_mode) { ! 357: cycle_init.tme_bus_cycle_lane_routing ! 358: = &tme_sun_sc_router[TME_BUS_ROUTER_SIZE(TME_BUS16_LOG2)]; ! 359: cycle_init.tme_bus_cycle_size ! 360: = sizeof(tme_uint16_t); ! 361: } ! 362: ! 363: /* otherwise, use the 8-bit bus router and an 8-bit ! 364: cycle size: */ ! 365: else { ! 366: cycle_init.tme_bus_cycle_lane_routing ! 367: = &tme_sun_sc_router[0]; ! 368: cycle_init.tme_bus_cycle_size ! 369: = sizeof(tme_uint16_t); ! 370: } ! 371: ! 372: assert (tlb->tme_bus_tlb_addr_shift == 0); ! 373: cycle_init.tme_bus_cycle_address ! 374: = (address ! 375: + tlb->tme_bus_tlb_addr_offset); ! 376: ! 377: cycle_init.tme_bus_cycle_buffer_increment ! 378: = 1; ! 379: ! 380: cycle_init.tme_bus_cycle_type ! 381: = cycle_type; ! 382: ! 383: cycle_init.tme_bus_cycle_port = ! 384: TME_BUS_CYCLE_PORT(0, TME_BUS16_LOG2); ! 385: ! 386: /* unlock the mutex: */ ! 387: tme_mutex_unlock(&sun_sc->tme_sun_sc_mutex); ! 388: ! 389: /* run the bus cycle: */ ! 390: rc = ((*tlb->tme_bus_tlb_cycle) ! 391: (tlb->tme_bus_tlb_cycle_private, ! 392: &cycle_init)); ! 393: ! 394: /* lock the mutex: */ ! 395: tme_mutex_lock(&sun_sc->tme_sun_sc_mutex); ! 396: ! 397: return (rc); ! 398: } ! 399: ! 400: /* the Sun sc callout function. it must be called with the mutex locked: */ ! 401: static void ! 402: _tme_sun_sc_callout(struct tme_sun_sc *sun_sc, int new_callouts) ! 403: { ! 404: struct tme_scsi_connection *conn_scsi; ! 405: struct tme_bus_connection *conn_bus; ! 406: struct tme_bus_tlb *tlb; ! 407: int old_tail; ! 408: struct tme_sun_sc_cycle *sun_sc_cycle; ! 409: int callouts, later_callouts; ! 410: tme_bus_addr_t address; ! 411: tme_uint16_t resid; ! 412: tme_uint8_t cycle_type; ! 413: tme_bus_addr_t avail; ! 414: tme_uint8_t *emulator_off; ! 415: tme_uint16_t icr; ! 416: int rc; ! 417: int int_asserted; ! 418: ! 419: /* add in any new callouts: */ ! 420: sun_sc->tme_sun_sc_callout_flags |= new_callouts; ! 421: ! 422: /* if this function is already running in another thread, simply ! 423: return now. the other thread will do our work: */ ! 424: if (sun_sc->tme_sun_sc_callout_flags ! 425: & TME_SUN_SC_CALLOUT_RUNNING) { ! 426: return; ! 427: } ! 428: ! 429: /* callouts are now running: */ ! 430: sun_sc->tme_sun_sc_callout_flags ! 431: |= TME_SUN_SC_CALLOUT_RUNNING; ! 432: ! 433: /* assume that we won't need any later callouts: */ ! 434: later_callouts = 0; ! 435: ! 436: /* loop while callouts are needed: */ ! 437: for (; ((callouts ! 438: = sun_sc->tme_sun_sc_callout_flags) ! 439: & TME_SUN_SC_CALLOUTS_MASK); ) { ! 440: ! 441: /* clear the needed callouts: */ ! 442: sun_sc->tme_sun_sc_callout_flags ! 443: = (callouts ! 444: & ~TME_SUN_SC_CALLOUTS_MASK); ! 445: callouts ! 446: &= TME_SUN_SC_CALLOUTS_MASK; ! 447: ! 448: /* get this card's bus and SCSI connections: */ ! 449: conn_scsi = sun_sc->tme_sun_sc_scsi_connection; ! 450: conn_bus = TME_ATOMIC_READ(struct tme_bus_connection *, ! 451: sun_sc->tme_sun_sc_device.tme_bus_device_connection); ! 452: ! 453: /* if we need to call out a SCSI bus cycle: */ ! 454: if (callouts & TME_SUN_SC_CALLOUT_CYCLE) { ! 455: ! 456: /* there must be a cycle to call out: */ ! 457: old_tail = sun_sc->tme_sun_sc_cycle_tail; ! 458: assert (old_tail ! 459: != sun_sc->tme_sun_sc_cycle_head); ! 460: sun_sc_cycle ! 461: = &sun_sc->tme_sun_sc_cycles[old_tail]; ! 462: ! 463: /* unlock the mutex: */ ! 464: tme_mutex_unlock(&sun_sc->tme_sun_sc_mutex); ! 465: ! 466: /* do the callout: */ ! 467: rc = (conn_scsi != NULL ! 468: ? ((*conn_scsi->tme_scsi_connection_cycle) ! 469: (conn_scsi, ! 470: sun_sc_cycle->tme_sun_sc_cycle_control, ! 471: sun_sc_cycle->tme_sun_sc_cycle_data, ! 472: sun_sc_cycle->tme_sun_sc_cycle_sequence, ! 473: ((sun_sc_cycle->tme_sun_sc_cycle_sequence ! 474: == sun_sc->tme_sun_sc_sequence_info_dma_initiator) ! 475: ? &sun_sc_cycle->tme_sun_sc_cycle_dma ! 476: : NULL))) ! 477: : TME_OK); ! 478: ! 479: /* lock the mutex: */ ! 480: tme_mutex_lock(&sun_sc->tme_sun_sc_mutex); ! 481: ! 482: /* if the callout was unsuccessful, remember that at some later ! 483: time this callout should be attempted again: */ ! 484: if (rc != TME_OK) { ! 485: later_callouts |= TME_SUN_SC_CALLOUT_CYCLE; ! 486: } ! 487: ! 488: /* otherwise, this callout was successful. if this cycle did ! 489: not use the DMA initiator sequence, it either used no ! 490: sequence or it used the wait_change sequence: */ ! 491: else if (sun_sc_cycle->tme_sun_sc_cycle_sequence ! 492: != sun_sc->tme_sun_sc_sequence_info_dma_initiator) { ! 493: ! 494: /* advance the tail pointer if it hasn't been advanced ! 495: already: */ ! 496: if (sun_sc->tme_sun_sc_cycle_tail ! 497: == old_tail) { ! 498: sun_sc->tme_sun_sc_cycle_tail ! 499: = ((sun_sc->tme_sun_sc_cycle_tail ! 500: + 1) ! 501: & (TME_SUN_SC_CYCLE_RING_SIZE ! 502: - 1)); ! 503: } ! 504: ! 505: /* if there are more cycles to run, run them now: */ ! 506: if (sun_sc->tme_sun_sc_cycle_tail ! 507: != sun_sc->tme_sun_sc_cycle_head) { ! 508: sun_sc->tme_sun_sc_callout_flags ! 509: |= TME_SUN_SC_CALLOUT_CYCLE; ! 510: } ! 511: } ! 512: } ! 513: ! 514: /* if we need to call out a TLB fill: */ ! 515: if (callouts & TME_SUN_SC_CALLOUT_TLB_FILL) { ! 516: ! 517: /* get the current ICR value: */ ! 518: icr = TME_SUN_SC_ICR_GET(sun_sc); ! 519: ! 520: /* get the DMA address: */ ! 521: address ! 522: = TME_SUN_SC_REG16_GET(sun_sc, ! 523: TME_SUN_SC_REG_DMA_H); ! 524: address ! 525: = ((address ! 526: << 16) ! 527: | TME_SUN_SC_REG16_GET(sun_sc, ! 528: TME_SUN_SC_REG_DMA_L)); ! 529: ! 530: /* get the cycle type: */ ! 531: cycle_type ! 532: = ((icr ! 533: & TME_SUN_SC_ICR_INPUT_OUTPUT) ! 534: ? TME_BUS_CYCLE_WRITE ! 535: : TME_BUS_CYCLE_READ); ! 536: ! 537: /* get the resid: */ ! 538: resid ! 539: = (TME_SUN_SC_REG16_GET(sun_sc, ! 540: TME_SUN_SC_REG_DMA_LEN) ! 541: ^ 0xffff); ! 542: assert (resid ! 543: >= ((icr ! 544: & TME_SUN_SC_ICR_WORD_MODE) ! 545: ? sizeof(tme_uint16_t) ! 546: : sizeof(tme_uint8_t))); ! 547: ! 548: /* get the TLB entry: */ ! 549: tlb ! 550: = TME_ATOMIC_READ(struct tme_bus_tlb *, ! 551: sun_sc->tme_sun_sc_dma_tlb); ! 552: ! 553: /* unlock the mutex: */ ! 554: tme_mutex_unlock(&sun_sc->tme_sun_sc_mutex); ! 555: ! 556: /* do the callout: */ ! 557: rc = (conn_bus != NULL ! 558: ? ((*conn_bus->tme_bus_tlb_fill) ! 559: (conn_bus, ! 560: tlb, ! 561: address, ! 562: cycle_type)) ! 563: : TME_OK); ! 564: ! 565: /* lock the mutex: */ ! 566: tme_mutex_lock(&sun_sc->tme_sun_sc_mutex); ! 567: ! 568: /* if the callout was unsuccessful, remember that at some later ! 569: time this callout should be attempted again: */ ! 570: if (rc != TME_OK) { ! 571: later_callouts |= TME_SUN_SC_CALLOUT_TLB_FILL; ! 572: } ! 573: ! 574: /* otherwise, use the filled TLB entry to start a SCSI ! 575: DMA sequence: */ ! 576: else { ! 577: ! 578: /* get the number of bytes available in this TLB entry: */ ! 579: avail ! 580: = ((TME_ATOMIC_READ(tme_bus_addr_t, ! 581: tlb->tme_bus_tlb_addr_last) ! 582: - address) ! 583: + 1); ! 584: if (avail == 0 ! 585: || avail > resid) { ! 586: avail = resid; ! 587: } ! 588: assert (avail ! 589: >= ((icr ! 590: & TME_SUN_SC_ICR_WORD_MODE) ! 591: ? sizeof(tme_uint16_t) ! 592: : sizeof(tme_uint8_t))); ! 593: ! 594: /* allocate the new SCSI bus cycle: */ ! 595: sun_sc_cycle ! 596: = _tme_sun_sc_cycle_new(sun_sc, ! 597: sun_sc->tme_sun_sc_sequence_info_dma_initiator); ! 598: ! 599: /* if this TLB entry allows fast transfers: */ ! 600: emulator_off ! 601: = ((cycle_type ! 602: == TME_BUS_CYCLE_READ) ! 603: ? tlb->tme_bus_tlb_emulator_off_read ! 604: : tlb->tme_bus_tlb_emulator_off_write); ! 605: if (emulator_off ! 606: != TME_EMULATOR_OFF_UNDEF) { ! 607: ! 608: /* do the SCSI DMA sequence with the TLB fast transfer ! 609: buffer: */ ! 610: sun_sc_cycle->tme_sun_sc_cycle_dma.tme_scsi_dma_in ! 611: = emulator_off + address; ! 612: } ! 613: ! 614: /* otherwise, this TLB entry does not allow fast transfers: */ ! 615: else { ! 616: ! 617: /* if this we need to read from this TLB, do a memory ! 618: read cycle into our internal DMA buffer: */ ! 619: if (cycle_type == TME_BUS_CYCLE_READ) { ! 620: rc = _tme_sun_sc_bus_cycle_dma(sun_sc, ! 621: tlb, ! 622: TME_BUS_CYCLE_READ, ! 623: address, ! 624: (icr ! 625: & TME_SUN_SC_ICR_WORD_MODE)); ! 626: assert (rc == TME_OK); ! 627: } ! 628: ! 629: /* do the SCSI DMA sequence with our internal DMA buffer: */ ! 630: sun_sc_cycle->tme_sun_sc_cycle_dma.tme_scsi_dma_in ! 631: = emulator_off + address; ! 632: avail ! 633: = ((icr ! 634: & TME_SUN_SC_ICR_WORD_MODE) ! 635: ? sizeof(tme_uint16_t) ! 636: : sizeof(tme_uint8_t)); ! 637: } ! 638: ! 639: /* finish the SCSI cycle: */ ! 640: sun_sc_cycle->tme_sun_sc_cycle_dma.tme_scsi_dma_out ! 641: = sun_sc_cycle->tme_sun_sc_cycle_dma.tme_scsi_dma_in; ! 642: sun_sc_cycle->tme_sun_sc_cycle_dma.tme_scsi_dma_resid ! 643: = avail; ! 644: ! 645: /* we now need to call out a SCSI cycle: */ ! 646: sun_sc->tme_sun_sc_callout_flags ! 647: |= TME_SUN_SC_CALLOUT_CYCLE; ! 648: } ! 649: } ! 650: ! 651: /* if we need to call out a possible change to our interrupt ! 652: signal: */ ! 653: if (callouts & TME_SUN_SC_CALLOUT_INT) { ! 654: ! 655: /* get the current ICR value: */ ! 656: icr = TME_SUN_SC_ICR_GET(sun_sc); ! 657: ! 658: /* see if the interrupt signal should be asserted or negated: */ ! 659: int_asserted = ((icr ! 660: & TME_SUN_SC_ICR_INT_REQUEST) ! 661: && (icr ! 662: & TME_SUN_SC_ICR_INT_ENABLE)); ! 663: ! 664: /* if the interrupt signal doesn't already have the right state: */ ! 665: if (!int_asserted ! 666: != !sun_sc->tme_sun_sc_int_asserted) { ! 667: ! 668: /* unlock our mutex: */ ! 669: tme_mutex_unlock(&sun_sc->tme_sun_sc_mutex); ! 670: ! 671: /* call out the bus interrupt signal edge: */ ! 672: rc = (*conn_bus->tme_bus_signal) ! 673: (conn_bus, ! 674: TME_BUS_SIGNAL_INT_UNSPEC ! 675: | (int_asserted ! 676: ? TME_BUS_SIGNAL_LEVEL_ASSERTED ! 677: : TME_BUS_SIGNAL_LEVEL_NEGATED) ! 678: | TME_BUS_SIGNAL_EDGE); ! 679: ! 680: /* lock our mutex: */ ! 681: tme_mutex_lock(&sun_sc->tme_sun_sc_mutex); ! 682: ! 683: /* if this callout was successful, note the new state of the ! 684: interrupt signal: */ ! 685: if (rc == TME_OK) { ! 686: sun_sc->tme_sun_sc_int_asserted = int_asserted; ! 687: } ! 688: ! 689: /* otherwise, remember that at some later time this callout ! 690: should be attempted again: */ ! 691: else { ! 692: later_callouts |= TME_SUN_SC_CALLOUT_INT; ! 693: } ! 694: } ! 695: } ! 696: } ! 697: ! 698: /* put in any later callouts, and clear that callouts are running: */ ! 699: sun_sc->tme_sun_sc_callout_flags = later_callouts; ! 700: } ! 701: ! 702: /* the Sun sc bus cycle handler for the data and cmd_stat registers. ! 703: these registers are connected directly to the SCSI data signals. ! 704: ! 705: a read of one of these registers samples the SCSI data bus, and a ! 706: write to one of these registers changes the SCSI data bus signals ! 707: asserted by the card. ! 708: ! 709: additionally, depending on context, a read or write of one of these ! 710: registers will cause the card to execute the initiator's side of a ! 711: REQ/ACK handshake to transfer a byte. ! 712: ! 713: a read or write of the cmd_stat register always causes the ! 714: handshake. a read or write of the data register when the SCSI bus ! 715: is in the DATA IN or DATA OUT phase with REQ asserted also causes ! 716: the handshake: */ ! 717: static int ! 718: _tme_sun_sc_bus_cycle_data_reg(struct tme_sun_sc *sun_sc, ! 719: struct tme_bus_cycle *cycle_init, ! 720: int is_cmd_stat) ! 721: { ! 722: tme_uint16_t icr; ! 723: tme_scsi_data_t data_old, data_new; ! 724: struct tme_sun_sc_cycle *sun_sc_cycle; ! 725: int new_callouts; ! 726: ! 727: /* assume we won't need any new callouts: */ ! 728: new_callouts = 0; ! 729: ! 730: /* lock the mutex: */ ! 731: tme_mutex_lock(&sun_sc->tme_sun_sc_mutex); ! 732: ! 733: /* get the current ICR value: */ ! 734: icr = TME_SUN_SC_ICR_GET(sun_sc); ! 735: ! 736: /* save the old data register (really, the current ! 737: signals asserted on the data bus), and, in case ! 738: this is a read of the cmd_stat register, save ! 739: it in that register: */ ! 740: data_old = sun_sc->tme_sun_sc_card[TME_SUN_SC_REG_DATA]; ! 741: sun_sc->tme_sun_sc_card[TME_SUN_SC_REG_CMD_STAT] = data_old; ! 742: ! 743: /* run the cycle: */ ! 744: tme_bus_cycle_xfer_memory(cycle_init, ! 745: sun_sc->tme_sun_sc_card, ! 746: sun_sc->tme_sun_sc_device.tme_bus_device_address_last); ! 747: ! 748: /* put back the old data register, but get any value that ! 749: may have been written: */ ! 750: data_new ! 751: = (is_cmd_stat ! 752: ? sun_sc->tme_sun_sc_card[TME_SUN_SC_REG_CMD_STAT] ! 753: : sun_sc->tme_sun_sc_card[TME_SUN_SC_REG_DATA]); ! 754: sun_sc->tme_sun_sc_card[TME_SUN_SC_REG_DATA] = data_old; ! 755: ! 756: /* if this was a read or write of the cmd_stat register, or a read ! 757: or write of the data register while the bus is in the DATA IN or ! 758: DATA OUT phase with REQ asserted, do the initiator's side of the ! 759: REQ/ACK handshake: */ ! 760: if (is_cmd_stat ! 761: || ((icr ! 762: & (TME_SUN_SC_ICR_BUSY ! 763: | TME_SUN_SC_ICR_MESSAGE ! 764: | TME_SUN_SC_ICR_COMMAND_DATA ! 765: | TME_SUN_SC_ICR_REQUEST)) ! 766: == (TME_SUN_SC_ICR_BUSY ! 767: | TME_SUN_SC_ICR_REQUEST))) { ! 768: ! 769: /* make a new SCSI bus cycle: */ ! 770: /* XXX parity? */ ! 771: sun_sc_cycle ! 772: = _tme_sun_sc_cycle_new(sun_sc, ! 773: sun_sc->tme_sun_sc_sequence_info_dma_initiator); ! 774: sun_sc_cycle->tme_sun_sc_cycle_dma.tme_scsi_dma_resid ! 775: = sizeof(sun_sc_cycle->tme_sun_sc_cycle_cmd_stat); ! 776: sun_sc_cycle->tme_sun_sc_cycle_dma.tme_scsi_dma_in ! 777: = &sun_sc_cycle->tme_sun_sc_cycle_cmd_stat; ! 778: sun_sc_cycle->tme_sun_sc_cycle_dma.tme_scsi_dma_out ! 779: = &sun_sc_cycle->tme_sun_sc_cycle_cmd_stat; ! 780: sun_sc_cycle->tme_sun_sc_cycle_cmd_stat ! 781: = data_new; ! 782: ! 783: tme_log(&sun_sc->tme_sun_sc_element->tme_element_log_handle, ! 784: 100, TME_OK, ! 785: (&sun_sc->tme_sun_sc_element->tme_element_log_handle, ! 786: ((cycle_init->tme_bus_cycle_type ! 787: == TME_BUS_CYCLE_WRITE) ! 788: ? (is_cmd_stat ! 789: ? "0x%02x -> cmd_stat" ! 790: : "0x%02x -> data (handshake)") ! 791: : (is_cmd_stat ! 792: ? "cmd_stat-> 0x%02x" ! 793: : "data -> 0x%02x (handshake)")), ! 794: sun_sc_cycle->tme_sun_sc_cycle_cmd_stat)); ! 795: ! 796: new_callouts |= TME_SUN_SC_CALLOUT_CYCLE; ! 797: ! 798: /* since this SCSI DMA sequence won't be run right away, it's ! 799: important that we clear REQ now - otherwise if the sc device ! 800: driver happens to see REQ still set, it will think that the SCSI ! 801: handshake *did* happen, and that this REQ is now requesting the ! 802: next byte. when the DMA sequence ends we'll get a cycle call ! 803: that will bring us up-to-date: */ ! 804: TME_SUN_SC_ICR_PUT(sun_sc, ! 805: (icr ! 806: & ~TME_SUN_SC_ICR_REQUEST)); ! 807: } ! 808: ! 809: /* otherwise, if this was a write of the data register in a ! 810: non-handshake bus phase: */ ! 811: else if (cycle_init->tme_bus_cycle_type ! 812: == TME_BUS_CYCLE_WRITE) { ! 813: ! 814: /* if the data signals that we are asserting have changed, call ! 815: out a cycle, then wait: */ ! 816: sun_sc_cycle ! 817: = &sun_sc->tme_sun_sc_cycles[((sun_sc->tme_sun_sc_cycle_head ! 818: - 1) ! 819: & (TME_SUN_SC_CYCLE_RING_SIZE ! 820: - 1))]; ! 821: if (data_new != sun_sc_cycle->tme_sun_sc_cycle_data) { ! 822: tme_log(&sun_sc->tme_sun_sc_element->tme_element_log_handle, ! 823: 100, TME_OK, ! 824: (&sun_sc->tme_sun_sc_element->tme_element_log_handle, ! 825: "0x%02x -> data (no handshake)", ! 826: data_new)); ! 827: sun_sc_cycle ! 828: = _tme_sun_sc_cycle_new(sun_sc, ! 829: sun_sc->tme_sun_sc_sequence_wait_change); ! 830: sun_sc_cycle->tme_sun_sc_cycle_data ! 831: = data_new; ! 832: new_callouts ! 833: |= TME_SUN_SC_CALLOUT_CYCLE; ! 834: } ! 835: } ! 836: ! 837: /* otherwise, this was a read of the data register in a ! 838: non-handshake bus phase: */ ! 839: else { ! 840: tme_log(&sun_sc->tme_sun_sc_element->tme_element_log_handle, ! 841: 100, TME_OK, ! 842: (&sun_sc->tme_sun_sc_element->tme_element_log_handle, ! 843: "data -> 0x%02x (no handshake)", ! 844: data_old)); ! 845: } ! 846: ! 847: /* make any new callouts: */ ! 848: _tme_sun_sc_callout(sun_sc, new_callouts); ! 849: ! 850: /* unlock the mutex: */ ! 851: tme_mutex_unlock(&sun_sc->tme_sun_sc_mutex); ! 852: ! 853: /* no faults: */ ! 854: return (TME_OK); ! 855: } ! 856: ! 857: /* the Sun sc bus cycle handler for the data register. this register ! 858: is connected directly to the SCSI data signals: */ ! 859: static int ! 860: _tme_sun_sc_bus_cycle_data(void *_sun_sc, ! 861: struct tme_bus_cycle *cycle_init) ! 862: { ! 863: return (_tme_sun_sc_bus_cycle_data_reg((struct tme_sun_sc *) _sun_sc, ! 864: cycle_init, ! 865: FALSE)); ! 866: } ! 867: ! 868: /* the Sun sc bus cycle handler for the command/status register. this ! 869: register is also connected directly to the SCSI data signals, but ! 870: reading or writing it additionally causes the card to execute the ! 871: initiator's side of a REQ/ACK handshake to transfer a byte: */ ! 872: static int ! 873: _tme_sun_sc_bus_cycle_cmd_stat(void *_sun_sc, ! 874: struct tme_bus_cycle *cycle_init) ! 875: { ! 876: return (_tme_sun_sc_bus_cycle_data_reg((struct tme_sun_sc *) _sun_sc, ! 877: cycle_init, ! 878: TRUE)); ! 879: } ! 880: ! 881: /* this tries to start or continue a DMA transfer: */ ! 882: static int ! 883: _tme_sun_sc_dma_start(struct tme_sun_sc *sun_sc, ! 884: tme_uint16_t *_icr) ! 885: { ! 886: tme_uint16_t icr; ! 887: tme_uint16_t resid; ! 888: ! 889: /* get the current ICR value: */ ! 890: icr = *_icr; ! 891: ! 892: /* get the resid: */ ! 893: resid ! 894: = (TME_SUN_SC_REG16_GET(sun_sc, ! 895: TME_SUN_SC_REG_DMA_LEN) ! 896: ^ 0xffff); ! 897: ! 898: tme_log(&sun_sc->tme_sun_sc_element->tme_element_log_handle, ! 899: 100, TME_OK, ! 900: (&sun_sc->tme_sun_sc_element->tme_element_log_handle, ! 901: "dma_start: icr=0x%04x dvma=0x%04x%04x len=0x%04x", ! 902: icr, ! 903: TME_SUN_SC_REG16_GET(sun_sc, ! 904: TME_SUN_SC_REG_DMA_H), ! 905: TME_SUN_SC_REG16_GET(sun_sc, ! 906: TME_SUN_SC_REG_DMA_L), ! 907: resid)); ! 908: ! 909: /* if we're not in the DATA IN or DATA OUT phases, do nothing. the ! 910: sun2 PROMs seem to set DMA_ENABLE when DMA is impossible: */ ! 911: if ((icr ! 912: & (TME_SUN_SC_ICR_DMA_ENABLE ! 913: | TME_SUN_SC_ICR_BUSY ! 914: | TME_SUN_SC_ICR_MESSAGE ! 915: | TME_SUN_SC_ICR_COMMAND_DATA ! 916: | TME_SUN_SC_ICR_REQUEST)) ! 917: != (TME_SUN_SC_ICR_DMA_ENABLE ! 918: | TME_SUN_SC_ICR_BUSY ! 919: | TME_SUN_SC_ICR_REQUEST)) { ! 920: return (TME_SUN_SC_CALLOUT_CHECK); ! 921: } ! 922: ! 923: /* if there are no more bytes left to transfer, we need ! 924: an interrupt: */ ! 925: if (resid == 0) { ! 926: *_icr ! 927: = ((icr ! 928: & ~TME_SUN_SC_ICR_ODD_LENGTH) ! 929: | TME_SUN_SC_ICR_INT_REQUEST); ! 930: return (TME_SUN_SC_CALLOUT_INT); ! 931: } ! 932: ! 933: /* if there is only one byte left to transfer, and we're in word ! 934: mode, note the odd byte, and we need an interrupt: */ ! 935: else if (resid == 1 ! 936: && (icr ! 937: & TME_SUN_SC_ICR_WORD_MODE)) { ! 938: *_icr ! 939: = (icr ! 940: | TME_SUN_SC_ICR_ODD_LENGTH ! 941: | TME_SUN_SC_ICR_INT_REQUEST); ! 942: return (TME_SUN_SC_CALLOUT_INT); ! 943: } ! 944: ! 945: /* otherwise, start the DMA transfer with a TLB fill callout: */ ! 946: return (TME_SUN_SC_CALLOUT_TLB_FILL); ! 947: } ! 948: ! 949: /* the Sun sc bus cycle handler for the ICR. parts of this register ! 950: are connected directly to the SCSI control signals: */ ! 951: static int ! 952: _tme_sun_sc_bus_cycle_icr(void *_sun_sc, ! 953: struct tme_bus_cycle *cycle_init) ! 954: { ! 955: struct tme_sun_sc *sun_sc; ! 956: struct tme_sun_sc_cycle *sun_sc_cycle; ! 957: tme_uint16_t icr_old, icr_new, icr_diff; ! 958: int new_callouts; ! 959: ! 960: /* recover our data structure: */ ! 961: sun_sc = (struct tme_sun_sc *) _sun_sc; ! 962: ! 963: /* assume we won't need any new callouts: */ ! 964: new_callouts = 0; ! 965: ! 966: /* lock the mutex: */ ! 967: tme_mutex_lock(&sun_sc->tme_sun_sc_mutex); ! 968: ! 969: /* save the old ICR value: */ ! 970: icr_old = TME_SUN_SC_ICR_GET(sun_sc); ! 971: icr_new = icr_old; ! 972: ! 973: /* if we were requesting an interrupt, clear it now and call out an ! 974: interrupt change: */ ! 975: if (icr_new & TME_SUN_SC_ICR_INT_REQUEST) { ! 976: icr_new &= ~TME_SUN_SC_ICR_INT_REQUEST; ! 977: new_callouts |= TME_SUN_SC_CALLOUT_INT; ! 978: } ! 979: ! 980: /* run the bus cycle: */ ! 981: tme_bus_cycle_xfer_memory(cycle_init, ! 982: sun_sc->tme_sun_sc_card, ! 983: sun_sc->tme_sun_sc_device.tme_bus_device_address_last); ! 984: ! 985: ! 986: /* if this was a write: */ ! 987: if (cycle_init->tme_bus_cycle_type ! 988: == TME_BUS_CYCLE_WRITE) { ! 989: ! 990: /* put back the read-only bits: */ ! 991: icr_new = TME_SUN_SC_ICR_GET(sun_sc); ! 992: icr_new = ((icr_old ! 993: & _TME_SUN_SC_ICR_RO_BITS) ! 994: | (icr_new ! 995: & ~_TME_SUN_SC_ICR_RO_BITS)); ! 996: ! 997: /* get the set of changed bits: */ ! 998: icr_diff = icr_old ^ icr_new; ! 999: ! 1000: /* a change in RESET: */ ! 1001: if (icr_diff & TME_SUN_SC_ICR_RESET) { ! 1002: ! 1003: /* make a new cycle that asserts no data or control signals, ! 1004: except possibly for RST: */ ! 1005: sun_sc_cycle ! 1006: = _tme_sun_sc_cycle_new(sun_sc, ! 1007: sun_sc->tme_sun_sc_sequence_wait_change); ! 1008: sun_sc_cycle->tme_sun_sc_cycle_control ! 1009: = ((icr_new ! 1010: & TME_SUN_SC_ICR_RESET) ! 1011: ? TME_SCSI_SIGNAL_RST ! 1012: : 0); ! 1013: sun_sc_cycle->tme_sun_sc_cycle_data ! 1014: = 0; ! 1015: new_callouts ! 1016: |= TME_SUN_SC_CALLOUT_CYCLE; ! 1017: } ! 1018: ! 1019: /* a change in SELECT: */ ! 1020: else if (icr_diff & TME_SUN_SC_ICR_SELECT) { ! 1021: ! 1022: /* make a new cycle that sets the new state of SEL: */ ! 1023: sun_sc_cycle ! 1024: = _tme_sun_sc_cycle_new(sun_sc, ! 1025: sun_sc->tme_sun_sc_sequence_wait_change); ! 1026: sun_sc_cycle->tme_sun_sc_cycle_control ! 1027: = ((sun_sc_cycle->tme_sun_sc_cycle_control ! 1028: & ~TME_SCSI_SIGNAL_SEL) ! 1029: | ((icr_new ! 1030: & TME_SUN_SC_ICR_SELECT) ! 1031: ? TME_SCSI_SIGNAL_SEL ! 1032: : 0)); ! 1033: new_callouts ! 1034: |= TME_SUN_SC_CALLOUT_CYCLE; ! 1035: } ! 1036: ! 1037: /* if DMA_ENABLE is now set: */ ! 1038: if (icr_diff ! 1039: & icr_new ! 1040: & TME_SUN_SC_ICR_DMA_ENABLE) { ! 1041: ! 1042: /* try to start DMA: */ ! 1043: new_callouts ! 1044: |= _tme_sun_sc_dma_start(sun_sc, ! 1045: &icr_new); ! 1046: } ! 1047: ! 1048: /* a change in INT_ENABLE: */ ! 1049: if (icr_diff ! 1050: & icr_new ! 1051: & TME_SUN_SC_ICR_INT_ENABLE) { ! 1052: ! 1053: /* our interrupt signal may be changing: */ ! 1054: new_callouts |= TME_SUN_SC_CALLOUT_INT; ! 1055: } ! 1056: } ! 1057: ! 1058: /* if the ICR changed, save and log the new value: */ ! 1059: if (icr_new != icr_old) { ! 1060: TME_SUN_SC_ICR_PUT(sun_sc, icr_new); ! 1061: } ! 1062: ! 1063: /* make any new callouts: */ ! 1064: _tme_sun_sc_callout(sun_sc, new_callouts); ! 1065: ! 1066: /* unlock the mutex: */ ! 1067: tme_mutex_unlock(&sun_sc->tme_sun_sc_mutex); ! 1068: ! 1069: /* no faults: */ ! 1070: return (TME_OK); ! 1071: } ! 1072: ! 1073: /* the Sun sc bus cycle handler for other card registers: */ ! 1074: static int ! 1075: _tme_sun_sc_bus_cycle_other(void *_sun_sc, ! 1076: struct tme_bus_cycle *cycle_init) ! 1077: { ! 1078: struct tme_sun_sc *sun_sc; ! 1079: ! 1080: /* recover our data structure: */ ! 1081: sun_sc = (struct tme_sun_sc *) _sun_sc; ! 1082: ! 1083: /* lock the mutex: */ ! 1084: tme_mutex_lock(&sun_sc->tme_sun_sc_mutex); ! 1085: ! 1086: /* run the bus cycle: */ ! 1087: tme_bus_cycle_xfer_memory(cycle_init, ! 1088: sun_sc->tme_sun_sc_card, ! 1089: sun_sc->tme_sun_sc_device.tme_bus_device_address_last); ! 1090: ! 1091: /* if this was a write, dump out the other registers: */ ! 1092: if (cycle_init->tme_bus_cycle_type ! 1093: == TME_BUS_CYCLE_WRITE) { ! 1094: tme_log(&sun_sc->tme_sun_sc_element->tme_element_log_handle, ! 1095: 100, TME_OK, ! 1096: (&sun_sc->tme_sun_sc_element->tme_element_log_handle, ! 1097: "dvma=0x%04x%04x len=0x%04x", ! 1098: TME_SUN_SC_REG16_GET(sun_sc, ! 1099: TME_SUN_SC_REG_DMA_H), ! 1100: TME_SUN_SC_REG16_GET(sun_sc, ! 1101: TME_SUN_SC_REG_DMA_L), ! 1102: (TME_SUN_SC_REG16_GET(sun_sc, ! 1103: TME_SUN_SC_REG_DMA_LEN) ! 1104: ^ 0xffff))); ! 1105: } ! 1106: ! 1107: /* unlock the mutex: */ ! 1108: tme_mutex_unlock(&sun_sc->tme_sun_sc_mutex); ! 1109: ! 1110: /* no faults: */ ! 1111: return (TME_OK); ! 1112: } ! 1113: ! 1114: /* the Sun sc TLB filler: */ ! 1115: static int ! 1116: _tme_sun_sc_tlb_fill(void *_sun_sc, ! 1117: struct tme_bus_tlb *tlb, ! 1118: tme_bus_addr_t address, ! 1119: unsigned int cycles) ! 1120: { ! 1121: struct tme_sun_sc *sun_sc; ! 1122: ! 1123: /* recover our data structure: */ ! 1124: sun_sc = (struct tme_sun_sc *) _sun_sc; ! 1125: ! 1126: /* the address must be within range: */ ! 1127: assert(address < TME_SUN_SC_SIZ_CARD); ! 1128: ! 1129: /* initialize the TLB entry: */ ! 1130: tme_bus_tlb_initialize(tlb); ! 1131: ! 1132: #define TME_SUN_SC_TLB_REG(reg, siz, handler, rd)\ ! 1133: do { \ ! 1134: \ ! 1135: /* if this address falls in this register: */ \ ! 1136: if (((reg) \ ! 1137: <= address) \ ! 1138: && (address \ ! 1139: < ((reg) \ ! 1140: + (siz)))) { \ ! 1141: \ ! 1142: /* this TLB entry covers this register: */ \ ! 1143: TME_ATOMIC_WRITE(tme_bus_addr_t, \ ! 1144: tlb->tme_bus_tlb_addr_first,\ ! 1145: (reg)); \ ! 1146: TME_ATOMIC_WRITE(tme_bus_addr_t, \ ! 1147: tlb->tme_bus_tlb_addr_last,\ ! 1148: ((reg) \ ! 1149: + (siz) \ ! 1150: - 1)); \ ! 1151: \ ! 1152: /* our bus cycle handler: */ \ ! 1153: tlb->tme_bus_tlb_cycle = (handler); \ ! 1154: \ ! 1155: /* if this TLB entry allows fast reading: */\ ! 1156: if (rd) { \ ! 1157: tlb->tme_bus_tlb_emulator_off_read \ ! 1158: = &sun_sc->tme_sun_sc_card[0]; \ ! 1159: } \ ! 1160: } \ ! 1161: } while (/* CONSTCOND */ 0) ! 1162: ! 1163: TME_SUN_SC_TLB_REG(TME_SUN_SC_REG_DATA, ! 1164: TME_SUN_SC_SIZ_DATA, ! 1165: _tme_sun_sc_bus_cycle_data, ! 1166: FALSE); ! 1167: TME_SUN_SC_TLB_REG(TME_SUN_SC_REG_CMD_STAT, ! 1168: TME_SUN_SC_SIZ_CMD_STAT, ! 1169: _tme_sun_sc_bus_cycle_cmd_stat, ! 1170: FALSE); ! 1171: TME_SUN_SC_TLB_REG(TME_SUN_SC_REG_ICR, ! 1172: TME_SUN_SC_SIZ_ICR, ! 1173: _tme_sun_sc_bus_cycle_icr, ! 1174: TRUE); ! 1175: #undef TME_SUN_SC_TLB_REG ! 1176: ! 1177: /* anything else is some other register: */ ! 1178: if (tlb->tme_bus_tlb_cycle == NULL) { ! 1179: ! 1180: /* if this address is past the ICR, this TLB entry covers from ! 1181: past the ICR to the end of the card, else this TLB entry covers ! 1182: the byte at this address only: */ ! 1183: if (address ! 1184: >= (TME_SUN_SC_REG_ICR ! 1185: + TME_SUN_SC_SIZ_ICR)) { ! 1186: TME_ATOMIC_WRITE(tme_bus_addr_t, ! 1187: tlb->tme_bus_tlb_addr_first, ! 1188: (TME_SUN_SC_REG_ICR ! 1189: + TME_SUN_SC_SIZ_ICR)); ! 1190: TME_ATOMIC_WRITE(tme_bus_addr_t, ! 1191: tlb->tme_bus_tlb_addr_last, ! 1192: TME_SUN_SC_SIZ_CARD - 1); ! 1193: } ! 1194: else { ! 1195: TME_ATOMIC_WRITE(tme_bus_addr_t, ! 1196: tlb->tme_bus_tlb_addr_first, ! 1197: address); ! 1198: TME_ATOMIC_WRITE(tme_bus_addr_t, ! 1199: tlb->tme_bus_tlb_addr_last, ! 1200: address); ! 1201: } ! 1202: ! 1203: /* this TLB entry allows fast reading and writing: */ ! 1204: tlb->tme_bus_tlb_emulator_off_read ! 1205: = &sun_sc->tme_sun_sc_card[0]; ! 1206: tlb->tme_bus_tlb_emulator_off_write ! 1207: = &sun_sc->tme_sun_sc_card[0]; ! 1208: ! 1209: /* bus cycles are handled by the other handler: */ ! 1210: tlb->tme_bus_tlb_cycle = _tme_sun_sc_bus_cycle_other; ! 1211: } ! 1212: ! 1213: #ifdef TME_SUN_SC_DEBUG ! 1214: /* XXX when debugging, nothing is fast readable or writable: */ ! 1215: tlb->tme_bus_tlb_emulator_off_read ! 1216: = TME_EMULATOR_OFF_UNDEF; ! 1217: tlb->tme_bus_tlb_emulator_off_write ! 1218: = TME_EMULATOR_OFF_UNDEF; ! 1219: #endif /* TME_SUN_SC_DEBUG */ ! 1220: ! 1221: /* in case this TLB entry allows fast access: */ ! 1222: tlb->tme_bus_tlb_rwlock = &sun_sc->tme_sun_sc_rwlock; ! 1223: ! 1224: /* allow reading and writing: */ ! 1225: tlb->tme_bus_tlb_cycles_ok = TME_BUS_CYCLE_READ | TME_BUS_CYCLE_WRITE; ! 1226: ! 1227: /* our bus cycle handler private data: */ ! 1228: tlb->tme_bus_tlb_cycle_private = sun_sc; ! 1229: ! 1230: return (TME_OK); ! 1231: } ! 1232: ! 1233: /* this is called for an event on the SCSI bus: */ ! 1234: static int ! 1235: _tme_sun_sc_scsi_cycle(struct tme_scsi_connection *conn_scsi, ! 1236: tme_scsi_control_t control, ! 1237: tme_scsi_data_t data, ! 1238: _tme_const struct tme_scsi_sequence *sequence, ! 1239: struct tme_scsi_dma *dma) ! 1240: { ! 1241: struct tme_sun_sc *sun_sc; ! 1242: struct tme_sun_sc_cycle *sun_sc_cycle; ! 1243: unsigned long count; ! 1244: struct tme_bus_tlb *tlb; ! 1245: tme_uint32_t address; ! 1246: tme_uint16_t resid; ! 1247: tme_uint16_t icr_old, icr_new; ! 1248: int new_callouts; ! 1249: int new_callouts_dma; ! 1250: int rc; ! 1251: ! 1252: /* recover our data structure: */ ! 1253: sun_sc = conn_scsi->tme_scsi_connection.tme_connection_element->tme_element_private; ! 1254: ! 1255: /* assume we won't need any new callouts: */ ! 1256: new_callouts = 0; ! 1257: ! 1258: /* lock the mutex: */ ! 1259: tme_mutex_lock(&sun_sc->tme_sun_sc_mutex); ! 1260: ! 1261: /* get the old ICR value: */ ! 1262: icr_old = TME_SUN_SC_ICR_GET(sun_sc); ! 1263: ! 1264: /* update the ICR to reflect the current SCSI control signals: */ ! 1265: icr_new = icr_old; ! 1266: #define _TME_SUN_SC_ICR_CONTROL(_icr, _control) \ ! 1267: do { \ ! 1268: if (control & _control) { \ ! 1269: icr_new |= _icr; \ ! 1270: } \ ! 1271: else { \ ! 1272: icr_new &= ~_icr; \ ! 1273: } \ ! 1274: } while (/* CONSTCOND */ 0) ! 1275: _TME_SUN_SC_ICR_CONTROL(TME_SUN_SC_ICR_REQUEST, ! 1276: TME_SCSI_SIGNAL_REQ); ! 1277: _TME_SUN_SC_ICR_CONTROL(TME_SUN_SC_ICR_MESSAGE, ! 1278: TME_SCSI_SIGNAL_MSG); ! 1279: _TME_SUN_SC_ICR_CONTROL(TME_SUN_SC_ICR_COMMAND_DATA, ! 1280: TME_SCSI_SIGNAL_C_D); ! 1281: _TME_SUN_SC_ICR_CONTROL(TME_SUN_SC_ICR_INPUT_OUTPUT, ! 1282: TME_SCSI_SIGNAL_I_O); ! 1283: _TME_SUN_SC_ICR_CONTROL(TME_SUN_SC_ICR_PARITY, ! 1284: TME_SCSI_SIGNAL_DBP); ! 1285: _TME_SUN_SC_ICR_CONTROL(TME_SUN_SC_ICR_BUSY, ! 1286: TME_SCSI_SIGNAL_BSY); ! 1287: #undef _TME_SUN_SC_ICR_CONTROL ! 1288: ! 1289: /* if the bus phase has changed to the STATUS phase, call out an ! 1290: interrupt: */ ! 1291: /* XXX is this really how the board behaves? the sun2 PROM seems to ! 1292: rely on this behavior: */ ! 1293: if ((TME_SUN_SC_BUS_PHASE(icr_new) ! 1294: != TME_SUN_SC_BUS_PHASE(icr_old)) ! 1295: && (TME_SUN_SC_BUS_PHASE(icr_new) ! 1296: == (TME_SUN_SC_ICR_BUSY ! 1297: | TME_SUN_SC_ICR_COMMAND_DATA ! 1298: | TME_SUN_SC_ICR_INPUT_OUTPUT))) { ! 1299: icr_new ! 1300: |= TME_SUN_SC_ICR_INT_REQUEST; ! 1301: new_callouts ! 1302: |= TME_SUN_SC_CALLOUT_INT; ! 1303: } ! 1304: ! 1305: /* get the last SCSI cycle that we called out: */ ! 1306: sun_sc_cycle ! 1307: = &sun_sc->tme_sun_sc_cycles[sun_sc->tme_sun_sc_cycle_tail]; ! 1308: ! 1309: /* if the last SCSI cycle was for a DMA sequence: */ ! 1310: if (sun_sc_cycle->tme_sun_sc_cycle_sequence ! 1311: == sun_sc->tme_sun_sc_sequence_info_dma_initiator) { ! 1312: ! 1313: /* if the last SCSI cycle was for a genuine DMA sequence (as opposed ! 1314: to a DMA sequence to transfer the cmd_stat register), update the ! 1315: card's DMA engine registers: */ ! 1316: if ((sun_sc_cycle->tme_sun_sc_cycle_dma.tme_scsi_dma_out ! 1317: != &sun_sc_cycle->tme_sun_sc_cycle_cmd_stat) ! 1318: && (sun_sc_cycle->tme_sun_sc_cycle_dma.tme_scsi_dma_in ! 1319: != &sun_sc_cycle->tme_sun_sc_cycle_cmd_stat)) { ! 1320: ! 1321: /* get the number of bytes that were transferred: */ ! 1322: count ! 1323: = ((sun_sc_cycle->tme_sun_sc_cycle_dma.tme_scsi_dma_out ! 1324: > sun_sc_cycle->tme_sun_sc_cycle_dma.tme_scsi_dma_in) ! 1325: ? (sun_sc_cycle->tme_sun_sc_cycle_dma.tme_scsi_dma_out ! 1326: - sun_sc_cycle->tme_sun_sc_cycle_dma.tme_scsi_dma_in) ! 1327: : (sun_sc_cycle->tme_sun_sc_cycle_dma.tme_scsi_dma_in ! 1328: - sun_sc_cycle->tme_sun_sc_cycle_dma.tme_scsi_dma_out)); ! 1329: ! 1330: /* get the TLB entry: */ ! 1331: tlb ! 1332: = TME_ATOMIC_READ(struct tme_bus_tlb *, ! 1333: sun_sc->tme_sun_sc_dma_tlb); ! 1334: ! 1335: /* get the DMA address: */ ! 1336: address ! 1337: = TME_SUN_SC_REG16_GET(sun_sc, ! 1338: TME_SUN_SC_REG_DMA_H); ! 1339: address ! 1340: = ((address ! 1341: << 16) ! 1342: | TME_SUN_SC_REG16_GET(sun_sc, ! 1343: TME_SUN_SC_REG_DMA_L)); ! 1344: ! 1345: /* if we were doing a DMA write, but the TLB entry we filled ! 1346: doesn't allow fast writing, we need to do a memory write ! 1347: cycle to transfer the bytes from our internal DMA buffer into ! 1348: memory: */ ! 1349: if ((icr_old ! 1350: & TME_SUN_SC_ICR_INPUT_OUTPUT) ! 1351: && (tlb->tme_bus_tlb_emulator_off_write ! 1352: == TME_EMULATOR_OFF_UNDEF)) { ! 1353: rc = _tme_sun_sc_bus_cycle_dma(sun_sc, ! 1354: tlb, ! 1355: TME_BUS_CYCLE_WRITE, ! 1356: address, ! 1357: (icr_old ! 1358: & TME_SUN_SC_ICR_WORD_MODE)); ! 1359: assert (rc == TME_OK); ! 1360: } ! 1361: ! 1362: /* update the DMA address: */ ! 1363: address += count; ! 1364: TME_SUN_SC_REG16_PUT(sun_sc, ! 1365: TME_SUN_SC_REG_DMA_H, ! 1366: address >> 16); ! 1367: TME_SUN_SC_REG16_PUT(sun_sc, ! 1368: TME_SUN_SC_REG_DMA_L, ! 1369: address & 0xffff); ! 1370: ! 1371: /* update the DMA length: */ ! 1372: resid ! 1373: = (TME_SUN_SC_REG16_GET(sun_sc, ! 1374: TME_SUN_SC_REG_DMA_LEN) ! 1375: ^ 0xffff); ! 1376: assert (resid >= count); ! 1377: TME_SUN_SC_REG16_PUT(sun_sc, ! 1378: TME_SUN_SC_REG_DMA_LEN, ! 1379: ((resid ! 1380: - count) ! 1381: ^ 0xffff)); ! 1382: ! 1383: /* XXX this idea doesn't work because the initiator can't know ! 1384: the amount of data returned by some commands, like REQUEST ! 1385: SENSE. when does this card signal BUS_ERROR, then? */ ! 1386: #if 0 ! 1387: /* if the DMA sequence didn't transfer all of the DMA bytes that ! 1388: we had made available, that usually means that the SCSI bus ! 1389: phase changed in the middle of the transfer, which is a bus ! 1390: error: */ ! 1391: if (sun_sc_cycle->tme_sun_sc_cycle_dma.tme_scsi_dma_resid ! 1392: > 0) { ! 1393: ! 1394: /* note the bus error and request an interrupt: */ ! 1395: icr_new ! 1396: |= (TME_SUN_SC_ICR_BUS_ERROR ! 1397: | TME_SUN_SC_ICR_INT_REQUEST); ! 1398: new_callouts |= TME_SUN_SC_CALLOUT_INT; ! 1399: } ! 1400: #endif ! 1401: } ! 1402: ! 1403: /* advance the tail pointer: */ ! 1404: sun_sc->tme_sun_sc_cycle_tail ! 1405: = ((sun_sc->tme_sun_sc_cycle_tail ! 1406: + 1) ! 1407: & (TME_SUN_SC_CYCLE_RING_SIZE ! 1408: - 1)); ! 1409: } ! 1410: ! 1411: /* always try to start or continue a DMA transfer. if one ! 1412: can't be started, just wait for another SCSI bus change: */ ! 1413: new_callouts_dma ! 1414: = _tme_sun_sc_dma_start(sun_sc, ! 1415: &icr_new); ! 1416: if (new_callouts_dma != 0) { ! 1417: new_callouts |= new_callouts_dma; ! 1418: } ! 1419: else { ! 1420: sun_sc_cycle ! 1421: = _tme_sun_sc_cycle_new(sun_sc, ! 1422: sun_sc->tme_sun_sc_sequence_wait_change); ! 1423: new_callouts ! 1424: |= TME_SUN_SC_CALLOUT_CYCLE; ! 1425: } ! 1426: ! 1427: /* update the ICR and data registers: */ ! 1428: TME_SUN_SC_ICR_PUT(sun_sc, icr_new); ! 1429: sun_sc->tme_sun_sc_card[TME_SUN_SC_REG_DATA] = data; ! 1430: ! 1431: /* make any new callouts: */ ! 1432: _tme_sun_sc_callout(sun_sc, new_callouts); ! 1433: ! 1434: /* unlock the mutex: */ ! 1435: tme_mutex_unlock(&sun_sc->tme_sun_sc_mutex); ! 1436: ! 1437: return (TME_OK); ! 1438: } ! 1439: ! 1440: /* this makes a new bus connection: */ ! 1441: static int ! 1442: _tme_sun_sc_connection_make_bus(struct tme_connection *conn, ! 1443: unsigned int state) ! 1444: { ! 1445: struct tme_sun_sc *sun_sc; ! 1446: struct tme_bus_connection *conn_bus; ! 1447: int rc; ! 1448: ! 1449: /* recover our data structure: */ ! 1450: sun_sc = conn->tme_connection_element->tme_element_private; ! 1451: ! 1452: /* call the bus device connection maker: */ ! 1453: rc = tme_bus_device_connection_make(conn, state); ! 1454: ! 1455: /* if the full connection was successful, and we don't have a TLB ! 1456: set yet, allocate it: */ ! 1457: if (rc == TME_OK ! 1458: && state == TME_CONNECTION_FULL ! 1459: && TME_ATOMIC_READ(struct tme_bus_tlb *, ! 1460: sun_sc->tme_sun_sc_dma_tlb) == NULL) { ! 1461: ! 1462: /* get our bus connection: */ ! 1463: conn_bus ! 1464: = TME_ATOMIC_READ(struct tme_bus_connection *, ! 1465: sun_sc->tme_sun_sc_device.tme_bus_device_connection); ! 1466: ! 1467: /* allocate the TLB set: */ ! 1468: rc = ((*conn_bus->tme_bus_tlb_set_allocate) ! 1469: (conn_bus, ! 1470: 1, ! 1471: sizeof(struct tme_bus_tlb), ! 1472: TME_ATOMIC_POINTER(&sun_sc->tme_sun_sc_dma_tlb))); ! 1473: assert (rc == TME_OK); ! 1474: } ! 1475: ! 1476: return (rc); ! 1477: } ! 1478: ! 1479: /* this makes a new SCSI connection: */ ! 1480: static int ! 1481: _tme_sun_sc_connection_make_scsi(struct tme_connection *conn, ! 1482: unsigned int state) ! 1483: { ! 1484: struct tme_sun_sc *sun_sc; ! 1485: struct tme_sun_sc_cycle *sun_sc_cycle; ! 1486: struct tme_scsi_connection *conn_scsi; ! 1487: struct tme_scsi_connection *conn_scsi_other; ! 1488: ! 1489: /* recover our data structures: */ ! 1490: sun_sc = conn->tme_connection_element->tme_element_private; ! 1491: conn_scsi = (struct tme_scsi_connection *) conn; ! 1492: conn_scsi_other = (struct tme_scsi_connection *) conn->tme_connection_other; ! 1493: ! 1494: /* both sides must be SCSI connections: */ ! 1495: assert(conn->tme_connection_type == TME_CONNECTION_SCSI); ! 1496: assert(conn->tme_connection_other->tme_connection_type == TME_CONNECTION_SCSI); ! 1497: ! 1498: /* we're always set up to answer calls across the connection, so we ! 1499: only have to do work when the connection has gone full, namely ! 1500: taking the other side of the connection: */ ! 1501: if (state == TME_CONNECTION_FULL) { ! 1502: ! 1503: /* lock our mutex: */ ! 1504: tme_mutex_lock(&sun_sc->tme_sun_sc_mutex); ! 1505: ! 1506: /* save our connection: */ ! 1507: sun_sc->tme_sun_sc_scsi_connection = conn_scsi_other; ! 1508: ! 1509: /* get the sequences that we need: */ ! 1510: sun_sc->tme_sun_sc_sequence_info_dma_initiator ! 1511: = ((*conn_scsi_other->tme_scsi_connection_sequence_get) ! 1512: (conn_scsi_other, ! 1513: TME_SCSI_SEQUENCE_INFO_DMA_INITIATOR)); ! 1514: sun_sc->tme_sun_sc_sequence_wait_change ! 1515: = ((*conn_scsi_other->tme_scsi_connection_sequence_get) ! 1516: (conn_scsi_other, ! 1517: TME_SCSI_SEQUENCE_WAIT_CHANGE)); ! 1518: ! 1519: /* call out a cycle that asserts no signals and runs the ! 1520: wait-change sequence. this also fully-initializes ! 1521: this cycle - _tme_sun_sc_cycle_new copies the previous ! 1522: cycle into a newly allocated cycle, so this hopefully ! 1523: starts the chain of well-initialized cycles: */ ! 1524: sun_sc_cycle ! 1525: = _tme_sun_sc_cycle_new(sun_sc, ! 1526: sun_sc->tme_sun_sc_sequence_wait_change); ! 1527: sun_sc_cycle->tme_sun_sc_cycle_control ! 1528: = 0; ! 1529: sun_sc_cycle->tme_sun_sc_cycle_data ! 1530: = 0; ! 1531: _tme_sun_sc_callout(sun_sc, TME_SUN_SC_CALLOUT_CYCLE); ! 1532: ! 1533: /* unlock our mutex: */ ! 1534: tme_mutex_unlock(&sun_sc->tme_sun_sc_mutex); ! 1535: } ! 1536: ! 1537: return (TME_OK); ! 1538: } ! 1539: ! 1540: /* this breaks a connection: */ ! 1541: static int ! 1542: _tme_sun_sc_connection_break(struct tme_connection *conn, unsigned int state) ! 1543: { ! 1544: abort(); ! 1545: } ! 1546: ! 1547: /* this makes a new connection side for a Sun sc: */ ! 1548: static int ! 1549: _tme_sun_sc_connections_new(struct tme_element *element, ! 1550: const char * const *args, ! 1551: struct tme_connection **_conns, ! 1552: char **_output) ! 1553: { ! 1554: struct tme_sun_sc *sun_sc; ! 1555: struct tme_scsi_connection *conn_scsi; ! 1556: struct tme_connection *conn; ! 1557: int rc; ! 1558: ! 1559: /* recover our data structure: */ ! 1560: sun_sc = (struct tme_sun_sc *) element->tme_element_private; ! 1561: ! 1562: /* make the generic bus device connection side: */ ! 1563: rc = tme_bus_device_connections_new(element, args, _conns, _output); ! 1564: if (rc != TME_OK) { ! 1565: return (rc); ! 1566: } ! 1567: ! 1568: /* since we need to allocate a TLB set when we make our bus ! 1569: connection, make sure any generic bus device connection sides ! 1570: use our connection maker: */ ! 1571: for (conn = *_conns; ! 1572: conn != NULL; ! 1573: conn = conn->tme_connection_next) { ! 1574: if ((conn->tme_connection_type ! 1575: == TME_CONNECTION_BUS_GENERIC) ! 1576: && (conn->tme_connection_make ! 1577: == tme_bus_device_connection_make)) { ! 1578: conn->tme_connection_make ! 1579: = _tme_sun_sc_connection_make_bus; ! 1580: } ! 1581: } ! 1582: ! 1583: /* if we don't have a SCSI connection, make one: */ ! 1584: if (sun_sc->tme_sun_sc_scsi_connection == NULL) { ! 1585: ! 1586: /* allocate the new SCSI connection: */ ! 1587: conn_scsi = tme_new0(struct tme_scsi_connection, 1); ! 1588: conn = &conn_scsi->tme_scsi_connection; ! 1589: ! 1590: /* fill in the generic connection: */ ! 1591: conn->tme_connection_next = *_conns; ! 1592: conn->tme_connection_type = TME_CONNECTION_SCSI; ! 1593: conn->tme_connection_score = tme_scsi_connection_score; ! 1594: conn->tme_connection_make = _tme_sun_sc_connection_make_scsi; ! 1595: conn->tme_connection_break = _tme_sun_sc_connection_break; ! 1596: ! 1597: /* fill in the SCSI connection: */ ! 1598: conn_scsi->tme_scsi_connection_cycle = _tme_sun_sc_scsi_cycle; ! 1599: conn_scsi->tme_scsi_connection_sequence_get = NULL; ! 1600: ! 1601: /* return the connection side possibility: */ ! 1602: *_conns = conn; ! 1603: } ! 1604: ! 1605: /* done: */ ! 1606: return (TME_OK); ! 1607: } ! 1608: ! 1609: /* the new Sun sc function: */ ! 1610: TME_ELEMENT_SUB_NEW_DECL(tme_bus_multibus,sun_sc) { ! 1611: struct tme_sun_sc *sun_sc; ! 1612: int arg_i; ! 1613: int usage; ! 1614: ! 1615: /* check our arguments: */ ! 1616: usage = 0; ! 1617: arg_i = 1; ! 1618: for (;;) { ! 1619: ! 1620: if (0) { ! 1621: } ! 1622: ! 1623: /* if we ran out of arguments: */ ! 1624: else if (args[arg_i] == NULL) { ! 1625: ! 1626: break; ! 1627: } ! 1628: ! 1629: /* otherwise this is a bad argument: */ ! 1630: else { ! 1631: tme_output_append_error(_output, ! 1632: "%s %s, ", ! 1633: args[arg_i], ! 1634: _("unexpected")); ! 1635: usage = TRUE; ! 1636: break; ! 1637: } ! 1638: } ! 1639: ! 1640: if (usage) { ! 1641: tme_output_append_error(_output, ! 1642: "%s %s", ! 1643: _("usage:"), ! 1644: args[0]); ! 1645: return (EINVAL); ! 1646: } ! 1647: ! 1648: /* start the Sun sc structure: */ ! 1649: sun_sc = tme_new0(struct tme_sun_sc, 1); ! 1650: sun_sc->tme_sun_sc_element = element; ! 1651: tme_mutex_init(&sun_sc->tme_sun_sc_mutex); ! 1652: tme_rwlock_init(&sun_sc->tme_sun_sc_rwlock); ! 1653: ! 1654: /* initialize our simple bus device descriptor: */ ! 1655: sun_sc->tme_sun_sc_device.tme_bus_device_element = element; ! 1656: sun_sc->tme_sun_sc_device.tme_bus_device_tlb_fill = _tme_sun_sc_tlb_fill; ! 1657: sun_sc->tme_sun_sc_device.tme_bus_device_address_last = TME_SUN_SC_SIZ_CARD - 1; ! 1658: ! 1659: /* fill the element: */ ! 1660: element->tme_element_private = sun_sc; ! 1661: element->tme_element_connections_new = _tme_sun_sc_connections_new; ! 1662: ! 1663: return (TME_OK); ! 1664: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.