Annotation of Gnu-Mach/scsi/scsi.c, revision 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.