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

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

unix.superglobalmegacorp.com

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