Annotation of Gnu-Mach/scsi/scsi.c, revision 1.1.1.1

1.1       root        1: /* 
                      2:  * Mach Operating System
                      3:  * Copyright (c) 1993-1989 Carnegie Mellon University
                      4:  * All Rights Reserved.
                      5:  * 
                      6:  * Permission to use, copy, modify and distribute this software and its
                      7:  * documentation is hereby granted, provided that both the copyright
                      8:  * notice and this permission notice appear in all copies of the
                      9:  * software, derivative works or modified versions, and any portions
                     10:  * thereof, and that both notices appear in supporting documentation.
                     11:  * 
                     12:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
                     13:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
                     14:  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
                     15:  * 
                     16:  * Carnegie Mellon requests users of this software to return to
                     17:  * 
                     18:  *  Software Distribution Coordinator  or  [email protected]
                     19:  *  School of Computer Science
                     20:  *  Carnegie Mellon University
                     21:  *  Pittsburgh PA 15213-3890
                     22:  * 
                     23:  * any improvements or extensions that they make and grant Carnegie Mellon
                     24:  * the rights to redistribute these changes.
                     25:  */
                     26: /*
                     27:  *     File: scsi.c
                     28:  *     Author: Alessandro Forin, Carnegie Mellon University
                     29:  *     Date:   9/90
                     30:  *
                     31:  *     Middle layer of the SCSI driver: chip independent functions
                     32:  *     This file contains Controller and Device-independent functions
                     33:  */
                     34: 
                     35: #include <scsi.h>
                     36: 
                     37: #if    NSCSI > 0
                     38: #include <platforms.h>
                     39: 
                     40: #include <machine/machspl.h>           /* spl definitions */
                     41: 
                     42: #include <mach/std_types.h>
                     43: #include <sys/types.h>
                     44: #include <scsi/compat_30.h>
                     45: 
                     46: #include <chips/busses.h>
                     47: #include <scsi/scsi.h>
                     48: #include <scsi/scsi2.h>
                     49: #include <scsi/scsi_defs.h>
                     50: #include <machine/machspl.h>
                     51: 
                     52: 
                     53: 
                     54: #ifdef VAXSTATION
                     55: /* We run some of this code on the interrupt stack */
                     56: #undef spl0
                     57: #define        spl0()  spl1()
                     58: #endif /*VAXSTATION*/
                     59: 
                     60: /*
                     61:  *     Overall driver state
                     62:  */
                     63: 
                     64: target_info_t  scsi_target_data[NSCSI*8];      /* per target state */
                     65: scsi_softc_t   scsi_softc_data[NSCSI];         /* per HBA state */
                     66: scsi_softc_t   *scsi_softc[NSCSI];             /* quick access&checking */
                     67: 
                     68: /*
                     69:  * If a specific target should NOT be asked to go synchronous
                     70:  * then its bit in this bitmap should be set. Each SCSI controller
                     71:  * (Host Bus Adapter) can hold at most 8 targets --> use one
                     72:  * byte per controller.  A bit set to one means NO synchronous.
                     73:  * Patch with adb if necessary.
                     74:  */
                     75: unsigned char  scsi_no_synchronous_xfer[NSCSI];
                     76: 
                     77: /*
                     78:  * For certain targets it is wise to use the long form of the
                     79:  * read/write commands even if their capacity would not necessitate
                     80:  * it.  Same as above for usage.
                     81:  */
                     82: unsigned char  scsi_use_long_form[NSCSI];
                     83: 
                     84: 
                     85: /*
                     86:  * Control over disconnect-reconnect mode.
                     87:  */
                     88: unsigned char  scsi_might_disconnect[NSCSI] =  /* do it if deemed appropriate */
                     89:                { 0xff, 0xff, 0xff, 0xff, 0xff};/* Fix by hand viz NSCSI */
                     90: unsigned char  scsi_should_disconnect[NSCSI] = /* just do it */
                     91:                { 0,};
                     92: unsigned char  scsi_initiator_id[NSCSI] =      /* our id on the bus(ses) */
                     93:                { 7, 7, 7, 7, 7};
                     94: 
                     95: /*
                     96:  * Miscellaneus config
                     97:  */
                     98: boolean_t      scsi_exabyte_filemarks = FALSE; /* use short filemarks */
                     99: int            scsi_watchdog_period = 10;      /* but exabyte needs >=30 for bspace */
                    100: int            scsi_delay_after_reset = 1000000;/* microseconds */
                    101: boolean_t      scsi_no_automatic_bbr = FALSE;  /* revector bad blocks automatically */
                    102: 
                    103: #ifdef MACH_KERNEL
                    104: #else
                    105: /* This covers Exabyte's max record size */
                    106: unsigned int   scsi_per_target_virtual = 256*1024;
                    107: #endif MACH_KERNEL
                    108: 
                    109: 
                    110: /*
                    111:  * Device-specific operations are switched off this table
                    112:  */
                    113: 
                    114: extern char
                    115:                *scdisk_name(), *sctape_name(), *scprt_name(),
                    116:                *sccpu_name(), *scworm_name(), *sccdrom_name(),
                    117:                *scscn_name(), *scmem_name(), *scjb_name(), *sccomm_name();
                    118: extern void
                    119:                sctape_optimize();
                    120: extern scsi_ret_t
                    121:                scdisk_open(), sctape_open(), sctape_close(),
                    122:                sccomm_open(), sccomm_close();
                    123: extern int
                    124:                scdisk_strategy(), sctape_strategy(), sccpu_strategy(),
                    125:                sccomm_strategy();
                    126: extern void
                    127:                scdisk_start(), sctape_start(), sccpu_start(), sccomm_start();
                    128: 
                    129: extern io_return_t
                    130:                scdisk_set_status(), scdisk_get_status(),
                    131:                sctape_set_status(), sctape_get_status(),
                    132:                sccomm_set_status(), sccomm_get_status();
                    133: 
                    134: scsi_devsw_t   scsi_devsw[] = {
                    135: 
                    136: /* SCSI_DISK */                { scdisk_name, SCSI_OPTIMIZE_NULL,
                    137:                          scdisk_open, SCSI_CLOSE_NULL,
                    138:                          scdisk_strategy, scdisk_start,
                    139:                          scdisk_get_status, scdisk_set_status },
                    140: 
                    141: /* SCSI_TAPE */                { sctape_name, sctape_optimize,
                    142:                          sctape_open, sctape_close,
                    143:                          sctape_strategy, sctape_start,
                    144:                          sctape_get_status, sctape_set_status },
                    145: 
                    146: /* SCSI_PRINTER */     { scprt_name, SCSI_OPTIMIZE_NULL, /*XXX*/},
                    147: 
                    148: /* SCSI_CPU */         { sccpu_name, SCSI_OPTIMIZE_NULL,
                    149:                          SCSI_OPEN_NULL, SCSI_CLOSE_NULL,
                    150:                          sccpu_strategy, sccpu_start,},
                    151: 
                    152: /* SCSI_WORM */                { scworm_name, SCSI_OPTIMIZE_NULL,
                    153:                          scdisk_open, SCSI_CLOSE_NULL,
                    154:                          scdisk_strategy, scdisk_start,
                    155:                          scdisk_get_status, scdisk_set_status },
                    156: 
                    157: /* SCSI_CDROM */       { sccdrom_name, SCSI_OPTIMIZE_NULL,
                    158:                          scdisk_open, SCSI_CLOSE_NULL,
                    159:                          scdisk_strategy, scdisk_start,
                    160:                          scdisk_get_status, scdisk_set_status },
                    161: /* scsi2 */
                    162: /* SCSI_SCANNER */     { scscn_name, SCSI_OPTIMIZE_NULL, /*XXX*/ },
                    163: 
                    164: /* SCSI_MEMORY */      { scmem_name, SCSI_OPTIMIZE_NULL,
                    165:                          scdisk_open, SCSI_CLOSE_NULL,
                    166:                          scdisk_strategy, scdisk_start,
                    167:                          scdisk_get_status, scdisk_set_status },
                    168: 
                    169: /* SCSI_J_BOX */       { scjb_name, SCSI_OPTIMIZE_NULL, /*XXX*/ },
                    170: 
                    171: /* SCSI_COMM */                { sccomm_name, SCSI_OPTIMIZE_NULL,
                    172: #if    (NCENDATA>0)
                    173:                          sccomm_open, sccomm_close,
                    174:                          sccomm_strategy, sccomm_start,
                    175:                          sccomm_get_status, sccomm_set_status
                    176: #endif
                    177:                        },
                    178:                        0
                    179: };
                    180: 
                    181: /*
                    182:  * Allocation routines for state structures
                    183:  */
                    184: scsi_softc_t *
                    185: scsi_master_alloc(unit, hw)
                    186:        unsigned unit;
                    187:        char    *hw;
                    188: {
                    189:        scsi_softc_t    *sc;
                    190: 
                    191:        if (unit < NSCSI) {
                    192:                sc = &scsi_softc_data[unit];
                    193:                scsi_softc[unit] = sc;
                    194:                sc->masterno = unit;
                    195:                sc->hw_state = hw;
                    196:                return sc;
                    197:        }
                    198:        return 0;
                    199: }
                    200: 
                    201: target_info_t *
                    202: scsi_slave_alloc(unit, slave, hw)
                    203:        unsigned unit, slave;
                    204:        char    *hw;
                    205: {
                    206:        target_info_t   *tgt;
                    207: 
                    208:        tgt = &scsi_target_data[(unit<<3) + slave];
                    209:        tgt->hw_state = hw;
                    210:        tgt->dev_ops = 0;       /* later */
                    211:        tgt->target_id = slave;
                    212:        tgt->masterno = unit;
                    213:        tgt->block_size = 1;    /* default */
                    214:        tgt->flags = TGT_ALIVE;
                    215:        tgt->sync_period = 0;
                    216:        tgt->sync_offset = 0;
                    217:        simple_lock_init(&tgt->target_lock);
                    218: 
                    219:        scsi_softc[unit]->target[slave] = tgt;
                    220:        return tgt;
                    221: }
                    222: 
                    223: void
                    224: zero_ior(
                    225:        io_req_t        ior )
                    226: {
                    227:        ior->io_next = ior->io_prev = 0;
                    228:        ior->io_count = 0;
                    229:        ior->io_op = IO_INTERNAL;
                    230:        ior->io_error = 0;
                    231: }
                    232: 
                    233: /*
                    234:  * Slave routine:
                    235:  *     See if the slave description (controller, unit, ..)
                    236:  *     matches one of the slaves found during probe
                    237:  *
                    238:  * Implementation:
                    239:  *     Send out an INQUIRY command to see what sort of device
                    240:  *     the slave is.
                    241:  * Notes:
                    242:  *     At this time the driver is fully functional and works
                    243:  *     off interrupts.
                    244:  * TODO:
                    245:  *     The SCSI2 spec says what exactly must happen: see F.2.3
                    246:  */
                    247: int scsi_slave( ui, reg)
                    248:        struct bus_device       *ui;
                    249:        unsigned                reg;
                    250: {
                    251:        scsi_softc_t            *sc = scsi_softc[(unsigned char)ui->ctlr];
                    252:        target_info_t           *tgt = sc->target[(unsigned char)ui->slave];
                    253:        scsi2_inquiry_data_t    *inq;
                    254:        int                     scsi_std;
                    255:        int                     ptype, s;
                    256: 
                    257:        if (!tgt || !(tgt->flags & TGT_ALIVE))
                    258:                return 0;
                    259: 
                    260:        /* Might have scanned already */
                    261:        if (tgt->dev_ops)
                    262:                goto out;
                    263: 
                    264: #ifdef SCSI2
                    265:        This is what should happen:
                    266:        - for all LUNs 
                    267:                INQUIRY
                    268:                scsi_verify_state (see)
                    269:                scsi_initialize (see)
                    270: #endif SCSI2
                    271: 
                    272:        tgt->unit_no = ui->slave;       /* incorrect, but needed early */
                    273: 
                    274:        s = spl0();     /* we need interrupts */
                    275: 
                    276:        if (BGET(scsi_no_synchronous_xfer,(unsigned char)sc->masterno,tgt->target_id))
                    277:                tgt->flags |= TGT_DID_SYNCH;
                    278: 
                    279:        /*
                    280:         * Ok, it is time to see what type of device this is,
                    281:         * send an INQUIRY cmd and wait till done.
                    282:         * Possibly do the synch negotiation here.
                    283:         */
                    284:        scsi_inquiry(tgt, SCSI_INQ_STD_DATA);
                    285: 
                    286:        inq = (scsi2_inquiry_data_t*)tgt->cmd_ptr;
                    287:        ptype = inq->periph_type;
                    288: 
                    289:        switch (ptype) {
                    290:        case SCSI_CDROM :
                    291:                tgt->flags |= TGT_READONLY;
                    292:                /* fall through */
                    293:        case SCSI_DISK :
                    294:        case SCSI_TAPE :
                    295:        case SCSI_PRINTER :
                    296:        case SCSI_CPU :
                    297:        case SCSI_WORM :
                    298:        case SCSI_SCANNER :
                    299:        case SCSI_MEMORY :
                    300:        case SCSI_J_BOX :
                    301:        case SCSI_COMM :
                    302: /*     case SCSI_PREPRESS1 : reserved, really
                    303:        case SCSI_PREPRESS2 :   */
                    304:                tgt->dev_ops = &scsi_devsw[ptype];
                    305:                break;
                    306:        default:
                    307:                printf("scsi%d: %s %d (x%x). ", ui->ctlr,
                    308:                       "Unsupported device type at SCSI id", ui->slave,
                    309:                        inq->periph_type);
                    310:                scsi_print_inquiry((scsi2_inquiry_data_t*)inq,
                    311:                        SCSI_INQ_STD_DATA, 0);
                    312:                tgt->flags = 0;
                    313:                splx(s);
                    314:                return 0;
                    315:        }
                    316: 
                    317:        if (inq->rmb)
                    318:                tgt->flags |= TGT_REMOVABLE_MEDIA;
                    319: 
                    320:        /*
                    321:         * Tell the user we know this target, then see if we
                    322:         * can be a bit smart about it.
                    323:         */
                    324:        scsi_print_inquiry((scsi2_inquiry_data_t*)inq,
                    325:                SCSI_INQ_STD_DATA, tgt->tgt_name);
                    326:        if (scsi_debug)
                    327:                scsi_print_inquiry((scsi2_inquiry_data_t*)inq,
                    328:                        SCSI_INQ_STD_DATA, 0);
                    329: 
                    330:        /*
                    331:         * The above says if it currently behaves as a scsi2,
                    332:         * however scsi1 might just be the default setting.
                    333:         * The spec say that even if in scsi1 mode the target
                    334:         * should answer to the full scsi2 inquiry spec.
                    335:         */
                    336:        scsi_std = (inq->ansi == 2 || inq->response_fmt == 2) ? 2 : 1;
                    337: #if nosey
                    338:        if (scsi_std == 2) {
                    339:                unsigned char   supp_pages[256], i;
                    340:                scsi2_impl_opdef_page_t *impl;
                    341: 
                    342:                scsi_inquiry(tgt, SCSI_INQ_SUPP_PAGES);
                    343:                impl = (scsi2_impl_opdef_page_t *)inq;
                    344:                npages = impl->page_len - 2;
                    345:                bcopy(impl->supp_opdef, supp_pages, npages);
                    346: 
                    347:                for (i = 0; i < npages; i++) {
                    348:                        scsi_inquiry(tgt, supp_pages[i]);
                    349:                        scsi_print_inquiry(inq, supp_pages[i], 0);
                    350:                }
                    351:        }
                    352: 
                    353:        if (scsi_std == 2) {
                    354:                scsi2_impl_opdef_page_t *impl;
                    355:                int i;
                    356: 
                    357:                scsi_inquiry(tgt, SCSI_INQ_IMPL_OPDEF);
                    358:                impl = (scsi2_impl_opdef_page_t *)inq;
                    359:                for (i = 0; i < impl->page_len - 2; i++)
                    360:                        if (impl->supp_opdef[i] == SCSI2_OPDEF) {
                    361:                                scsi_change_definition(tgt, SCSI2_OPDEF);
                    362:                                /* if success .. */
                    363:                                        tgt->flags |= TGT_SCSI_2_MODE;
                    364:                                break;
                    365:                        }
                    366:        }
                    367: #endif nosey
                    368: 
                    369:        splx(s);
                    370: out:
                    371:        return (strcmp(ui->name, (*tgt->dev_ops->driver_name)(TRUE)) == 0);
                    372: }
                    373: 
                    374: #ifdef SCSI2
                    375: scsi_verify_state(...)
                    376: {
                    377: verify_state: send test_unit_ready up to 3 times, each time it fails
                    378: (with check condition) send a requeste_sense. It is ok to get UNIT ATTENTION 
                    379: the first time only, NOT READY the second, only GOOD the last time.
                    380: If you get BUSY or RESERVATION CONFLICT retry.
                    381: }
                    382: 
                    383: scsi_initialize(...)
                    384: {
                    385: 
                    386: initialize: send start_unit with immed=0 (->disconnect), if fails
                    387: with check condition send requeste_sense and if "illegal request"
                    388: proceed anyways. Retry on BUSY.
                    389: Do a verify_state, then
                    390: disks:
                    391:        - mode_sense (current) if ANSI2 or needed by vendor (!!!!)
                    392:          and if check-condition&illegal-request goto capacity
                    393:        - mode_sense (changeable)
                    394:        - if needed do a mode_select (yes, 512)
                    395:        - read_capacity
                    396: tapes:
                    397: 
                    398: }
                    399: #endif SCSI2
                    400: 
                    401: /*
                    402:  * Attach routine:
                    403:  *     Fill in all the relevant per-slave data and make
                    404:  *     the slave operational.
                    405:  *
                    406:  * Implementation:
                    407:  *     Get target's status, start the unit and then
                    408:  *     switch off to device-specific functions to gather
                    409:  *     as much info as possible about the slave.
                    410:  */
                    411: void scsi_attach(ui)
                    412:        register struct bus_device *ui;
                    413: {
                    414:        scsi_softc_t            *sc = scsi_softc[ui->mi->unit];
                    415:        target_info_t           *tgt = sc->target[(unsigned char)ui->slave];
                    416:        int                     i;
                    417:        spl_t                   s;
                    418: 
                    419:        printf(" (%s %s) ", (*tgt->dev_ops->driver_name)(FALSE),tgt->tgt_name);
                    420: 
                    421:        if (tgt->flags & TGT_US) {
                    422:                printf(" [this cpu]");
                    423:                return;
                    424:        }
                    425: 
                    426:        s = spl0();
                    427: 
                    428:        /* sense return from inquiry */
                    429:        scsi_request_sense(tgt, 0, 0);
                    430: 
                    431:        /*
                    432:         * Do this twice, certain targets need it
                    433:         */
                    434:        if (tgt->dev_ops != &scsi_devsw[SCSI_CPU]) {
                    435:                (void) scsi_start_unit(tgt, SCSI_CMD_SS_START, 0);
                    436:                i = 0;
                    437:                while (scsi_start_unit(tgt, SCSI_CMD_SS_START, 0) == SCSI_RET_RETRY) {
                    438:                        if (i++ == 5)
                    439:                                printf(".. not yet online ..");
                    440:                        delay(1000000);
                    441:                        if (i == 60) {
                    442:                                printf(" seems hopeless.");
                    443:                                break;
                    444:                        }
                    445:                }
                    446:        }
                    447: 
                    448:        /*
                    449:         * See if it is up and about
                    450:         */
                    451:        scsi_test_unit_ready(tgt, 0);
                    452: 
                    453:        if (tgt->dev_ops->optimize != SCSI_OPTIMIZE_NULL)
                    454:                (*tgt->dev_ops->optimize)(tgt);
                    455: 
                    456:        tgt->flags |= TGT_FULLY_PROBED;
                    457: 
                    458:        splx(s);
                    459: }
                    460: 
                    461: /*
                    462:  * Probe routine:
                    463:  *     See if a device answers.  Used AFTER autoconf.
                    464:  *
                    465:  * Implementation:
                    466:  *     First ask the HBA to see if anyone is there at all, then
                    467:  *     call the scsi_slave and scsi_attach routines with a fake ui.
                    468:  */
                    469: boolean_t
                    470: scsi_probe( sc, tgt_ptr, target_id, ior)
                    471:        scsi_softc_t            *sc;
                    472:        target_info_t           **tgt_ptr;
                    473:        int                     target_id;
                    474:        io_req_t                ior;
                    475: {
                    476:        struct bus_device       ui;
                    477:        target_info_t           *tgt;
                    478: 
                    479:        if (!sc->probe || target_id > 7 || target_id == sc->initiator_id)
                    480:                return FALSE;   /* sanity */
                    481: 
                    482:        if (sc->target[target_id] == 0)
                    483:                scsi_slave_alloc( sc->masterno, target_id, sc->hw_state);
                    484:        tgt = sc->target[target_id];
                    485:        tgt->flags = 0;/* we donno yet */
                    486:        tgt->dev_ops = 0;
                    487: 
                    488:        /* mildly enquire */
                    489:        if (!(sc->probe)(tgt, ior))
                    490:                goto fail;
                    491: 
                    492:        /* There is something there, see what it is */
                    493:        bzero(&ui, sizeof(ui));
                    494:        ui.ctlr = sc->masterno;
                    495:        ui.unit =
                    496:        ui.slave = target_id;
                    497:        ui.name = "";
                    498: 
                    499:        /* this fails on the name for sure */
                    500:        (void) scsi_slave( &ui, 0 /* brrrr */);
                    501:        if ((tgt->flags & TGT_ALIVE) == 0)
                    502:                goto fail;
                    503: 
                    504:        {
                    505:                struct bus_ctlr mi;
                    506: 
                    507:                mi.unit = sc->masterno;
                    508:                ui.mi = &mi;
                    509:                printf("%s at slave %d ",
                    510:                        (*tgt->dev_ops->driver_name)(TRUE), target_id);
                    511:                scsi_attach(&ui);
                    512:        }
                    513: 
                    514:        *tgt_ptr = tgt;
                    515:        return TRUE;
                    516: fail:
                    517:        tgt->flags = 0;
                    518:        return FALSE;
                    519: }
                    520: 
                    521: 
                    522: /*
                    523:  * Watchdog routine:
                    524:  *     Issue a SCSI bus reset if a target holds up the
                    525:  *     bus for too long.
                    526:  *
                    527:  * Implementation:
                    528:  *     Each HBA that wants to use this should have a
                    529:  *     watchdog_t structure at the head of its hardware
                    530:  *     descriptor.  This variable is set by this periodic
                    531:  *     routine and reset on bus activity. If it is not reset on
                    532:  *     time (say some ten seconds or so) we reset the
                    533:  *     SCSI bus.
                    534:  * NOTE:
                    535:  *     An HBA must be ready to accept bus reset interrupts
                    536:  *     properly in order to use this.
                    537:  */
                    538: void scsi_watchdog(hw)
                    539:        watchdog_t      *hw;
                    540: {
                    541:        spl_t           s = splbio();
                    542: 
                    543:        switch (hw->watchdog_state) {
                    544:        case SCSI_WD_EXPIRED:
                    545: 
                    546:                /* double check first */
                    547:                if (hw->nactive == 0) {
                    548:                        hw->watchdog_state = SCSI_WD_INACTIVE;
                    549:                        break;
                    550:                }
                    551:                if (scsi_debug)
                    552:                        printf("SCSI Watchdog expired\n");
                    553:                hw->watchdog_state = SCSI_WD_INACTIVE;
                    554:                (*hw->reset)(hw);
                    555:                break;
                    556: 
                    557:        case SCSI_WD_ACTIVE:
                    558: 
                    559:                hw->watchdog_state = SCSI_WD_EXPIRED;
                    560:                break;
                    561: 
                    562:        case SCSI_WD_INACTIVE:
                    563: 
                    564:                break;
                    565:        }
                    566: 
                    567:        /* do this here, fends against powered down devices */
                    568:        if (scsi_watchdog_period != 0)
                    569:            timeout((int(*)())scsi_watchdog, (char*)hw, scsi_watchdog_period * hz);
                    570: 
                    571:        splx(s);
                    572: }
                    573: 
                    574: 
                    575: /*
                    576:  * BusReset Notification:
                    577:  *     Called when the HBA sees a BusReset interrupt
                    578:  *
                    579:  * Implementation:
                    580:  *     Go through the list of targets, redo the synch
                    581:  *     negotiation, and restart whatever operation was
                    582:  *     in progress for that target.
                    583:  */
                    584: void scsi_bus_was_reset(sc)
                    585:        scsi_softc_t    *sc;
                    586: {
                    587:        register target_info_t  *tgt;
                    588:        int                     i;
                    589:        /*
                    590:         * Redo the synch negotiation
                    591:         */
                    592:        for (i = 0; i < 8; i++) {
                    593:                io_req_t        ior;
                    594:                spl_t           s;
                    595: 
                    596:                if (i == sc->initiator_id)
                    597:                        continue;
                    598:                tgt = sc->target[i];
                    599:                if (!tgt || !(tgt->flags & TGT_ALIVE))
                    600:                        continue;
                    601: 
                    602:                tgt->flags &= ~(TGT_DID_SYNCH|TGT_DISCONNECTED);
                    603: #if 0
                    604:                /* the standard does *not* imply this gets reset too */
                    605:                tgt->sync_period = 0;
                    606:                tgt->sync_offset = 0;
                    607: #endif
                    608: 
                    609:                /*
                    610:                 * retry the synch negotiation
                    611:                 */
                    612:                ior = tgt->ior;
                    613:                tgt->ior = 0;
                    614:                printf(".. tgt %d ", tgt->target_id);
                    615:                if (BGET(scsi_no_synchronous_xfer,(unsigned char)sc->masterno,tgt->target_id))
                    616:                        tgt->flags |= TGT_DID_SYNCH;
                    617:                else {
                    618:                        s = spl0();
                    619:                        scsi_test_unit_ready(tgt, 0);
                    620:                        splx(s);
                    621:                }
                    622:                tgt->ior = ior;
                    623:        }
                    624: 
                    625:        /*
                    626:         * Notify each target of the accident
                    627:         */
                    628:        for (i = 0; i < 8; i++) {
                    629:                if (i == sc->initiator_id)
                    630:                        continue;
                    631:                tgt = sc->target[i];
                    632:                if (!tgt)
                    633:                        continue;
                    634:                tgt->done = SCSI_RET_ABORTED|SCSI_RET_RETRY;
                    635:                if (tgt->ior)
                    636:                        (*tgt->dev_ops->restart)( tgt, TRUE);
                    637:        }
                    638: 
                    639:        printf("%s", " reset complete\n");
                    640: }
                    641: 
                    642: #endif NSCSI > 0

unix.superglobalmegacorp.com

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