[BACK]Return to iopsp.c CVS log [TXT][DIR] Up to [local] / sys / dev / i2o

Annotation of sys/dev/i2o/iopsp.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: iopsp.c,v 1.9 2006/11/28 23:59:45 dlg Exp $   */
        !             2: /*     $NetBSD$        */
        !             3:
        !             4: /*-
        !             5:  * Copyright (c) 2000, 2001 The NetBSD Foundation, Inc.
        !             6:  * All rights reserved.
        !             7:  *
        !             8:  * This code is derived from software contributed to The NetBSD Foundation
        !             9:  * by Andrew Doran.
        !            10:  *
        !            11:  * Redistribution and use in source and binary forms, with or without
        !            12:  * modification, are permitted provided that the following conditions
        !            13:  * are met:
        !            14:  * 1. Redistributions of source code must retain the above copyright
        !            15:  *    notice, this list of conditions and the following disclaimer.
        !            16:  * 2. Redistributions in binary form must reproduce the above copyright
        !            17:  *    notice, this list of conditions and the following disclaimer in the
        !            18:  *    documentation and/or other materials provided with the distribution.
        !            19:  * 3. All advertising materials mentioning features or use of this software
        !            20:  *    must display the following acknowledgement:
        !            21:  *        This product includes software developed by the NetBSD
        !            22:  *        Foundation, Inc. and its contributors.
        !            23:  * 4. Neither the name of The NetBSD Foundation nor the names of its
        !            24:  *    contributors may be used to endorse or promote products derived
        !            25:  *    from this software without specific prior written permission.
        !            26:  *
        !            27:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
        !            28:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
        !            29:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
        !            30:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
        !            31:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
        !            32:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
        !            33:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
        !            34:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
        !            35:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
        !            36:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
        !            37:  * POSSIBILITY OF SUCH DAMAGE.
        !            38:  */
        !            39:
        !            40: /*
        !            41:  * Raw SCSI device support for I2O.  IOPs present SCSI devices individually;
        !            42:  * we group them by controlling port.
        !            43:  */
        !            44:
        !            45: #include <sys/param.h>
        !            46: #include <sys/systm.h>
        !            47: #include <sys/kernel.h>
        !            48: #include <sys/device.h>
        !            49: #include <sys/queue.h>
        !            50: #include <sys/proc.h>
        !            51: #include <sys/buf.h>
        !            52: #include <sys/endian.h>
        !            53: #include <sys/malloc.h>
        !            54: #include <sys/scsiio.h>
        !            55: #include <sys/lock.h>
        !            56:
        !            57: #include <machine/bus.h>
        !            58:
        !            59: #include <scsi/scsi_all.h>
        !            60: #include <scsi/scsi_disk.h>
        !            61: #include <scsi/scsi_all.h>
        !            62: #include <scsi/scsiconf.h>
        !            63: #include <scsi/scsi_message.h>
        !            64:
        !            65: #include <dev/i2o/i2o.h>
        !            66: #include <dev/i2o/iopio.h>
        !            67: #include <dev/i2o/iopvar.h>
        !            68: #include <dev/i2o/iopspvar.h>
        !            69:
        !            70: struct cfdriver iopsp_cd = {
        !            71:        NULL, "iopsp", DV_DULL
        !            72: };
        !            73:
        !            74: int    iopsp_match(struct device *, void *, void *);
        !            75: void   iopsp_attach(struct device *, struct device *, void *);
        !            76:
        !            77: struct cfattach iopsp_ca = {
        !            78:        sizeof(struct iopsp_softc), iopsp_match, iopsp_attach
        !            79: };
        !            80:
        !            81: int    iopsp_scsi_cmd(struct scsi_xfer *);
        !            82: void   iopspminphys(struct buf *bp);
        !            83:
        !            84: struct scsi_adapter iopsp_switch = {
        !            85:        iopsp_scsi_cmd, iopspminphys, 0, 0,
        !            86: };
        !            87:
        !            88: struct scsi_device iopsp_dev = {
        !            89:        NULL, NULL, NULL, NULL
        !            90: };
        !            91:
        !            92: void   iopsp_adjqparam(struct device *, int);
        !            93: void   iopsp_intr(struct device *, struct iop_msg *, void *);
        !            94: int    iopsp_rescan(struct iopsp_softc *);
        !            95: int    iopsp_reconfig(struct device *);
        !            96:
        !            97: /*
        !            98:  * Match a supported device.
        !            99:  */
        !           100: int
        !           101: iopsp_match(struct device *parent, void *match, void *aux)
        !           102: {
        !           103:        struct iop_attach_args *ia = aux;
        !           104:        struct {
        !           105:                struct  i2o_param_op_results pr;
        !           106:                struct  i2o_param_read_results prr;
        !           107:                struct  i2o_param_hba_ctlr_info ci;
        !           108:        } __attribute__ ((__packed__)) param;
        !           109:        int rv;
        !           110:
        !           111:        if (ia->ia_class != I2O_CLASS_BUS_ADAPTER_PORT)
        !           112:                return (0);
        !           113:
        !           114:        if ((rv = iop_param_op((struct iop_softc *)parent, ia->ia_tid, NULL, 0,
        !           115:            I2O_PARAM_HBA_CTLR_INFO, &param, sizeof(param)))) {
        !           116: #ifdef I2ODEBUG
        !           117:                printf("iopsp_match: iop_param_op failed, status = %d\n", rv);
        !           118: #endif
        !           119:                return (0);
        !           120:        }
        !           121:
        !           122: #ifdef I2ODEBUG
        !           123:        printf("iopsp_match: bustype = %d\n", param.ci.bustype);
        !           124: #endif
        !           125:
        !           126:        return (param.ci.bustype == I2O_HBA_BUS_SCSI ||
        !           127:            param.ci.bustype == I2O_HBA_BUS_FCA);
        !           128: }
        !           129:
        !           130: /*
        !           131:  * Attach a supported device.
        !           132:  */
        !           133: void
        !           134: iopsp_attach(struct device *parent, struct device *self, void *aux)
        !           135: {
        !           136:        struct iop_softc *iop = (struct iop_softc *)parent;
        !           137:        struct iopsp_softc *sc = (struct iopsp_softc *)self;
        !           138:        struct iop_attach_args *ia = (struct iop_attach_args *)aux;
        !           139:        struct scsibus_attach_args saa;
        !           140:        struct {
        !           141:                struct  i2o_param_op_results pr;
        !           142:                struct  i2o_param_read_results prr;
        !           143:                union {
        !           144:                        struct  i2o_param_hba_ctlr_info ci;
        !           145:                        struct  i2o_param_hba_scsi_ctlr_info sci;
        !           146:                        struct  i2o_param_hba_scsi_port_info spi;
        !           147:                } p;
        !           148:        } __attribute__ ((__packed__)) param;
        !           149:        int fcal, rv;
        !           150: #ifdef I2OVERBOSE
        !           151:        int size;
        !           152: #endif
        !           153:
        !           154:        /* Register us as an initiator. */
        !           155:        sc->sc_ii.ii_dv = self;
        !           156:        sc->sc_ii.ii_intr = iopsp_intr;
        !           157:        sc->sc_ii.ii_flags = 0;
        !           158:        sc->sc_ii.ii_tid = ia->ia_tid;
        !           159:        sc->sc_ii.ii_reconfig = iopsp_reconfig;
        !           160:        sc->sc_ii.ii_adjqparam = iopsp_adjqparam;
        !           161:        iop_initiator_register(iop, &sc->sc_ii);
        !           162:
        !           163:        rv = iop_param_op(iop, ia->ia_tid, NULL, 0, I2O_PARAM_HBA_CTLR_INFO,
        !           164:            &param, sizeof(param));
        !           165:        if (rv != 0) {
        !           166:                printf("%s: unable to get parameters (0x%04x; %d)\n",
        !           167:                    sc->sc_dv.dv_xname, I2O_PARAM_HBA_CTLR_INFO, rv);
        !           168:                goto bad;
        !           169:        }
        !           170:
        !           171:        fcal = (param.p.ci.bustype == I2O_HBA_BUS_FCA);         /* XXX */
        !           172:
        !           173:        /*
        !           174:         * Say what the device is.  If we can find out what the controling
        !           175:         * device is, say what that is too.
        !           176:         */
        !           177:        printf(": SCSI port");
        !           178:        iop_print_ident(iop, ia->ia_tid);
        !           179:        printf("\n");
        !           180:
        !           181:        rv = iop_param_op(iop, ia->ia_tid, NULL, 0,
        !           182:            I2O_PARAM_HBA_SCSI_CTLR_INFO, &param, sizeof(param));
        !           183:        if (rv != 0) {
        !           184:                printf("%s: unable to get parameters (0x%04x; %d)\n",
        !           185:                    sc->sc_dv.dv_xname, I2O_PARAM_HBA_SCSI_CTLR_INFO, rv);
        !           186:                goto bad;
        !           187:        }
        !           188:
        !           189: #ifdef I2OVERBOSE
        !           190:        printf("%s: %d-bit, max sync rate %dMHz, initiator ID %d\n",
        !           191:            sc->sc_dv.dv_xname, param.p.sci.maxdatawidth,
        !           192:            (u_int32_t)letoh64(param.p.sci.maxsyncrate) / 1000,
        !           193:            letoh32(param.p.sci.initiatorid));
        !           194: #endif
        !           195:
        !           196:        sc->sc_link.adapter_softc = sc;
        !           197:        sc->sc_link.adapter = &iopsp_switch;
        !           198:        sc->sc_link.adapter_target = letoh32(param.p.sci.initiatorid);
        !           199:        sc->sc_link.device = &iopsp_dev;
        !           200:        sc->sc_link.openings = 1;
        !           201:        sc->sc_link.adapter_buswidth = fcal?
        !           202:            IOPSP_MAX_FCAL_TARGET : param.p.sci.maxdatawidth;
        !           203:        sc->sc_link.luns = IOPSP_MAX_LUN;
        !           204:
        !           205: #ifdef I2OVERBOSE
        !           206:        /*
        !           207:         * Allocate the target map.  Currently used for informational
        !           208:         * purposes only.
        !           209:         */
        !           210:        size = sc->sc_link.adapter_buswidth * sizeof(struct iopsp_target);
        !           211:        sc->sc_targetmap = malloc(size, M_DEVBUF, M_NOWAIT);
        !           212:        bzero(sc->sc_targetmap, size);
        !           213: #endif
        !           214:
        !           215:        /* Build the two maps, and attach to scsi. */
        !           216:        if (iopsp_reconfig(self) != 0) {
        !           217:                printf("%s: configure failed\n", sc->sc_dv.dv_xname);
        !           218:                goto bad;
        !           219:        }
        !           220:
        !           221:        bzero(&saa, sizeof(saa));
        !           222:        saa.saa_sc_link = &sc->sc_link;
        !           223:
        !           224:        config_found(&sc->sc_dv, &saa, scsiprint);
        !           225:        return;
        !           226:
        !           227:  bad:
        !           228:        iop_initiator_unregister(iop, &sc->sc_ii);
        !           229: }
        !           230:
        !           231: /*
        !           232:  * Scan the LCT to determine which devices we control, and enter them into
        !           233:  * the maps.
        !           234:  */
        !           235: int
        !           236: iopsp_reconfig(struct device *dv)
        !           237: {
        !           238:        struct iopsp_softc *sc = (struct iopsp_softc *)dv;
        !           239:        struct iop_softc *iop = (struct iop_softc *)sc->sc_dv.dv_parent;
        !           240:        struct i2o_lct_entry *le;
        !           241:        struct {
        !           242:                struct  i2o_param_op_results pr;
        !           243:                struct  i2o_param_read_results prr;
        !           244:                struct  i2o_param_scsi_device_info sdi;
        !           245:        } __attribute__ ((__packed__)) param;
        !           246:        u_int tid, nent, i, targ, lun, size, s, rv, bptid;
        !           247:        u_short *tidmap;
        !           248: #ifdef I2OVERBOSE
        !           249:        struct iopsp_target *it;
        !           250:        int syncrate;
        !           251: #endif
        !           252:
        !           253:        /* Anything to do? */
        !           254:        if (iop->sc_chgind == sc->sc_chgind)
        !           255:                return (0);
        !           256:
        !           257:        /*
        !           258:         * Allocate memory for the target/LUN -> TID map.  Use zero to
        !           259:         * denote absent targets (zero is the TID of the I2O executive,
        !           260:         * and we never address that here).
        !           261:         */
        !           262:        size = sc->sc_link.adapter_buswidth * IOPSP_MAX_LUN * sizeof(u_short);
        !           263:        if (!(tidmap = malloc(size, M_DEVBUF, M_NOWAIT)))
        !           264:                return (ENOMEM);
        !           265:        bzero(tidmap, size);
        !           266:
        !           267: #ifdef I2OVERBOSE
        !           268:        for (i = 0; i < sc->sc_link.adapter_buswidth; i++)
        !           269:                sc->sc_targetmap[i].it_flags &= ~IT_PRESENT;
        !           270: #endif
        !           271:
        !           272:        /*
        !           273:         * A quick hack to handle Intel's stacked bus port arrangement.
        !           274:         */
        !           275:        bptid = sc->sc_ii.ii_tid;
        !           276:        nent = iop->sc_nlctent;
        !           277:        for (le = iop->sc_lct->entry; nent != 0; nent--, le++)
        !           278:                if ((letoh16(le->classid) & 4095) ==
        !           279:                    I2O_CLASS_BUS_ADAPTER_PORT &&
        !           280:                    (letoh32(le->usertid) & 4095) == bptid) {
        !           281:                        bptid = letoh16(le->localtid) & 4095;
        !           282:                        break;
        !           283:                }
        !           284:
        !           285:        nent = iop->sc_nlctent;
        !           286:        for (i = 0, le = iop->sc_lct->entry; i < nent; i++, le++) {
        !           287:                if ((letoh16(le->classid) & I2O_CLASS_MASK) !=
        !           288:                    I2O_CLASS_SCSI_PERIPHERAL ||
        !           289:                    ((letoh32(le->usertid) >> 12) & 4095) != bptid)
        !           290:                        continue;
        !           291:                tid = letoh16(le->localtid) & I2O_LCT_ENTRY_TID_MASK;
        !           292:
        !           293:                rv = iop_param_op(iop, tid, NULL, 0, I2O_PARAM_SCSI_DEVICE_INFO,
        !           294:                    &param, sizeof(param));
        !           295:                if (rv != 0) {
        !           296:                        printf("%s: unable to get parameters (0x%04x; %d)\n",
        !           297:                            sc->sc_dv.dv_xname, I2O_PARAM_SCSI_DEVICE_INFO,
        !           298:                            rv);
        !           299:                        continue;
        !           300:                }
        !           301:                targ = letoh32(param.sdi.identifier);
        !           302:                lun = param.sdi.luninfo[1];
        !           303: #if defined(DIAGNOSTIC) || defined(I2ODEBUG)
        !           304:                if (targ >= sc->sc_link.adapter_buswidth ||
        !           305:                    lun >= sc->sc_link.adapter_buswidth) {
        !           306:                        printf("%s: target %d,%d (tid %d): bad target/LUN\n",
        !           307:                            sc->sc_dv.dv_xname, targ, lun, tid);
        !           308:                        continue;
        !           309:                }
        !           310: #endif
        !           311:
        !           312: #ifdef I2OVERBOSE
        !           313:                /*
        !           314:                 * If we've already described this target, and nothing has
        !           315:                 * changed, then don't describe it again.
        !           316:                 */
        !           317:                it = &sc->sc_targetmap[targ];
        !           318:                it->it_flags |= IT_PRESENT;
        !           319:                syncrate = (int)((letoh64(param.sdi.negsyncrate) + 500) / 1000);
        !           320:                if (it->it_width == param.sdi.negdatawidth &&
        !           321:                    it->it_offset == param.sdi.negoffset &&
        !           322:                    it->it_syncrate == syncrate)
        !           323:                        continue;
        !           324:
        !           325:                it->it_width = param.sdi.negdatawidth;
        !           326:                it->it_offset = param.sdi.negoffset;
        !           327:                it->it_syncrate = syncrate;
        !           328:
        !           329:                printf("%s: target %d (tid %d): %d-bit, ", sc->sc_dv.dv_xname,
        !           330:                    targ, tid, it->it_width);
        !           331:                if (it->it_syncrate == 0)
        !           332:                        printf("asynchronous\n");
        !           333:                else
        !           334:                        printf("synchronous at %dMHz, offset 0x%x\n",
        !           335:                            it->it_syncrate, it->it_offset);
        !           336: #endif
        !           337:
        !           338:                /* Ignore the device if it's in use by somebody else. */
        !           339:                if ((letoh32(le->usertid) & 4095) != I2O_TID_NONE) {
        !           340: #ifdef I2OVERBOSE
        !           341:                        if (sc->sc_tidmap == NULL ||
        !           342:                            IOPSP_TIDMAP(sc->sc_tidmap, targ, lun) !=
        !           343:                            IOPSP_TID_INUSE)
        !           344:                                printf("%s: target %d,%d (tid %d): in use by"
        !           345:                                    " tid %d\n", sc->sc_dv.dv_xname,
        !           346:                                    targ, lun, tid,
        !           347:                                    letoh32(le->usertid) & 4095);
        !           348: #endif
        !           349:                        IOPSP_TIDMAP(tidmap, targ, lun) = IOPSP_TID_INUSE;
        !           350:                } else
        !           351:                        IOPSP_TIDMAP(tidmap, targ, lun) = (u_short)tid;
        !           352:        }
        !           353:
        !           354: #ifdef I2OVERBOSE
        !           355:        for (i = 0; i < sc->sc_link.adapter_buswidth; i++)
        !           356:                if ((sc->sc_targetmap[i].it_flags & IT_PRESENT) == 0)
        !           357:                        sc->sc_targetmap[i].it_width = 0;
        !           358: #endif
        !           359:
        !           360:        /* Swap in the new map and return. */
        !           361:        s = splbio();
        !           362:        if (sc->sc_tidmap != NULL)
        !           363:                free(sc->sc_tidmap, M_DEVBUF);
        !           364:        sc->sc_tidmap = tidmap;
        !           365:        splx(s);
        !           366:        sc->sc_chgind = iop->sc_chgind;
        !           367:        return (0);
        !           368: }
        !           369:
        !           370: /*
        !           371:  * Re-scan the bus; to be called from a higher level (e.g. scsi).
        !           372:  */
        !           373: int
        !           374: iopsp_rescan(struct iopsp_softc *sc)
        !           375: {
        !           376:        struct iop_softc *iop;
        !           377:        struct iop_msg *im;
        !           378:        struct i2o_hba_bus_scan mf;
        !           379:        int rv;
        !           380:
        !           381:        iop = (struct iop_softc *)sc->sc_dv.dv_parent;
        !           382:
        !           383:        rv = lockmgr(&iop->sc_conflock, LK_EXCLUSIVE, NULL);
        !           384:        if (rv != 0) {
        !           385: #ifdef I2ODEBUG
        !           386:                printf("iopsp_rescan: unable to acquire lock\n");
        !           387: #endif
        !           388:                return (rv);
        !           389:        }
        !           390:
        !           391:        im = iop_msg_alloc(iop, &sc->sc_ii, IM_WAIT);
        !           392:
        !           393:        mf.msgflags = I2O_MSGFLAGS(i2o_hba_bus_scan);
        !           394:        mf.msgfunc = I2O_MSGFUNC(sc->sc_ii.ii_tid, I2O_HBA_BUS_SCAN);
        !           395:        mf.msgictx = sc->sc_ii.ii_ictx;
        !           396:        mf.msgtctx = im->im_tctx;
        !           397:
        !           398:        rv = iop_msg_post(iop, im, &mf, 5*60*1000);
        !           399:        iop_msg_free(iop, im);
        !           400:        if (rv != 0)
        !           401:                printf("%s: bus rescan failed (error %d)\n",
        !           402:                    sc->sc_dv.dv_xname, rv);
        !           403:
        !           404:        if ((rv = iop_lct_get(iop)) == 0)
        !           405:                rv = iopsp_reconfig(&sc->sc_dv);
        !           406:
        !           407:        lockmgr(&iop->sc_conflock, LK_RELEASE, NULL);
        !           408:        return (rv);
        !           409: }
        !           410:
        !           411: void
        !           412: iopspminphys(bp)
        !           413:        struct buf *bp;
        !           414: {
        !           415:        if (bp->b_bcount > IOP_MAX_XFER)
        !           416:                bp->b_bcount = IOP_MAX_XFER;
        !           417:        minphys(bp);
        !           418: }
        !           419:
        !           420: /*
        !           421:  * Start a SCSI command.
        !           422:  */
        !           423: int
        !           424: iopsp_scsi_cmd(xs)
        !           425:        struct scsi_xfer *xs;
        !           426: {
        !           427:        struct scsi_link *link = xs->sc_link;
        !           428:        struct iopsp_softc *sc = (struct iopsp_softc *)link->adapter_softc;
        !           429:        struct iop_softc *iop = (struct iop_softc *)sc->sc_dv.dv_parent;
        !           430:        struct iop_msg *im;
        !           431:        struct i2o_scsi_scb_exec *mf;
        !           432:        int error, tid, s;
        !           433:        u_int32_t mb[IOP_MAX_MSG_SIZE / sizeof(u_int32_t)];
        !           434:
        !           435:        tid = IOPSP_TIDMAP(sc->sc_tidmap, link->target, link->lun);
        !           436:        if (tid == IOPSP_TID_ABSENT || tid == IOPSP_TID_INUSE) {
        !           437:                xs->error = XS_SELTIMEOUT;
        !           438:                scsi_done(xs);
        !           439:                return (COMPLETE);
        !           440:        }
        !           441:
        !           442:        SC_DEBUG(xs->sc_link, SDEV_DB2, ("iopsp_scsi_cmd: run_xfer\n"));
        !           443:
        !           444:        /* Need to reset the target? */
        !           445:        if ((xs->flags & XS_RESET) != 0) {
        !           446:                if (iop_simple_cmd(iop, tid, I2O_SCSI_DEVICE_RESET,
        !           447:                    sc->sc_ii.ii_ictx, 1, 30*1000) != 0) {
        !           448: #ifdef I2ODEBUG
        !           449:                        printf("%s: reset failed\n",
        !           450:                            sc->sc_dv.dv_xname);
        !           451: #endif
        !           452:                        xs->error = XS_DRIVER_STUFFUP;
        !           453:                } else
        !           454:                        xs->error = XS_NOERROR;
        !           455:
        !           456:                scsi_done(xs);
        !           457:                return (COMPLETE);
        !           458:        }
        !           459:
        !           460: #if defined(I2ODEBUG) || defined(SCSIDEBUG)
        !           461:        if (xs->cmdlen > sizeof(mf->cdb))
        !           462:                panic("%s: CDB too large", sc->sc_dv.dv_xname);
        !           463: #endif
        !           464:
        !           465:        im = iop_msg_alloc(iop, &sc->sc_ii, IM_POLL_INTR |
        !           466:            IM_NOSTATUS | ((xs->flags & SCSI_POLL) != 0 ? IM_POLL : 0));
        !           467:        im->im_dvcontext = xs;
        !           468:
        !           469:        mf = (struct i2o_scsi_scb_exec *)mb;
        !           470:        mf->msgflags = I2O_MSGFLAGS(i2o_scsi_scb_exec);
        !           471:        mf->msgfunc = I2O_MSGFUNC(tid, I2O_SCSI_SCB_EXEC);
        !           472:        mf->msgictx = sc->sc_ii.ii_ictx;
        !           473:        mf->msgtctx = im->im_tctx;
        !           474:        mf->flags = xs->cmdlen | I2O_SCB_FLAG_ENABLE_DISCONNECT |
        !           475:            I2O_SCB_FLAG_SENSE_DATA_IN_MESSAGE;
        !           476:        mf->datalen = xs->datalen;
        !           477:        memcpy(mf->cdb, xs->cmd, xs->cmdlen);
        !           478:
        !           479: #if 0
        !           480:        switch (xs->xs_tag_type) {
        !           481:        case MSG_ORDERED_Q_TAG:
        !           482:                mf->flags |= I2O_SCB_FLAG_ORDERED_QUEUE_TAG;
        !           483:                break;
        !           484:        case MSG_SIMPLE_Q_TAG:
        !           485:                mf->flags |= I2O_SCB_FLAG_SIMPLE_QUEUE_TAG;
        !           486:                break;
        !           487:        case MSG_HEAD_OF_Q_TAG:
        !           488:                mf->flags |= I2O_SCB_FLAG_HEAD_QUEUE_TAG;
        !           489:                break;
        !           490:        default:
        !           491:                break;
        !           492:        }
        !           493: #endif
        !           494:
        !           495:        if (xs->datalen != 0) {
        !           496:                error = iop_msg_map_bio(iop, im, mb, xs->data,
        !           497:                    xs->datalen, (xs->flags & SCSI_DATA_OUT) == 0);
        !           498:                if (error) {
        !           499:                        xs->error = XS_DRIVER_STUFFUP;
        !           500:                        iop_msg_free(iop, im);
        !           501:                        scsi_done(xs);
        !           502:                        return (COMPLETE);
        !           503:                }
        !           504:                if ((xs->flags & SCSI_DATA_IN) == 0)
        !           505:                        mf->flags |= I2O_SCB_FLAG_XFER_TO_DEVICE;
        !           506:                else
        !           507:                        mf->flags |= I2O_SCB_FLAG_XFER_FROM_DEVICE;
        !           508:        }
        !           509:
        !           510:        s = splbio();
        !           511:        sc->sc_curqd++;
        !           512:        splx(s);
        !           513:
        !           514:        if (iop_msg_post(iop, im, mb, xs->timeout)) {
        !           515:                s = splbio();
        !           516:                sc->sc_curqd--;
        !           517:                splx(s);
        !           518:                if (xs->datalen != 0)
        !           519:                        iop_msg_unmap(iop, im);
        !           520:                iop_msg_free(iop, im);
        !           521:                xs->error = XS_DRIVER_STUFFUP;
        !           522:                scsi_done(xs);
        !           523:                return (COMPLETE);
        !           524:        }
        !           525:
        !           526:        return (xs->flags & SCSI_POLL? COMPLETE : SUCCESSFULLY_QUEUED);
        !           527: }
        !           528:
        !           529: #ifdef notyet
        !           530: /*
        !           531:  * Abort the specified I2O_SCSI_SCB_EXEC message and its associated SCB.
        !           532:  */
        !           533: int
        !           534: iopsp_scsi_abort(struct iopsp_softc *sc, int atid, struct iop_msg *aim)
        !           535: {
        !           536:        struct iop_msg *im;
        !           537:        struct i2o_scsi_scb_abort mf;
        !           538:        struct iop_softc *iop;
        !           539:        int rv, s;
        !           540:
        !           541:        iop = (struct iop_softc *)sc->sc_dv.dv_parent;
        !           542:        im = iop_msg_alloc(iop, &sc->sc_ii, IM_POLL);
        !           543:
        !           544:        mf.msgflags = I2O_MSGFLAGS(i2o_scsi_scb_abort);
        !           545:        mf.msgfunc = I2O_MSGFUNC(atid, I2O_SCSI_SCB_ABORT);
        !           546:        mf.msgictx = sc->sc_ii.ii_ictx;
        !           547:        mf.msgtctx = im->im_tctx;
        !           548:        mf.tctxabort = aim->im_tctx;
        !           549:
        !           550:        s = splbio();
        !           551:        rv = iop_msg_post(iop, im, &mf, 30000);
        !           552:        splx(s);
        !           553:        iop_msg_free(iop, im);
        !           554:        return (rv);
        !           555: }
        !           556: #endif
        !           557:
        !           558: /*
        !           559:  * We have a message which has been processed and replied to by the IOP -
        !           560:  * deal with it.
        !           561:  */
        !           562: void
        !           563: iopsp_intr(struct device *dv, struct iop_msg *im, void *reply)
        !           564: {
        !           565:        struct scsi_xfer *xs;
        !           566:        struct iopsp_softc *sc;
        !           567:        struct i2o_scsi_reply *rb;
        !           568:        struct iop_softc *iop;
        !           569:        u_int sl;
        !           570:
        !           571:        sc = (struct iopsp_softc *)dv;
        !           572:        xs = (struct scsi_xfer *)im->im_dvcontext;
        !           573:        iop = (struct iop_softc *)dv->dv_parent;
        !           574:        rb = reply;
        !           575:
        !           576:        SC_DEBUG(xs->sc_link, SDEV_DB2, ("iopsp_intr\n"));
        !           577:
        !           578:        if ((rb->msgflags & I2O_MSGFLAGS_FAIL) != 0) {
        !           579:                xs->error = XS_DRIVER_STUFFUP;
        !           580:                xs->resid = xs->datalen;
        !           581:        } else {
        !           582:                if (rb->hbastatus != I2O_SCSI_DSC_SUCCESS) {
        !           583:                        switch (rb->hbastatus) {
        !           584:                        case I2O_SCSI_DSC_ADAPTER_BUSY:
        !           585:                        case I2O_SCSI_DSC_SCSI_BUS_RESET:
        !           586:                        case I2O_SCSI_DSC_BUS_BUSY:
        !           587:                                xs->error = XS_BUSY;
        !           588:                                break;
        !           589:                        case I2O_SCSI_DSC_SELECTION_TIMEOUT:
        !           590:                                xs->error = XS_SELTIMEOUT;
        !           591:                                break;
        !           592:                        case I2O_SCSI_DSC_COMMAND_TIMEOUT:
        !           593:                        case I2O_SCSI_DSC_DEVICE_NOT_PRESENT:
        !           594:                        case I2O_SCSI_DSC_LUN_INVALID:
        !           595:                        case I2O_SCSI_DSC_SCSI_TID_INVALID:
        !           596:                                xs->error = XS_TIMEOUT;
        !           597:                                break;
        !           598:                        default:
        !           599:                                xs->error = XS_DRIVER_STUFFUP;
        !           600:                                break;
        !           601:                        }
        !           602:                        printf("%s: HBA status 0x%02x\n", sc->sc_dv.dv_xname,
        !           603:                           rb->hbastatus);
        !           604:                } else if (rb->scsistatus != SCSI_OK) {
        !           605:                        switch (rb->scsistatus) {
        !           606:                        case SCSI_CHECK:
        !           607:                                xs->error = XS_SENSE;
        !           608:                                sl = letoh32(rb->senselen);
        !           609:                                if (sl > sizeof(xs->sense))
        !           610:                                        sl = sizeof(xs->sense);
        !           611:                                bcopy(rb->sense, &xs->sense, sl);
        !           612:                                break;
        !           613:                        case SCSI_QUEUE_FULL:
        !           614:                        case SCSI_BUSY:
        !           615:                                xs->error = XS_BUSY;
        !           616:                                break;
        !           617:                        default:
        !           618:                                xs->error = XS_DRIVER_STUFFUP;
        !           619:                                break;
        !           620:                        }
        !           621:                } else
        !           622:                        xs->error = XS_NOERROR;
        !           623:
        !           624:                xs->resid = xs->datalen - letoh32(rb->datalen);
        !           625:                xs->status = rb->scsistatus;
        !           626:        }
        !           627:
        !           628:        /* Free the message wrapper and pass the news to scsi. */
        !           629:        if (xs->datalen != 0)
        !           630:                iop_msg_unmap(iop, im);
        !           631:        iop_msg_free(iop, im);
        !           632:
        !           633:        if (--sc->sc_curqd == sc->sc_link.openings)
        !           634:                wakeup(&sc->sc_curqd);
        !           635:
        !           636:        scsi_done(xs);
        !           637: }
        !           638:
        !           639: /*
        !           640:  * The number of openings available to us has changed, so inform scsi.
        !           641:  */
        !           642: void
        !           643: iopsp_adjqparam(struct device *dv, int mpi)
        !           644: {
        !           645:        struct iopsp_softc *sc = (struct iopsp_softc *)dv;
        !           646:        int s;
        !           647:
        !           648:        s = splbio();
        !           649:        sc->sc_link.openings = mpi;
        !           650:        if (mpi < sc->sc_curqd)
        !           651:                tsleep(&sc->sc_curqd, PWAIT, "iopspdrn", 0);
        !           652:        splx(s);
        !           653: }

CVSweb