[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

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