Home | History | Annotate | Line # | Download | only in i2o
iopsp.c revision 1.4
      1 /*	$NetBSD: iopsp.c,v 1.4 2001/02/07 17:05:46 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 	return (param.ci.bustype == I2O_HBA_BUS_SCSI ||
    116 	    param.ci.bustype == I2O_HBA_BUS_FCA);
    117 }
    118 
    119 /*
    120  * Attach a supported device.
    121  */
    122 static void
    123 iopsp_attach(struct device *parent, struct device *self, void *aux)
    124 {
    125 	struct iop_attach_args *ia;
    126 	struct iopsp_softc *sc;
    127 	struct scsipi_link *sc_link;
    128 	struct iop_softc *iop;
    129 	struct {
    130 		struct	i2o_param_op_results pr;
    131 		struct	i2o_param_read_results prr;
    132 		union {
    133 			struct	i2o_param_device_identity di;
    134 			struct	i2o_param_hba_ctlr_info ci;
    135 			struct	i2o_param_hba_scsi_ctlr_info sci;
    136 			struct	i2o_param_hba_scsi_port_info spi;
    137 		} p;
    138 	} __attribute__ ((__packed__)) param;
    139 	char ident[64];
    140 	int fcal, rv;
    141 #ifdef I2OVERBOSE
    142 	int size;
    143 #endif
    144 
    145 	ia = (struct iop_attach_args *)aux;
    146 	sc = (struct iopsp_softc *)self;
    147 	iop = (struct iop_softc *)parent;
    148 	sc->sc_tid = ia->ia_tid;
    149 
    150 	/* Register us as an initiator. */
    151 	sc->sc_ii.ii_dv = self;
    152 	sc->sc_ii.ii_intr = iopsp_intr;
    153 	sc->sc_ii.ii_flags = 0;
    154 	sc->sc_ii.ii_tid = ia->ia_tid;
    155 	sc->sc_ii.ii_reconfig = iopsp_reconfig;
    156 	if (iop_initiator_register(iop, &sc->sc_ii) != 0) {
    157 		printf("%s: unable to register as an initiator",
    158 		    sc->sc_dv.dv_xname);
    159 		return;
    160 	}
    161 
    162 	rv = iop_param_op(iop, ia->ia_tid, 0, I2O_PARAM_HBA_CTLR_INFO, &param,
    163 	    sizeof(param));
    164 	if (rv != 0) {
    165 		printf("%s: unable to get parameters (0x%04x; %d)\n",
    166 	    	    sc->sc_dv.dv_xname, I2O_PARAM_HBA_CTLR_INFO, rv);
    167 		goto bad;
    168 	}
    169 
    170 	fcal = (param.p.ci.bustype == I2O_HBA_BUS_FCA);		/* XXX */
    171 
    172 	/*
    173 	 * Say what the device is.  If we can find out what the controling
    174 	 * device is, say what that is too.
    175 	 */
    176 	printf(": %s SCSI port", fcal ? "FC-AL" : "SE/LVD");
    177 	if (iop_param_op(iop, ia->ia_tid, 0, I2O_PARAM_DEVICE_IDENTITY, &param,
    178 	    sizeof(param)) == 0) {
    179 		iop_strvis(iop, param.p.di.vendorinfo,
    180 		    sizeof(param.p.di.vendorinfo), ident, sizeof(ident));
    181 		printf(" <%s, ", ident);
    182 		iop_strvis(iop, param.p.di.productinfo,
    183 		    sizeof(param.p.di.productinfo), ident, sizeof(ident));
    184 		printf("%s, ", ident);
    185 		iop_strvis(iop, param.p.di.revlevel,
    186 		    sizeof(param.p.di.revlevel), ident, sizeof(ident));
    187 		printf("%s> ", ident);
    188 	}
    189 	printf("\n");
    190 
    191 	rv = iop_param_op(iop, ia->ia_tid, 0, I2O_PARAM_HBA_SCSI_CTLR_INFO,
    192 	    &param, sizeof(param));
    193 	if (rv != 0) {
    194 		printf("%s: unable to get parameters (0x%04x; %d)\n",
    195 		    sc->sc_dv.dv_xname, I2O_PARAM_HBA_SCSI_CTLR_INFO, rv);
    196 		goto bad;
    197 	}
    198 
    199 #ifdef I2OVERBOSE
    200 	printf("%s: %d-bit, max sync rate %dMHz, initiator ID %d\n",
    201 	    sc->sc_dv.dv_xname, param.p.sci.maxdatawidth,
    202 	    (u_int32_t)le64toh(param.p.sci.maxsyncrate) / 1000,
    203 	    le32toh(param.p.sci.initiatorid));
    204 #endif
    205 
    206 	sc->sc_adapter.scsipi_cmd = iopsp_scsi_cmd;
    207 	sc->sc_adapter.scsipi_minphys = iopsp_minphys;
    208 	sc->sc_adapter.scsipi_ioctl = iopsp_ioctl;
    209 
    210 	sc_link = &sc->sc_link;
    211 	sc_link->type = BUS_SCSI;
    212 	sc_link->device = &iopsp_dev;
    213 	sc_link->adapter = &sc->sc_adapter;
    214 	sc_link->adapter_softc = sc;
    215 	sc_link->scsipi_scsi.channel = 0;
    216 	sc_link->scsipi_scsi.adapter_target = le32toh(param.p.sci.initiatorid);
    217 	sc_link->scsipi_scsi.max_target =
    218 	    fcal ? IOPSP_MAX_FCAL_TARGET : param.p.sci.maxdatawidth - 1;
    219 	sc_link->scsipi_scsi.max_lun = IOPSP_MAX_LUN;
    220 	sc_link->openings = iop->sc_maxqueuecnt / 4;		/* XXX */
    221 
    222 #ifdef I2OVERBOSE
    223 	/*
    224 	 * Allocate the target map.  Currently used for informational
    225 	 * purposes only.
    226 	 */
    227 	size = (sc_link->scsipi_scsi.max_target + 1) *
    228 	    sizeof(struct iopsp_target);
    229 	sc->sc_targetmap = malloc(size, M_DEVBUF, M_NOWAIT);
    230 	memset(sc->sc_targetmap, 0, size);
    231 #endif
    232 
    233  	/* Build the two maps, and attach to scsipi. */
    234 	if (iopsp_reconfig(self) != 0) {
    235 		printf("%s: bus scan failed\n", sc->sc_dv.dv_xname);
    236 		goto bad;
    237 	}
    238 	config_found(self, sc_link, scsiprint);
    239 	return;
    240 
    241 bad:
    242 	iop_initiator_unregister(iop, &sc->sc_ii);
    243 }
    244 
    245 /*
    246  * Scan the LCT to determine which devices we control, and enter them into
    247  * the maps.
    248  */
    249 static int
    250 iopsp_reconfig(struct device *dv)
    251 {
    252 	struct iopsp_softc *sc;
    253 	struct iop_softc *iop;
    254 	struct i2o_lct_entry *le;
    255 	struct scsipi_link *sc_link;
    256 	struct {
    257 		struct	i2o_param_op_results pr;
    258 		struct	i2o_param_read_results prr;
    259 		struct	i2o_param_scsi_device_info sdi;
    260 	} __attribute__ ((__packed__)) param;
    261 	int tid, nent, i, targ, lun, size, s, rv;
    262 	u_short *tidmap;
    263 #ifdef I2OVERBOSE
    264 	struct iopsp_target *it;
    265 	int syncrate;
    266 #endif
    267 
    268 	sc = (struct iopsp_softc *)dv;
    269 	iop = (struct iop_softc *)sc->sc_dv.dv_parent;
    270 	sc_link = &sc->sc_link;
    271 
    272 	/* Anything to do? */
    273 	if (iop->sc_lct->changeindicator == sc->sc_chgindicator)
    274 		return (0);
    275 
    276 	/*
    277 	 * Allocate memory for the target/LUN -> TID map.  Use zero to
    278 	 * denote absent targets (zero is the TID of the I2O executive,
    279 	 * and we never address that here).
    280 	 */
    281 	size = (sc_link->scsipi_scsi.max_target + 1) *
    282 	    (IOPSP_MAX_LUN + 1) * sizeof(u_short);
    283 	if ((tidmap = malloc(size, M_DEVBUF, M_WAITOK)) == NULL)
    284 		return (ENOMEM);
    285 	memset(tidmap, 0, size);
    286 
    287 #ifdef I2OVERBOSE
    288 	for (i = 0; i <= sc_link->scsipi_scsi.max_target; i++)
    289 		sc->sc_targetmap[i].it_flags &= ~IT_PRESENT;
    290 #endif
    291 
    292 	nent = iop->sc_nlctent;
    293 	for (i = 0, le = iop->sc_lct->entry; i < nent; i++, le++) {
    294 		switch (le16toh(le->classid) & 4095) {
    295 		case I2O_CLASS_SCSI_PERIPHERAL:
    296 			break;
    297 		default:
    298 			continue;
    299 		}
    300 		if (((le32toh(le->usertid) >> 12) & 4095) != sc->sc_tid)
    301 			continue;
    302 
    303 		tid = le32toh(le->localtid) & 4095;
    304 
    305 		rv = iop_param_op(iop, tid, 0, I2O_PARAM_SCSI_DEVICE_INFO,
    306 		    &param, sizeof(param));
    307 		if (rv != 0) {
    308 			printf("%s: unable to get parameters (0x%04x; %d)\n",
    309 			    sc->sc_dv.dv_xname, I2O_PARAM_SCSI_DEVICE_INFO,
    310 			    rv);
    311 			continue;
    312 		}
    313 		targ = le32toh(param.sdi.identifier);
    314 		lun = param.sdi.luninfo[1];
    315 
    316 		/* If the device is in use by a DDM, ignore it. */
    317 		if ((le32toh(le->usertid) & 4095) != 4095) {
    318 #ifdef I2OVERBOSE
    319 			if (sc->sc_tidmap == NULL ||
    320 			    IOPSP_TIDMAP(sc->sc_tidmap, targ, lun) !=
    321 			    IOPSP_TID_INUSE)
    322 				printf("%s: target %d,%d (tid %d): in use by"
    323 				    " tid %d\n", sc->sc_dv.dv_xname,
    324 				    targ, lun, tid,
    325 				    le32toh(le->usertid) & 4095);
    326 #endif
    327 			IOPSP_TIDMAP(tidmap, targ, lun) = IOPSP_TID_INUSE;
    328 			continue;
    329 		}
    330 		IOPSP_TIDMAP(tidmap, targ, lun) = (u_short)tid;
    331 
    332 #ifdef I2OVERBOSE
    333 		/*
    334 		 * If we've already described this target, and nothing has
    335 		 * changed, then don't describe it again.
    336 		 */
    337 		it = &sc->sc_targetmap[targ];
    338 		it->it_flags |= IT_PRESENT;
    339 		syncrate = ((int)le64toh(param.sdi.negsyncrate) + 500) / 1000;
    340 		if (it->it_width == param.sdi.negdatawidth &&
    341 		    it->it_offset == param.sdi.negoffset &&
    342 		    it->it_syncrate == syncrate)
    343 			continue;
    344 
    345 		it->it_width = param.sdi.negdatawidth;
    346 		it->it_offset = param.sdi.negoffset;
    347 		it->it_syncrate = syncrate;
    348 
    349 		printf("%s: target %d (tid %d): %d-bit, ", sc->sc_dv.dv_xname,
    350 		    targ, tid, it->it_width);
    351 		if (it->it_syncrate == 0)
    352 			printf("asynchronous\n");
    353 		else
    354 			printf("synchronous at %dMHz, offset 0x%x\n",
    355 			    it->it_syncrate, it->it_offset);
    356 #endif
    357 	}
    358 
    359 #ifdef I2OVERBOSE
    360 	for (i = 0; i <= sc_link->scsipi_scsi.max_target; i++)
    361 		if ((sc->sc_targetmap[i].it_flags & IT_PRESENT) == 0)
    362 			sc->sc_targetmap[i].it_width = 0;
    363 #endif
    364 
    365 	/* Swap in the new map and return. */
    366 	s = splbio();
    367 	if (sc->sc_tidmap != NULL)
    368 		free(sc->sc_tidmap, M_DEVBUF);
    369 	sc->sc_tidmap = tidmap;
    370 	splx(s);
    371 	sc->sc_chgindicator = iop->sc_lct->changeindicator;
    372 	return (0);
    373 }
    374 
    375 /*
    376  * Adjust the size of an I/O request.
    377  */
    378 static void
    379 iopsp_minphys(struct buf *bp)
    380 {
    381 
    382 	if (bp->b_bcount > IOP_MAX_XFER)
    383 		bp->b_bcount = IOP_MAX_XFER;
    384 	minphys(bp);
    385 }
    386 
    387 /*
    388  * Re-scan the bus; to be called from a higher level (e.g. scsipi).
    389  */
    390 static int
    391 iopsp_rescan(struct iopsp_softc *sc)
    392 {
    393 	struct iop_softc *iop;
    394 	struct iop_msg *im;
    395 	struct i2o_hba_bus_scan *mb;
    396 	int rv;
    397 
    398 	iop = (struct iop_softc *)sc->sc_dv.dv_parent;
    399 
    400 	rv = lockmgr(&iop->sc_conflock, LK_EXCLUSIVE | LK_RECURSEFAIL, NULL);
    401 	if (rv != 0) {
    402 #ifdef I2ODEBUG
    403 		printf("iopsp_rescan: unable to acquire lock\n");
    404 #endif
    405 		return (rv);
    406 	}
    407 
    408 	/* XXX If it's boot time, the bus will already have been scanned. */
    409 	if (curproc != &proc0) {
    410 		if ((rv = iop_msg_alloc(iop, &sc->sc_ii, &im, IM_NOINTR)) != 0)
    411 			goto done;
    412 
    413 		mb = (struct i2o_hba_bus_scan *)im->im_msg;
    414 		mb->msgflags = I2O_MSGFLAGS(i2o_hba_bus_scan);
    415 		mb->msgfunc = I2O_MSGFUNC(sc->sc_tid, I2O_HBA_BUS_SCAN);
    416 		mb->msgictx = sc->sc_ii.ii_ictx;
    417 		mb->msgtctx = im->im_tctx;
    418 
    419 		rv = iop_msg_enqueue(iop, im, 5*60*1000);
    420 		iop_msg_free(iop, &sc->sc_ii, im);
    421 		if (rv != 0)
    422 			goto done;
    423 
    424 		if ((rv = iop_lct_get(iop)) != 0)
    425 			goto done;
    426 	}
    427 
    428 	/* Rebuild the target/LUN -> TID map, release lock, and return. */
    429 	rv = iopsp_reconfig(&sc->sc_dv);
    430 done:
    431 	lockmgr(&iop->sc_conflock, LK_RELEASE, NULL);
    432 	return (rv);
    433 }
    434 
    435 /*
    436  * Start a SCSI command.
    437  */
    438 static int
    439 iopsp_scsi_cmd(struct scsipi_xfer *xs)
    440 {
    441 	struct scsipi_link *sc_link;
    442 	struct iopsp_softc *sc;
    443 	struct iop_msg *im;
    444 	struct iop_softc *iop;
    445 	struct i2o_scsi_scb_exec *mb;
    446 	int error, flags, tid;
    447 
    448 	sc_link = xs->sc_link;
    449 	flags = xs->xs_control;
    450 	sc = sc_link->adapter_softc;
    451 	iop = (struct iop_softc *)sc->sc_dv.dv_parent;
    452 
    453 	tid = IOPSP_TIDMAP(sc->sc_tidmap, sc_link->scsipi_scsi.target,
    454 	    sc_link->scsipi_scsi.lun);
    455 	if (tid == IOPSP_TID_ABSENT || tid == IOPSP_TID_INUSE) {
    456 		xs->error = XS_SELTIMEOUT;
    457 		return (COMPLETE);
    458 	}
    459 
    460 	SC_DEBUG(sc_link, SDEV_DB2, ("iopsp_scsi_cmd\n"));
    461 
    462 	/* Need to reset the target? */
    463 	if ((flags & XS_CTL_RESET) != 0) {
    464 		if (iop_simple_cmd(iop, tid, I2O_SCSI_DEVICE_RESET,
    465 		    sc->sc_ii.ii_ictx, 1, 10*1000) != 0) {
    466 #ifdef I2ODEBUG
    467 			printf("%s: reset failed\n", sc->sc_dv.dv_xname);
    468 #endif
    469 			xs->error = XS_DRIVER_STUFFUP;
    470 		}
    471 		return (COMPLETE);
    472 	}
    473 
    474 #if defined(I2ODEBUG) || defined(SCSIDEBUG)
    475 	if (xs->cmdlen > 16)
    476 		panic("%s: CDB too large\n", sc->sc_dv.dv_xname);
    477 #endif
    478 
    479 	if (iop_msg_alloc(iop, &sc->sc_ii, &im,
    480 	    (flags & (XS_CTL_POLL | XS_CTL_NOSLEEP)) != 0 ? IM_NOWAIT : 0)) {
    481 		xs->error = XS_DRIVER_STUFFUP;
    482 		return (TRY_AGAIN_LATER);
    483 	}
    484 	im->im_dvcontext = xs;
    485 
    486 	mb = (struct i2o_scsi_scb_exec *)im->im_msg;
    487 	mb->msgflags = I2O_MSGFLAGS(i2o_scsi_scb_exec);
    488 	mb->msgfunc = I2O_MSGFUNC(tid, I2O_SCSI_SCB_EXEC);
    489 	mb->msgictx = sc->sc_ii.ii_ictx;
    490 	mb->msgtctx = im->im_tctx;
    491 	mb->flags = xs->cmdlen | I2O_SCB_FLAG_ENABLE_DISCONNECT |
    492 	    I2O_SCB_FLAG_SENSE_DATA_IN_MESSAGE;
    493 	memcpy(mb->cdb, xs->cmd, xs->cmdlen);
    494 	mb->datalen = xs->datalen;
    495 
    496 	if ((xs->sc_link->quirks & SDEV_NOTAG) == 0 &&
    497 	    (xs->xs_control & XS_CTL_POLL) != 0) {
    498 		if (xs->bp != NULL && (xs->bp->b_flags & B_ASYNC) != 0)
    499 			mb->flags |= I2O_SCB_FLAG_ORDERED_QUEUE_TAG;
    500 		else
    501 			mb->flags |= I2O_SCB_FLAG_SIMPLE_QUEUE_TAG;
    502 	}
    503 
    504 	if (xs->datalen != 0) {
    505 		error = iop_msg_map(iop, im, xs->data, xs->datalen,
    506 		    (flags & XS_CTL_DATA_OUT) == 0);
    507 		if (error) {
    508 #ifdef I2ODEBUG
    509 			printf("%s: error %d mapping xfer\n",
    510 			    sc->sc_dv.dv_xname, error);
    511 #endif
    512 			xs->error = XS_DRIVER_STUFFUP;
    513 			iop_msg_free(iop, &sc->sc_ii, im);
    514 			return (COMPLETE);
    515 		}
    516 		if ((flags & XS_CTL_DATA_IN) == 0)
    517 			mb->flags |= I2O_SCB_FLAG_XFER_TO_DEVICE;
    518 		else
    519 			mb->flags |= I2O_SCB_FLAG_XFER_FROM_DEVICE;
    520 	}
    521 
    522 	/*
    523 	 * If the command is allowed to execute asynchronously, enqueue it
    524 	 * with the IOP.
    525 	 */
    526 	if ((flags & XS_CTL_POLL) == 0) {
    527 		iop_msg_enqueue(iop, im, 0);
    528 		return (SUCCESSFULLY_QUEUED);
    529 	}
    530 
    531 	if (iop_msg_send(iop, im, xs->timeout)) {
    532 		scsi_print_addr(xs->sc_link);
    533 		printf("timeout; aborting command\n");
    534 		if (iopsp_scsi_abort(sc, tid, im)) {
    535 			scsi_print_addr(xs->sc_link);
    536 			printf("abort failed\n");
    537 		}
    538 		xs->error = XS_DRIVER_STUFFUP;
    539 	}
    540 	return (COMPLETE);
    541 }
    542 
    543 /*
    544  * Abort the specified I2O_SCSI_SCB_EXEC message and its associated SCB.
    545  */
    546 static int
    547 iopsp_scsi_abort(struct iopsp_softc *sc, int atid, struct iop_msg *aim)
    548 {
    549 	struct iop_msg *im;
    550 	struct i2o_scsi_scb_abort *mb;
    551 	struct iop_softc *iop;
    552 	int rv;
    553 
    554 	iop = (struct iop_softc *)sc->sc_dv.dv_parent;
    555 
    556 	rv = iop_msg_alloc(iop, &sc->sc_ii, &im, IM_NOWAIT | IM_NOINTR);
    557 	if (rv != 0)
    558 		return (rv);
    559 
    560 	mb = (struct i2o_scsi_scb_abort *)im->im_msg;
    561 	mb->msgflags = I2O_MSGFLAGS(i2o_scsi_scb_abort);
    562 	mb->msgfunc = I2O_MSGFUNC(atid, I2O_SCSI_SCB_ABORT);
    563 	mb->msgictx = sc->sc_ii.ii_ictx;
    564 	mb->msgtctx = im->im_tctx;
    565 	mb->tctxabort = aim->im_tctx;
    566 
    567 	rv = iop_msg_send(iop, im, 1000);
    568 	iop_msg_free(iop, &sc->sc_ii, im);
    569 	return (rv);
    570 }
    571 
    572 /*
    573  * We have a message which has been processed and replied to by the IOP -
    574  * deal with it.
    575  */
    576 static void
    577 iopsp_intr(struct device *dv, struct iop_msg *im, void *reply)
    578 {
    579 	struct scsipi_xfer *xs;
    580 	struct iopsp_softc *sc;
    581 	struct i2o_scsi_reply *rb;
    582 	struct iop_softc *iop;
    583 	u_int hba_status, scsi_status, detail;
    584 	int sl;
    585 
    586 	sc = (struct iopsp_softc *)dv;
    587 	xs = (struct scsipi_xfer *)im->im_dvcontext;
    588 	iop = (struct iop_softc *)dv->dv_parent;
    589 
    590 	SC_DEBUG(xs->sc_link, SDEV_DB2, ("iopsp_intr\n"));
    591 
    592 	if (xs->error == XS_NOERROR) {
    593 		rb = reply;
    594 		detail = le16toh(rb->detail);
    595 		hba_status = (detail >> 8) & 0xff;
    596 		scsi_status = detail & 0xff;
    597 
    598 		if (hba_status != I2O_SCSI_DSC_SUCCESS) {
    599 			switch (hba_status) {
    600 			case I2O_SCSI_DSC_ADAPTER_BUSY:
    601 			case I2O_SCSI_DSC_SCSI_BUS_RESET:
    602 			case I2O_SCSI_DSC_BUS_BUSY:
    603 				xs->error = XS_BUSY;
    604 				break;
    605 			case I2O_SCSI_DSC_SELECTION_TIMEOUT:
    606 				xs->error = XS_SELTIMEOUT;
    607 				break;
    608 			case I2O_SCSI_DSC_COMMAND_TIMEOUT:
    609 			case I2O_SCSI_DSC_DEVICE_NOT_PRESENT:
    610 			case I2O_SCSI_DSC_LUN_INVALID:
    611 			case I2O_SCSI_DSC_SCSI_TID_INVALID:
    612 				xs->error = XS_TIMEOUT;
    613 				break;
    614 			default:
    615 				xs->error = XS_DRIVER_STUFFUP;
    616 				break;
    617 			}
    618 #ifdef I2ODEBUG
    619 			printf("%s: HBA status 0x%02x\n", sc->sc_dv.dv_xname,
    620 			    hba_status);
    621 #endif
    622 		} else if (scsi_status != SCSI_OK) {
    623 			switch (scsi_status) {
    624 			case SCSI_CHECK:
    625 				xs->error = XS_SENSE;
    626 				sl = le32toh(rb->senselen);
    627 				if (xs->req_sense_length != 0 &&
    628 				    xs->req_sense_length < sl)
    629 					sl = xs->req_sense_length;
    630 				if (sl > sizeof(xs->sense.scsi_sense))
    631 					sl = le32toh(rb->senselen);
    632 				memcpy(&xs->sense.scsi_sense, rb->sense, sl);
    633 				break;
    634 			case SCSI_BUSY:
    635 				xs->error = XS_BUSY;
    636 				break;
    637 			default:
    638 				xs->error = XS_DRIVER_STUFFUP;
    639 				break;
    640 			}
    641 		} else
    642 			xs->error = XS_NOERROR;
    643 
    644 		xs->resid = le32toh(rb->datalen) - xs->datalen;
    645 		xs->status = scsi_status;
    646 	}
    647 
    648 	/* Free the message wrapper and pass the news to scsipi. */
    649 	iop_msg_unmap(iop, im);
    650 	iop_msg_free(iop, &sc->sc_ii, im);
    651 	xs->xs_status |= XS_STS_DONE;
    652 	scsipi_done(xs);
    653 }
    654 
    655 /*
    656  * ioctl hook; used here only to initiate low-level rescans.
    657  */
    658 static int
    659 iopsp_ioctl(struct scsipi_link *sc_link, u_long cmd, caddr_t data, int flag,
    660 	    struct proc *p)
    661 {
    662 	int rv;
    663 
    664 	switch (cmd) {
    665 	case SCBUSIOLLSCAN:
    666 		rv = iopsp_rescan(sc_link->adapter_softc);
    667 		break;
    668 	default:
    669 		rv = ENXIO;
    670 		break;
    671 	}
    672 
    673 	return (rv);
    674 }
    675