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