|
|
1.1.1.3 ! root 1: /* $Id: scsi-bus.c,v 1.8 2007/02/15 01:30:43 fredette Exp $ */ 1.1 root 2: 3: /* scsi/scsi-bus.c - a generic SCSI bus element: */ 4: 5: /* 6: * Copyright (c) 2003 Matt Fredette 7: * All rights reserved. 8: * 9: * Redistribution and use in source and binary forms, with or without 10: * modification, are permitted provided that the following conditions 11: * are met: 12: * 1. Redistributions of source code must retain the above copyright 13: * notice, this list of conditions and the following disclaimer. 14: * 2. Redistributions in binary form must reproduce the above copyright 15: * notice, this list of conditions and the following disclaimer in the 16: * documentation and/or other materials provided with the distribution. 17: * 3. All advertising materials mentioning features or use of this software 18: * must display the following acknowledgement: 19: * This product includes software developed by Matt Fredette. 20: * 4. The name of the author may not be used to endorse or promote products 21: * derived from this software without specific prior written permission. 22: * 23: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 24: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 25: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 26: * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 27: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 28: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 29: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 31: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 32: * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 33: * POSSIBILITY OF SUCH DAMAGE. 34: */ 35: 36: #include <tme/common.h> 1.1.1.3 ! root 37: _TME_RCSID("$Id: scsi-bus.c,v 1.8 2007/02/15 01:30:43 fredette Exp $"); 1.1 root 38: 39: /* includes: */ 40: #include <tme/generic/scsi.h> 1.1.1.3 ! root 41: #include <tme/threads.h> 1.1 root 42: #ifdef HAVE_STDARG_H 43: #include <stdarg.h> 44: #else /* HAVE_STDARG_H */ 45: #include <varargs.h> 46: #endif /* HAVE_STDARG_H */ 47: 48: /* macros: */ 49: 50: /* the callout flags: */ 51: #define TME_SCSI_BUS_CALLOUT_CHECK (0) 52: #define TME_SCSI_BUS_CALLOUT_RUNNING TME_BIT(0) 53: #define TME_SCSI_BUS_CALLOUTS_MASK (-2) 54: #define TME_SCSI_BUS_CALLOUT_CYCLE TME_BIT(1) 55: 56: /* structures: */ 57: 58: /* a scsi bus: */ 59: struct tme_scsi_bus { 60: 61: /* backpointer to our element: */ 62: struct tme_element *tme_scsi_bus_element; 63: 64: /* our mutex: */ 65: tme_mutex_t tme_scsi_bus_mutex; 66: 67: /* our connections: */ 68: struct tme_connection *tme_scsi_bus_connections; 69: 70: /* the callout flags: */ 71: int tme_scsi_bus_callout_flags; 72: 73: /* the current bus state: */ 74: tme_scsi_control_t tme_scsi_bus_control; 75: tme_scsi_control_t tme_scsi_bus_data; 76: }; 77: 78: /* internal information about a SCSI connection: */ 79: struct tme_scsi_connection_int { 80: 81: /* the external SCSI connection: */ 82: struct tme_scsi_connection tme_scsi_connection_int; 83: 1.1.1.3 ! root 84: /* the cycle marker for this connection: */ ! 85: tme_uint32_t tme_scsi_connection_int_cycle_marker; ! 86: 1.1 root 87: /* the control and data lines currently asserted by this connection: */ 88: tme_scsi_control_t tme_scsi_connection_int_control; 89: tme_scsi_data_t tme_scsi_connection_int_data; 90: 91: /* the SCSI bus state last reported to the connection: */ 92: tme_scsi_control_t tme_scsi_connection_int_last_control; 93: tme_scsi_control_t tme_scsi_connection_int_last_data; 94: 1.1.1.2 root 95: /* any events that this connection is waiting on, and any that 96: triggered: */ 97: tme_uint32_t tme_scsi_connection_int_events_waiting; 98: tme_uint32_t tme_scsi_connection_int_events_triggered; 99: 100: /* any actions that this connection is waiting to take, and any that 101: were taken: */ 102: tme_uint32_t tme_scsi_connection_int_actions_waiting; 103: tme_uint32_t tme_scsi_connection_int_actions_taken; 104: 105: /* any step within the current action sequence: */ 1.1 root 106: unsigned int tme_scsi_connection_int_sequence_step; 107: 108: /* any DMA structure for this connection: */ 1.1.1.2 root 109: struct tme_scsi_dma tme_scsi_connection_int_dma_buffer; 1.1 root 110: struct tme_scsi_dma *tme_scsi_connection_int_dma; 111: 112: /* specific callout flags for this connection: */ 113: int tme_scsi_connection_int_callout_flags; 114: }; 115: 116: /* the SCSI bus callout function. it must be called with the mutex locked: */ 117: static void 118: _tme_scsi_bus_callout(struct tme_scsi_bus *scsi_bus, int new_callouts) 119: { 120: struct tme_scsi_connection_int *conn_int; 121: struct tme_scsi_connection *conn_scsi; 122: int callouts, later_callouts; 123: tme_scsi_control_t control; 124: tme_scsi_data_t data; 1.1.1.2 root 125: tme_uint32_t events_triggered; 126: tme_uint32_t actions_taken; 127: struct tme_scsi_dma dma_buffer; 128: const struct tme_scsi_dma *dma; 1.1 root 129: int rc; 130: 131: /* add in any new callouts: */ 132: scsi_bus->tme_scsi_bus_callout_flags |= new_callouts; 133: 134: /* if this function is already running in another thread, simply 135: return now. the other thread will do our work: */ 136: if (scsi_bus->tme_scsi_bus_callout_flags 137: & TME_SCSI_BUS_CALLOUT_RUNNING) { 138: return; 139: } 140: 141: /* callouts are now running: */ 142: scsi_bus->tme_scsi_bus_callout_flags 143: |= TME_SCSI_BUS_CALLOUT_RUNNING; 144: 145: /* assume that we won't need any later callouts: */ 146: later_callouts = 0; 147: 148: /* loop while callouts are needed: */ 149: for (; ((callouts 150: = scsi_bus->tme_scsi_bus_callout_flags) 151: & TME_SCSI_BUS_CALLOUTS_MASK); ) { 152: 153: /* clear the needed callouts: */ 154: scsi_bus->tme_scsi_bus_callout_flags 155: = (callouts 156: & ~TME_SCSI_BUS_CALLOUTS_MASK); 157: callouts &= TME_SCSI_BUS_CALLOUTS_MASK; 158: 159: /* if we need to call out SCSI bus cycles: */ 160: if (callouts & TME_SCSI_BUS_CALLOUT_CYCLE) { 161: 162: /* loop over all devices on the bus: */ 163: for (conn_int 164: = ((struct tme_scsi_connection_int *) 165: scsi_bus->tme_scsi_bus_connections); 166: conn_int != NULL; 167: conn_int 168: = ((struct tme_scsi_connection_int *) 169: conn_int->tme_scsi_connection_int.tme_scsi_connection.tme_connection_next)) { 170: 171: /* if this device doesn't need a callout, continue: */ 172: if (!(conn_int->tme_scsi_connection_int_callout_flags 173: & TME_SCSI_BUS_CALLOUT_CYCLE)) { 174: continue; 175: } 176: 177: /* clear the callout flag on this device: */ 178: conn_int->tme_scsi_connection_int_callout_flags 179: &= ~TME_SCSI_BUS_CALLOUT_CYCLE; 180: 181: /* get the current state of the bus: */ 182: control = scsi_bus->tme_scsi_bus_control; 183: data = scsi_bus->tme_scsi_bus_data; 184: 185: /* remember this last bus state called out to this connection: */ 186: conn_int->tme_scsi_connection_int_last_control 187: = control; 188: conn_int->tme_scsi_connection_int_last_data 189: = data; 190: 1.1.1.3 ! root 191: /* get and clear the events triggered, actions taken, and any ! 192: DMA structure: */ 1.1.1.2 root 193: events_triggered = conn_int->tme_scsi_connection_int_events_triggered; 194: actions_taken = conn_int->tme_scsi_connection_int_actions_taken; 195: dma = conn_int->tme_scsi_connection_int_dma; 196: if (dma != NULL) { 197: dma_buffer = *dma; 198: dma = &dma_buffer; 199: } 1.1.1.3 ! root 200: conn_int->tme_scsi_connection_int_events_triggered = 0; ! 201: conn_int->tme_scsi_connection_int_actions_taken = 0; ! 202: conn_int->tme_scsi_connection_int_dma = NULL; ! 203: ! 204: /* add the cycle marker to the actions taken: */ ! 205: actions_taken |= conn_int->tme_scsi_connection_int_cycle_marker; 1.1.1.2 root 206: 1.1 root 207: /* unlock the mutex: */ 208: tme_mutex_unlock(&scsi_bus->tme_scsi_bus_mutex); 209: 210: /* do the callout: */ 211: conn_scsi 212: = ((struct tme_scsi_connection *) 213: conn_int->tme_scsi_connection_int.tme_scsi_connection.tme_connection_other); 214: rc = ((*conn_scsi->tme_scsi_connection_cycle) 215: (conn_scsi, 216: control, 217: data, 1.1.1.2 root 218: events_triggered, 219: actions_taken, 220: dma)); 1.1 root 221: 222: /* lock the mutex: */ 223: tme_mutex_lock(&scsi_bus->tme_scsi_bus_mutex); 224: 225: /* if the callout was unsuccessful, remember that at some later 226: time this callout should be attempted again: */ 227: if (rc != TME_OK) { 228: conn_int->tme_scsi_connection_int_callout_flags 229: |= TME_SCSI_BUS_CALLOUT_CYCLE; 230: later_callouts 231: |= TME_SCSI_BUS_CALLOUT_CYCLE; 232: } 233: } 234: } 235: } 236: 237: /* put in any later callouts, and clear that callouts are running: */ 238: scsi_bus->tme_scsi_bus_callout_flags = later_callouts; 239: } 240: 241: /* this handles a SCSI bus cycle: */ 242: static int 243: _tme_scsi_bus_cycle(struct tme_scsi_connection *conn_scsi, 244: tme_scsi_control_t control, 245: tme_scsi_data_t data, 1.1.1.2 root 246: tme_uint32_t events_asker, 247: tme_uint32_t actions_asker, 248: const struct tme_scsi_dma *dma_asker) 1.1 root 249: { 250: struct tme_scsi_bus *scsi_bus; 251: struct tme_scsi_connection_int *conn_int_asker, *conn_int; 1.1.1.2 root 252: tme_uint32_t events; 253: tme_uint32_t actions; 254: struct tme_scsi_dma *dma; 1.1 root 255: struct tme_scsi_connection_int *dma_initiator; 256: struct tme_scsi_connection_int *dma_target; 257: struct tme_scsi_dma *dma_in, *dma_out; 258: unsigned long count; 259: int bus_changed; 260: int new_callouts; 261: int again; 262: 263: /* recover our bus and internal connection: */ 264: scsi_bus = conn_scsi->tme_scsi_connection.tme_connection_element->tme_element_private; 265: conn_int_asker = (struct tme_scsi_connection_int *) conn_scsi; 266: 267: /* assume we won't need any new callouts: */ 268: new_callouts = 0; 269: 270: /* lock the mutex: */ 271: tme_mutex_lock(&scsi_bus->tme_scsi_bus_mutex); 272: 1.1.1.3 ! root 273: /* update the cycle marker for this device: */ ! 274: conn_int_asker->tme_scsi_connection_int_cycle_marker = (actions_asker & TME_SCSI_ACTION_CYCLE_MARKER); ! 275: actions_asker &= ~TME_SCSI_ACTION_CYCLE_MARKER; ! 276: 1.1 root 277: /* update the signals that this device is asserting: */ 278: conn_int_asker->tme_scsi_connection_int_control = control; 279: conn_int_asker->tme_scsi_connection_int_data = data; 280: 1.1.1.2 root 281: /* if you're waiting on TME_SCSI_EVENT_BUS_CHANGE, you can't wait on 282: anything else, and you can't have any actions: */ 283: /* you can't wait on TME_SCSI_EVENT_BUS_CHANGE and anything else: */ 284: assert(!(events_asker & TME_SCSI_EVENT_BUS_CHANGE) 285: || (events_asker == TME_SCSI_EVENT_BUS_CHANGE 286: && actions_asker == TME_SCSI_ACTION_NONE)); 287: 288: /* you can do at most one of: select, reselect, DMA initiator, DMA target: */ 289: assert (((events_asker 290: & (TME_SCSI_ACTION_SELECT 291: | TME_SCSI_ACTION_RESELECT 292: | TME_SCSI_ACTION_DMA_INITIATOR 293: | TME_SCSI_ACTION_DMA_TARGET)) 294: & ((events_asker 295: & (TME_SCSI_ACTION_SELECT 296: | TME_SCSI_ACTION_RESELECT 297: | TME_SCSI_ACTION_DMA_INITIATOR 298: | TME_SCSI_ACTION_DMA_TARGET)) - 1)) == 0); 299: 300: /* you can't provide a DMA structure without a DMA action, or with any events: */ 301: assert ((dma_asker != NULL) 302: == ((actions_asker 303: & (TME_SCSI_ACTION_DMA_INITIATOR 304: | TME_SCSI_ACTION_DMA_TARGET)) != 0)); 305: assert ((dma_asker == NULL) || (events_asker == TME_SCSI_EVENT_NONE)); 306: 307: /* update the events and actions for this device: */ 308: conn_int_asker->tme_scsi_connection_int_events_waiting = events_asker; 309: conn_int_asker->tme_scsi_connection_int_events_triggered = 0; 310: conn_int_asker->tme_scsi_connection_int_actions_waiting = actions_asker; 311: conn_int_asker->tme_scsi_connection_int_actions_taken = 0; 1.1 root 312: conn_int_asker->tme_scsi_connection_int_sequence_step = 0; 313: 1.1.1.2 root 314: /* if this is a DMA sequence: */ 315: conn_int_asker->tme_scsi_connection_int_dma = NULL; 316: if (dma_asker != NULL) { 317: 318: /* XXX is the 8-bit DMA restriction necessary? how does wide SCSI 319: handle transfers of odd numbers of bytes? */ 320: if ((dma_asker->tme_scsi_dma_flags 321: & TME_SCSI_DMA_WIDTH) 322: != TME_SCSI_DMA_8BIT) { 1.1 root 323: abort(); 324: } 1.1.1.2 root 325: 326: /* copy in the DMA structure: */ 327: conn_int_asker->tme_scsi_connection_int_dma_buffer = *dma_asker; 328: conn_int_asker->tme_scsi_connection_int_dma = &conn_int_asker->tme_scsi_connection_int_dma_buffer; 329: 330: /* if the caller passed us a DMA structure with zero bytes left to 331: transfer, call out a cycle now: */ 332: if (dma_asker->tme_scsi_dma_resid == 0) { 1.1 root 333: conn_int_asker->tme_scsi_connection_int_callout_flags 334: |= TME_SCSI_BUS_CALLOUT_CYCLE; 1.1.1.2 root 335: conn_int_asker->tme_scsi_connection_int_events_waiting = TME_SCSI_EVENT_NONE; 336: conn_int_asker->tme_scsi_connection_int_actions_waiting = actions_asker; 1.1 root 337: new_callouts 338: |= TME_SCSI_BUS_CALLOUT_CYCLE; 339: } 340: } 341: 342: /* if during any iteration of the below loop, we see or cause a 343: change on the bus, we want to call out cycles to all devices 344: waiting on a simple change: */ 345: bus_changed = FALSE; 346: 347: /* loop until things settle down: */ 348: for (again = TRUE; again; ) { 349: again = FALSE; 350: 351: /* get the current state of the bus: */ 352: control = 0; 353: data = 0; 354: for (conn_int 355: = ((struct tme_scsi_connection_int *) 356: scsi_bus->tme_scsi_bus_connections); 357: conn_int != NULL; 358: conn_int 359: = ((struct tme_scsi_connection_int *) 360: conn_int->tme_scsi_connection_int.tme_scsi_connection.tme_connection_next)) { 361: control |= conn_int->tme_scsi_connection_int_control; 362: data |= conn_int->tme_scsi_connection_int_data; 363: } 364: if ((control != scsi_bus->tme_scsi_bus_control) 365: || (data != scsi_bus->tme_scsi_bus_data)) { 366: bus_changed = TRUE; 367: } 368: scsi_bus->tme_scsi_bus_control = control; 369: scsi_bus->tme_scsi_bus_data = data; 370: 371: /* loop over all devices on the bus: */ 372: dma_initiator = NULL; 373: dma_target = NULL; 374: for (conn_int 375: = ((struct tme_scsi_connection_int *) 376: scsi_bus->tme_scsi_bus_connections); 377: conn_int != NULL; 378: conn_int 379: = ((struct tme_scsi_connection_int *) 380: conn_int->tme_scsi_connection_int.tme_scsi_connection.tme_connection_next)) { 381: 1.1.1.2 root 382: /* get any waiting events and actions: */ 383: events = conn_int->tme_scsi_connection_int_events_waiting; 384: actions = conn_int->tme_scsi_connection_int_actions_waiting; 385: 1.1.1.3 ! root 386: /* if this device isn't waiting for any events and has no ! 387: actions to take, continue now: */ ! 388: if (events == TME_SCSI_EVENT_NONE ! 389: && actions == TME_SCSI_ACTION_NONE) { ! 390: continue; ! 391: } ! 392: 1.1.1.2 root 393: /* if this device is waiting on any change to the bus state, and 394: the bus has changed: */ 395: if ((events & TME_SCSI_EVENT_BUS_CHANGE) 396: && (bus_changed 397: || (control != 398: conn_int->tme_scsi_connection_int_last_control) 399: || (data 400: != conn_int->tme_scsi_connection_int_last_data))) { 401: 402: /* this event has triggered. we never take any action: */ 403: conn_int->tme_scsi_connection_int_events_triggered = TME_SCSI_EVENT_BUS_CHANGE; 404: events = TME_SCSI_EVENT_NONE; 405: actions = TME_SCSI_ACTION_NONE; 1.1 root 406: } 407: 1.1.1.2 root 408: /* if this device is waiting to be selected, and the device is 409: now being selected: */ 410: if ((events & TME_SCSI_EVENT_SELECTED) 1.1 root 411: 412: /* "In all systems, the target shall determine that it is 413: selected when SEL and its SCSI ID bit are true and BSY and 414: I/O are false for at least a bus settle delay." */ 1.1.1.2 root 415: && TME_SCSI_ID_SELECTED(TME_SCSI_EVENT_IDS_WHICH(events), control, data)) { 416: 417: /* this event has triggered. the only action we can take is 418: to respond to the selection: */ 419: conn_int->tme_scsi_connection_int_events_triggered = TME_SCSI_EVENT_SELECTED | TME_SCSI_EVENT_IDS_SELF(data); 420: events = TME_SCSI_EVENT_NONE; 421: actions &= TME_SCSI_ACTION_RESPOND_SELECTED; 422: } 423: 424: /* if this device is waiting to be reselected, and the device is 425: now being reselected: */ 426: if ((events & TME_SCSI_EVENT_RESELECTED) 427: 428: /* "The initiator shall determine that it is reselected when 429: SEL, I/O, and its SCSI ID bit are true and BSY is false 430: for at least a bus settle delay." */ 431: && TME_SCSI_ID_RESELECTED(TME_SCSI_EVENT_IDS_WHICH(events), control, data)) { 432: 433: /* this event has triggered. the only action we can take is 434: to respond to the reselection: */ 435: conn_int->tme_scsi_connection_int_events_triggered = TME_SCSI_EVENT_RESELECTED | TME_SCSI_EVENT_IDS_SELF(data); 436: events = TME_SCSI_EVENT_NONE; 437: actions &= TME_SCSI_ACTION_RESPOND_RESELECTED; 438: } 439: 440: /* if this device is waiting for the bus to be free, and the bus 441: is now free: */ 442: if ((events & TME_SCSI_EVENT_BUS_FREE) 443: 444: /* "SCSI devices shall detect the BUS FREE phase after SEL 445: and BSY are both false for at least a bus settle delay." */ 446: && (control 447: & (TME_SCSI_SIGNAL_SEL 448: | TME_SCSI_SIGNAL_BSY)) == 0) { 449: 450: /* this event has triggered. we won't respond to selection or 451: reselection, since we won't be selected or reselected: */ 452: conn_int->tme_scsi_connection_int_events_triggered = TME_SCSI_EVENT_BUS_FREE; 453: events = TME_SCSI_EVENT_NONE; 454: actions &= ~(TME_SCSI_ACTION_RESPOND_SELECTED | TME_SCSI_ACTION_RESPOND_RESELECTED); 455: } 456: 457: /* put back this device's waiting events. if this device is 458: still waiting for one or more events, continue now: */ 459: conn_int->tme_scsi_connection_int_events_waiting = events; 460: if (events != TME_SCSI_EVENT_NONE) { 461: continue; 462: } 463: 464: /* if this device is arbitrating for the bus: */ 465: if (TME_SCSI_ACTIONS_SELECTED(actions, TME_SCSI_ACTION_ARBITRATE_FULL)) { 466: 467: /* assert BSY and the device ID on this device's behalf. if 468: we're doing full arbitration, also assert SEL on this 469: device's behalf: */ 470: conn_int->tme_scsi_connection_int_control 471: = (TME_SCSI_SIGNAL_BSY 472: | (((actions & TME_SCSI_ACTION_ARBITRATE_FULL) 473: == TME_SCSI_ACTION_ARBITRATE_FULL) 474: ? TME_SCSI_SIGNAL_SEL 475: : 0)); 476: conn_int->tme_scsi_connection_int_data 477: = TME_BIT(TME_SCSI_ACTION_ID_SELF_WHICH(actions)); 478: again = TRUE; 479: bus_changed = TRUE; 480: 481: /* this action has been taken: */ 482: conn_int->tme_scsi_connection_int_actions_taken 483: |= ((actions & TME_SCSI_ACTION_ARBITRATE_FULL) 484: | TME_SCSI_ACTION_ID_SELF(TME_SCSI_ACTION_ID_SELF_WHICH(actions))); 485: actions &= ~TME_SCSI_ACTION_ARBITRATE_FULL; 486: } 487: 488: /* if this device is selecting or reselecting another device: */ 489: if (TME_SCSI_ACTIONS_SELECTED(actions, 490: (TME_SCSI_ACTION_SELECT 1.1.1.3 ! root 491: | TME_SCSI_ACTION_SELECT_WITH_ATN 1.1.1.2 root 492: | TME_SCSI_ACTION_SELECT_SINGLE_INITIATOR 493: | TME_SCSI_ACTION_RESELECT))) { 494: 495: /* "Except in certain single initiator environments with 496: initiators employing the single initiator option, the 497: initiator shall set the DATA BUS to a value which is the OR 498: of its SCSI ID bit and the target's SCSI ID bit. The 499: initiator shall then wait at least two deskew delays and 500: release BSY." 501: 502: "Initiators that do not implement the RESELECTION phase and 503: do not operate in the multiple initiator environment are 504: allowed to set only the target's SCSI ID bit during the 505: SELECTION phase. This makes it impossible for the target 506: to determine the initiator's SCSI ID." 507: 508: "The winning SCSI device becomes a target by asserting the 509: I/O signal. The winning SCSI device shall also set the 510: DATA BUS to a value that is the OR of its SCSI ID bit and 511: the initiator's SCSI ID bit. The target shall wait at 512: least two deskew delays and release BSY." */ 513: 514: /* set the sequence's selection/reselection SCSI IDs on the 515: bus, then set I/O if this is a reselection, and release 516: BSY: */ 517: conn_int->tme_scsi_connection_int_data 518: = (TME_BIT(TME_SCSI_ACTION_ID_OTHER_WHICH(actions)) 519: | (((actions & TME_SCSI_ACTION_SELECT_SINGLE_INITIATOR) 520: == TME_SCSI_ACTION_SELECT_SINGLE_INITIATOR) 521: ? 0 522: : TME_BIT(TME_SCSI_ACTION_ID_SELF_WHICH(actions)))); 523: conn_int->tme_scsi_connection_int_control 524: = (TME_SCSI_SIGNAL_SEL 525: | ((actions & TME_SCSI_ACTION_RESELECT) 526: ? TME_SCSI_SIGNAL_I_O 1.1.1.3 ! root 527: : 0) ! 528: | (((actions & TME_SCSI_ACTION_SELECT_WITH_ATN) ! 529: == TME_SCSI_ACTION_SELECT_WITH_ATN) ! 530: ? TME_SCSI_SIGNAL_ATN 1.1.1.2 root 531: : 0)); 532: again = TRUE; 533: bus_changed = TRUE; 534: 535: /* this action has been taken: */ 536: conn_int->tme_scsi_connection_int_actions_taken 537: |= ((actions 538: & (TME_SCSI_ACTION_SELECT 1.1.1.3 ! root 539: | TME_SCSI_ACTION_SELECT_WITH_ATN 1.1.1.2 root 540: | TME_SCSI_ACTION_SELECT_SINGLE_INITIATOR 541: | TME_SCSI_ACTION_RESELECT)) 542: | TME_SCSI_ACTION_ID_SELF(TME_SCSI_ACTION_ID_SELF_WHICH(actions)) 543: | TME_SCSI_ACTION_ID_OTHER(TME_SCSI_ACTION_ID_OTHER_WHICH(actions))); 544: actions &= ~(TME_SCSI_ACTION_SELECT 1.1.1.3 ! root 545: | TME_SCSI_ACTION_SELECT_WITH_ATN 1.1.1.2 root 546: | TME_SCSI_ACTION_SELECT_SINGLE_INITIATOR 547: | TME_SCSI_ACTION_RESELECT); 548: } 549: 550: /* if this device is responding to selection or reselection: */ 551: if (TME_SCSI_ACTIONS_SELECTED(actions, 552: (TME_SCSI_ACTION_RESPOND_SELECTED 553: | TME_SCSI_ACTION_RESPOND_RESELECTED))) { 554: 555: /* dispatch on the step: */ 556: switch (conn_int->tme_scsi_connection_int_sequence_step) { 557: 1.1 root 558: case 0: 1.1.1.2 root 559: 560: /* assert BSY on the device's behalf: */ 561: conn_int->tme_scsi_connection_int_control 562: = TME_SCSI_SIGNAL_BSY; 563: again = TRUE; 564: bus_changed = TRUE; 1.1 root 565: 1.1.1.2 root 566: /* advance to the next step: */ 567: conn_int->tme_scsi_connection_int_sequence_step++; 568: 569: /* FALLTHROUGH */ 570: 571: case 1: 1.1 root 572: 573: /* "At least two deskew delays after the initiator detects 574: BSY is true, it shall release SEL and may change the DATA 575: BUS." 576: 1.1.1.2 root 577: "After the reselected initiator detects SEL false, it 578: shall release BSY." */ 1.1 root 579: if (!(control 580: & TME_SCSI_SIGNAL_SEL)) { 1.1.1.2 root 581: 582: /* if this was a reselection: */ 583: if (actions & TME_SCSI_ACTION_RESPOND_RESELECTED) { 584: 585: /* negate BSY on the device's behalf: */ 586: conn_int->tme_scsi_connection_int_control 587: = 0; 588: again = TRUE; 589: bus_changed = TRUE; 590: } 591: 592: /* this action has been taken: */ 593: conn_int->tme_scsi_connection_int_actions_taken 594: |= (actions 595: & (TME_SCSI_ACTION_RESPOND_SELECTED 596: | TME_SCSI_ACTION_RESPOND_RESELECTED)); 597: actions 598: &= ~(TME_SCSI_ACTION_RESPOND_SELECTED 599: | TME_SCSI_ACTION_RESPOND_RESELECTED); 600: conn_int->tme_scsi_connection_int_sequence_step = 0; 1.1 root 601: } 602: break; 603: } 604: } 605: 606: /* there can be at most one device in an initiator or target 607: information transfer phase DMA sequence: */ 1.1.1.3 ! root 608: else if (TME_SCSI_ACTIONS_SELECTED(actions, ! 609: (TME_SCSI_ACTION_DMA_INITIATOR ! 610: | TME_SCSI_ACTION_DMA_INITIATOR_HOLD_ACK))) { 1.1 root 611: assert (dma_initiator == NULL); 612: dma_initiator = conn_int; 613: } 1.1.1.2 root 614: else if (TME_SCSI_ACTIONS_SELECTED(actions, TME_SCSI_ACTION_DMA_TARGET)) { 1.1 root 615: assert (dma_target == NULL); 616: dma_target = conn_int; 617: } 1.1.1.2 root 618: 619: /* put back this device's waiting actions. if this device is 620: not waiting for any more actions: */ 621: conn_int->tme_scsi_connection_int_actions_waiting = actions; 622: if ((actions 623: & (TME_SCSI_ACTION_DMA_INITIATOR 1.1.1.3 ! root 624: | TME_SCSI_ACTION_DMA_INITIATOR_HOLD_ACK 1.1.1.2 root 625: | TME_SCSI_ACTION_DMA_TARGET 626: | TME_SCSI_ACTION_RESPOND_SELECTED 627: | TME_SCSI_ACTION_RESPOND_RESELECTED 628: | TME_SCSI_ACTION_SELECT 1.1.1.3 ! root 629: | TME_SCSI_ACTION_SELECT_WITH_ATN 1.1.1.2 root 630: | TME_SCSI_ACTION_SELECT_SINGLE_INITIATOR 631: | TME_SCSI_ACTION_RESELECT 632: | TME_SCSI_ACTION_ARBITRATE_HALF 633: | TME_SCSI_ACTION_ARBITRATE_FULL)) == 0) { 634: 635: /* call out a cycle on this device: */ 636: conn_int->tme_scsi_connection_int_callout_flags 637: |= TME_SCSI_BUS_CALLOUT_CYCLE; 638: new_callouts 639: |= TME_SCSI_BUS_CALLOUT_CYCLE; 640: } 1.1 root 641: } 642: 643: /* if we need to loop again, do so immediately: */ 644: if (again) { 645: continue; 646: } 647: 648: /* if a device is in the target information transfer phase DMA 649: sequence: */ 650: if (dma_target != NULL) { 651: 652: /* get this device's DMA structure: */ 653: dma = dma_target->tme_scsi_connection_int_dma; 654: assert (dma != NULL); 655: 656: /* dispatch on the sequence step: */ 657: switch (dma_target->tme_scsi_connection_int_sequence_step) { 658: 659: /* "If I/O is true (transfer to the initiator)... [after] ACK 660: is false the target may continue the transfer by driving 661: DB(7-0,P) and asserting REQ, as described above." 662: 663: "If I/O is false (transfer to the target)... [after ACK is 664: false the target] may continue the transfer by asserting 665: REQ, as described above." */ 666: case 2: 667: if (control & TME_SCSI_SIGNAL_ACK) { 668: break; 669: } 670: 671: /* if the DMA has been exhausted, callout a cycle on this 672: device: */ 673: if (control & TME_SCSI_SIGNAL_I_O) { 674: dma->tme_scsi_dma_out++; 675: } 676: else { 677: dma->tme_scsi_dma_in++; 678: } 679: if (--dma->tme_scsi_dma_resid == 0) { 680: dma_target->tme_scsi_connection_int_callout_flags 681: |= TME_SCSI_BUS_CALLOUT_CYCLE; 1.1.1.2 root 682: dma_target->tme_scsi_connection_int_actions_waiting 683: = TME_SCSI_ACTION_NONE; 684: dma_target->tme_scsi_connection_int_actions_taken 685: |= TME_SCSI_ACTION_DMA_TARGET; 1.1 root 686: new_callouts 687: |= TME_SCSI_BUS_CALLOUT_CYCLE; 688: break; 689: } 690: 691: /* FALLTHROUGH */ 692: 693: /* "If I/O is true (transfer to the initiator), the target shall 694: first drive DB(7-0,P) to their desired values, delay at least 695: one deskew delay plus a cable skew delay, then assert REQ." 696: 697: "If I/O is false (transfer to the target) the target shall request 698: information by asserting REQ. " */ 699: case 0: 700: 701: /* assert REQ on the target's behalf: */ 702: dma_target->tme_scsi_connection_int_control 703: |= TME_SCSI_SIGNAL_REQ; 704: again = TRUE; 705: bus_changed = TRUE; 706: 707: /* if I/O is asserted, assert the output data: */ 708: if (control & TME_SCSI_SIGNAL_I_O) { 709: dma_target->tme_scsi_connection_int_data 710: = *(dma->tme_scsi_dma_out); 711: } 712: 713: /* advance to step one: */ 714: dma_target->tme_scsi_connection_int_sequence_step = 1; 715: break; 716: 717: /* "If I/O is true (transfer to the initiator)... [when] ACK 718: becomes true at the target, the target may change or 719: release DB(7-0,P) and shall negate REQ." 720: 721: "If I/O is false (transfer to the target)... [when] ACK 722: becomes true at the target, the target shall read 723: DB(7-0,P), then negate REQ." */ 724: case 1: 725: if (control & TME_SCSI_SIGNAL_ACK) { 726: 727: /* if I/O is negated, read the input data: */ 728: if (!(control & TME_SCSI_SIGNAL_I_O)) { 729: *(dma->tme_scsi_dma_in) = data; 730: } 731: 732: /* negate REQ on the target's behalf: */ 733: dma_target->tme_scsi_connection_int_control 734: &= ~TME_SCSI_SIGNAL_REQ; 735: again = TRUE; 736: bus_changed = TRUE; 737: 738: /* advance to step two: */ 739: dma_target->tme_scsi_connection_int_sequence_step = 2; 740: } 741: break; 742: 743: default: assert (FALSE); 744: } 745: 746: /* if the bus is being reset: */ 747: if (control & TME_SCSI_SIGNAL_RST) { 748: 749: /* negate all signals on the target's behalf: */ 750: dma_target->tme_scsi_connection_int_control = 0; 751: dma_target->tme_scsi_connection_int_data = 0; 752: again = TRUE; 753: bus_changed = TRUE; 754: 755: /* callout a cycle on this device: */ 756: dma_target->tme_scsi_connection_int_callout_flags 757: |= TME_SCSI_BUS_CALLOUT_CYCLE; 1.1.1.2 root 758: dma_target->tme_scsi_connection_int_actions_waiting 759: = TME_SCSI_ACTION_NONE; 760: dma_target->tme_scsi_connection_int_actions_taken 761: = TME_SCSI_ACTION_NONE; 762: dma_target->tme_scsi_connection_int_events_triggered 763: = TME_SCSI_EVENT_BUS_RESET; 1.1 root 764: new_callouts 765: |= TME_SCSI_BUS_CALLOUT_CYCLE; 766: } 767: } 768: 769: /* if we need to loop again, do so immediately: */ 770: if (again) { 771: continue; 772: } 773: 774: /* if a device is in the initiator information transfer phase DMA 775: sequence: */ 776: if (dma_initiator != NULL) { 777: 778: /* get this device's DMA structure: */ 779: dma = dma_initiator->tme_scsi_connection_int_dma; 780: assert (dma != NULL); 781: 782: /* dispatch on the sequence step: */ 783: switch (dma_initiator->tme_scsi_connection_int_sequence_step) { 784: 785: /* "If I/O is true (transfer to the initiator)... [the] 786: initiator shall read DB(7-0,P) after REQ is true, then 787: signal its acceptance of the data by asserting ACK." 788: 789: "If I/O is false (transfer to the target)... [the] 790: initiator shall drive DB(7-0,P) to their desired values 791: [after REQ is true], delay at least one deskew delay plus a 792: cable skew delay and assert ACK." */ 793: case 0: 794: if (!(control & TME_SCSI_SIGNAL_REQ)) { 795: break; 796: } 797: 1.1.1.3 ! root 798: /* if the information transfer phase has changed, callout a ! 799: cycle on this device: */ ! 800: if (TME_SCSI_PHASE(control) ! 801: != TME_SCSI_PHASE(dma_initiator->tme_scsi_connection_int_last_control)) { ! 802: dma_initiator->tme_scsi_connection_int_callout_flags ! 803: |= TME_SCSI_BUS_CALLOUT_CYCLE; ! 804: dma_initiator->tme_scsi_connection_int_actions_taken ! 805: |= dma_initiator->tme_scsi_connection_int_actions_waiting; ! 806: dma_initiator->tme_scsi_connection_int_actions_waiting ! 807: = TME_SCSI_ACTION_NONE; ! 808: new_callouts ! 809: |= TME_SCSI_BUS_CALLOUT_CYCLE; ! 810: break; ! 811: } ! 812: ! 813: /* if another device is in the target information transfer ! 814: phase DMA sequence, we may do a bulk copy between them: */ ! 815: if (dma_target != NULL) { ! 816: assert (dma_target->tme_scsi_connection_int_sequence_step == 1); ! 817: ! 818: /* sort the devices' DMA structures into input and output: */ ! 819: if (control & TME_SCSI_SIGNAL_I_O) { ! 820: dma_in = dma_initiator->tme_scsi_connection_int_dma; ! 821: dma_out = dma_target->tme_scsi_connection_int_dma; ! 822: } ! 823: else { ! 824: dma_out = dma_initiator->tme_scsi_connection_int_dma; ! 825: dma_in = dma_target->tme_scsi_connection_int_dma; ! 826: } ! 827: assert (dma_out != NULL && dma_in != NULL); ! 828: ! 829: /* get the size of the bulk copy. we won't copy all ! 830: possible bytes, since this code doesn't know how to ! 831: assert control lines or make callouts. instead, we bulk ! 832: copy one less than all possible bytes, and let the ! 833: normal, non-bulk code handle the final byte: */ ! 834: count = TME_MIN(dma_out->tme_scsi_dma_resid, ! 835: dma_in->tme_scsi_dma_resid); ! 836: assert (count > 0); ! 837: ! 838: /* if we have bytes to bulk copy: */ ! 839: count--; ! 840: if (count > 0) { ! 841: ! 842: /* do the bulk copy: */ ! 843: memcpy(dma_in->tme_scsi_dma_in, ! 844: dma_out->tme_scsi_dma_out, ! 845: count); ! 846: ! 847: /* advance: */ ! 848: dma_in->tme_scsi_dma_in += count; ! 849: dma_in->tme_scsi_dma_resid -= count; ! 850: dma_out->tme_scsi_dma_out += count; ! 851: dma_out->tme_scsi_dma_resid -= count; ! 852: ! 853: /* if I/O is asserted, assert the new data on the target's ! 854: behalf: */ ! 855: if (control & TME_SCSI_SIGNAL_I_O) { ! 856: data = *(dma_out->tme_scsi_dma_out); ! 857: dma_target->tme_scsi_connection_int_data = data; ! 858: again = TRUE; ! 859: bus_changed = TRUE; ! 860: } ! 861: } ! 862: } ! 863: 1.1 root 864: /* if I/O is true, read the data, else 865: write the data: */ 866: if (control & TME_SCSI_SIGNAL_I_O) { 867: *dma->tme_scsi_dma_in = data; 868: } 869: else { 870: dma_initiator->tme_scsi_connection_int_data 871: = *(dma->tme_scsi_dma_out); 872: } 873: 874: /* assert ACK on the initiator's behalf: */ 875: dma_initiator->tme_scsi_connection_int_control 876: |= TME_SCSI_SIGNAL_ACK; 877: again = TRUE; 878: bus_changed = TRUE; 879: 880: /* advance to step one: */ 881: dma_initiator->tme_scsi_connection_int_sequence_step = 1; 882: break; 883: 884: /* "If I/O is true (transfer to the initiator)... [after] 885: REQ is false the initiator shall then negate ACK." 886: 887: "If I/O is false (transfer to the target)... [when] 888: REQ becomes false at the initiator, the initiator may 889: change or release DB(7-0,P) and shall negate ACK." */ 890: case 1: 891: if (control & TME_SCSI_SIGNAL_REQ) { 892: break; 893: } 894: 1.1.1.3 ! root 895: /* unless the initiator wants ACK held: */ ! 896: if ((dma_initiator->tme_scsi_connection_int_actions_waiting ! 897: & TME_SCSI_ACTION_DMA_INITIATOR_HOLD_ACK) ! 898: != TME_SCSI_ACTION_DMA_INITIATOR_HOLD_ACK) { ! 899: ! 900: /* negate ACK on the initiator's behalf: */ ! 901: dma_initiator->tme_scsi_connection_int_control ! 902: &= ~TME_SCSI_SIGNAL_ACK; ! 903: again = TRUE; ! 904: bus_changed = TRUE; ! 905: } 1.1 root 906: 907: /* if the DMA has been exhausted, callout a cycle on this 908: device: */ 909: if (control & TME_SCSI_SIGNAL_I_O) { 910: dma->tme_scsi_dma_in++; 911: } 912: else { 913: dma->tme_scsi_dma_out++; 914: } 915: if (--dma->tme_scsi_dma_resid == 0) { 916: dma_initiator->tme_scsi_connection_int_callout_flags 917: |= TME_SCSI_BUS_CALLOUT_CYCLE; 1.1.1.3 ! root 918: dma_initiator->tme_scsi_connection_int_actions_taken ! 919: |= dma_initiator->tme_scsi_connection_int_actions_waiting; 1.1.1.2 root 920: dma_initiator->tme_scsi_connection_int_actions_waiting 921: = TME_SCSI_ACTION_NONE; 1.1 root 922: new_callouts |= TME_SCSI_BUS_CALLOUT_CYCLE; 923: } 924: 925: /* otherwise, advance to step zero: */ 926: else { 927: dma_initiator->tme_scsi_connection_int_sequence_step = 0; 928: } 929: break; 930: 931: default: 932: assert (FALSE); 933: } 934: 935: /* if the bus is being reset: */ 936: if (control & TME_SCSI_SIGNAL_RST) { 937: 938: /* negate all signals on the initiator's behalf: */ 1.1.1.2 root 939: dma_initiator->tme_scsi_connection_int_control = 0; 940: dma_initiator->tme_scsi_connection_int_data = 0; 1.1 root 941: again = TRUE; 942: bus_changed = TRUE; 943: 944: /* callout a cycle on this device: */ 1.1.1.2 root 945: dma_initiator->tme_scsi_connection_int_callout_flags 1.1 root 946: |= TME_SCSI_BUS_CALLOUT_CYCLE; 1.1.1.2 root 947: dma_initiator->tme_scsi_connection_int_actions_waiting 948: = TME_SCSI_ACTION_NONE; 949: dma_initiator->tme_scsi_connection_int_actions_taken 950: = TME_SCSI_ACTION_NONE; 951: dma_initiator->tme_scsi_connection_int_events_triggered 952: = TME_SCSI_EVENT_BUS_RESET; 1.1 root 953: new_callouts 954: |= TME_SCSI_BUS_CALLOUT_CYCLE; 955: } 956: } 957: } 958: 959: /* make any needed callouts: */ 960: _tme_scsi_bus_callout(scsi_bus, new_callouts); 961: 962: /* unlock the mutex: */ 963: tme_mutex_unlock(&scsi_bus->tme_scsi_bus_mutex); 964: 965: return (TME_OK); 966: } 967: 968: /* this scores a new connection: */ 969: static int 970: _tme_scsi_bus_connection_score(struct tme_connection *conn, 971: unsigned int *_score) 972: { 973: struct tme_scsi_bus *scsi_bus; 1.1.1.2 root 974: struct tme_scsi_connection *conn_other; 1.1 root 975: 976: /* both sides must be SCSI connections: */ 977: assert (conn->tme_connection_type == TME_CONNECTION_SCSI); 978: assert (conn->tme_connection_other->tme_connection_type == TME_CONNECTION_SCSI); 979: 980: /* recover our bus and the other internal connection side: */ 981: scsi_bus = conn->tme_connection_element->tme_element_private; 1.1.1.2 root 982: conn_other = (struct tme_scsi_connection *) conn->tme_connection_other; 1.1 root 983: 984: /* you cannot connect a bus to a bus: */ 1.1.1.2 root 985: /* XXX we need a way to distinguish a bus from a device: */ 1.1 root 986: *_score 1.1.1.2 root 987: = 1; 1.1 root 988: return (TME_OK); 989: } 990: 991: /* this makes a new connection: */ 992: static int 993: _tme_scsi_bus_connection_make(struct tme_connection *conn, 994: unsigned int state) 995: { 996: struct tme_scsi_bus *scsi_bus; 997: struct tme_scsi_connection_int *conn_int; 998: 999: /* both sides must be SCSI connections: */ 1000: assert (conn->tme_connection_type == TME_CONNECTION_SCSI); 1001: assert (conn->tme_connection_other->tme_connection_type == TME_CONNECTION_SCSI); 1002: 1003: /* recover our bus and our internal connection side: */ 1004: scsi_bus = conn->tme_connection_element->tme_element_private; 1005: conn_int = (struct tme_scsi_connection_int *) conn; 1006: 1007: /* we're always set up to answer calls across the connection, 1008: so we only have to do work when the connection has gone full, 1009: namely taking the other side of the connection: */ 1010: if (state == TME_CONNECTION_FULL) { 1011: 1012: /* lock the mutex: */ 1013: tme_mutex_lock(&scsi_bus->tme_scsi_bus_mutex); 1014: 1015: /* add this connection to our list of connections: */ 1016: conn->tme_connection_next = scsi_bus->tme_scsi_bus_connections; 1017: scsi_bus->tme_scsi_bus_connections = conn; 1018: 1019: /* unlock the mutex: */ 1020: tme_mutex_unlock(&scsi_bus->tme_scsi_bus_mutex); 1021: } 1022: 1023: return (TME_OK); 1024: } 1025: 1026: /* this breaks a connection: */ 1027: static int 1028: _tme_scsi_bus_connection_break(struct tme_connection *conn, 1029: unsigned int state) 1030: { 1031: abort(); 1032: } 1033: 1034: /* this returns the new connections possible: */ 1035: static int 1036: _tme_scsi_bus_connections_new(struct tme_element *element, 1037: const char * const *args, 1038: struct tme_connection **_conns, 1039: char **_output) 1040: { 1041: struct tme_scsi_connection_int *conn_int; 1042: struct tme_scsi_connection *conn_scsi; 1043: struct tme_connection *conn; 1044: 1045: /* we never take any arguments: */ 1046: if (args[1] != NULL) { 1047: tme_output_append_error(_output, 1048: "%s %s, ", 1049: args[1], 1050: _("unexpected")); 1051: return (EINVAL); 1052: } 1053: 1054: /* create our side of a SCSI connection: */ 1055: conn_int = tme_new0(struct tme_scsi_connection_int, 1); 1056: conn_scsi = &conn_int->tme_scsi_connection_int; 1057: conn = &conn_scsi->tme_scsi_connection; 1058: 1059: /* fill in the generic connection: */ 1060: conn->tme_connection_next = *_conns; 1061: conn->tme_connection_type = TME_CONNECTION_SCSI; 1062: conn->tme_connection_score = _tme_scsi_bus_connection_score; 1063: conn->tme_connection_make = _tme_scsi_bus_connection_make; 1064: conn->tme_connection_break = _tme_scsi_bus_connection_break; 1065: 1066: /* fill in the SCSI connection: */ 1067: conn_scsi->tme_scsi_connection_cycle = _tme_scsi_bus_cycle; 1068: 1069: /* return the connection side possibility: */ 1070: *_conns = conn; 1071: return (TME_OK); 1072: } 1073: 1074: /* this creates a new SCSI bus element: */ 1075: TME_ELEMENT_SUB_NEW_DECL(tme_scsi,bus) { 1076: struct tme_scsi_bus *scsi_bus; 1077: int usage; 1078: int arg_i; 1079: 1080: /* check our arguments: */ 1081: arg_i = 1; 1082: usage = FALSE; 1083: 1084: /* loop reading our arguments: */ 1085: for (;;) { 1086: 1087: if (0) { 1088: } 1089: 1090: /* if we've run out of arguments: */ 1091: else if (args[arg_i + 0] == NULL) { 1092: 1093: break; 1094: } 1095: 1096: /* this is a bad argument: */ 1097: else { 1098: tme_output_append_error(_output, 1099: "%s %s", 1100: args[arg_i], 1101: _("unexpected")); 1102: usage = TRUE; 1103: break; 1104: } 1105: } 1106: 1107: if (usage) { 1108: tme_output_append_error(_output, 1109: "%s %s", 1110: _("usage:"), 1111: args[0]); 1112: return (EINVAL); 1113: } 1114: 1115: /* allocate and initialize the new SCSI bus: */ 1116: scsi_bus = tme_new0(struct tme_scsi_bus, 1); 1117: tme_mutex_init(&scsi_bus->tme_scsi_bus_mutex); 1118: 1119: /* fill the element: */ 1120: element->tme_element_private = scsi_bus; 1121: element->tme_element_connections_new = _tme_scsi_bus_connections_new; 1122: 1123: return (TME_OK); 1124: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.