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