Annotation of tme/scsi/scsi-bus.c, revision 1.1.1.3

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.