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