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