Home | History | Annotate | Line # | Download | only in ic
isp_netbsd.c revision 1.26
      1 /* $NetBSD: isp_netbsd.c,v 1.26 2000/07/05 22:23:05 mjacob Exp $ */
      2 /*
      3  * Platform (NetBSD) dependent common attachment code for Qlogic adapters.
      4  * Matthew Jacob <mjacob (at) nas.nasa.gov>
      5  */
      6 /*
      7  * Copyright (C) 1997, 1998, 1999 National Aeronautics & Space Administration
      8  * All rights reserved.
      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. The name of the author may not be used to endorse or promote products
     19  *    derived from this software without specific prior written permission
     20  *
     21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     22  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     23  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     24  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     26  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     30  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     31  */
     32 
     33 #include <dev/ic/isp_netbsd.h>
     34 #include <sys/scsiio.h>
     35 
     36 #define	_XT(xs)	((((xs)->timeout + 999)/1000) + (2 * hz))
     37 
     38 static void ispminphys __P((struct buf *));
     39 static int32_t ispcmd_slow __P((ISP_SCSI_XFER_T *));
     40 static int32_t ispcmd __P((ISP_SCSI_XFER_T *));
     41 static int
     42 ispioctl __P((struct scsipi_link *, u_long, caddr_t, int, struct proc *));
     43 
     44 static struct scsipi_device isp_dev = { NULL, NULL, NULL, NULL };
     45 static int isp_polled_cmd __P((struct ispsoftc *, ISP_SCSI_XFER_T *));
     46 static void isp_dog __P((void *));
     47 static void isp_command_requeue __P((void *));
     48 static void isp_internal_restart __P((void *));
     49 
     50 /*
     51  * Complete attachment of hardware, include subdevices.
     52  */
     53 void
     54 isp_attach(isp)
     55 	struct ispsoftc *isp;
     56 {
     57 	int maxluns = isp->isp_maxluns - 1;
     58 
     59 	isp->isp_osinfo._adapter.scsipi_minphys = ispminphys;
     60 	isp->isp_osinfo._adapter.scsipi_ioctl = ispioctl;
     61 
     62 	isp->isp_state = ISP_RUNSTATE;
     63 	isp->isp_osinfo._link.scsipi_scsi.channel =
     64 	    (IS_DUALBUS(isp))? 0 : SCSI_CHANNEL_ONLY_ONE;
     65 	isp->isp_osinfo._link.adapter_softc = isp;
     66 	isp->isp_osinfo._link.device = &isp_dev;
     67 	isp->isp_osinfo._link.adapter = &isp->isp_osinfo._adapter;
     68 	isp->isp_osinfo._link.openings = isp->isp_maxcmds;
     69 	isp->isp_osinfo._link.scsipi_scsi.max_lun = maxluns;
     70 	TAILQ_INIT(&isp->isp_osinfo.waitq);	/* XXX 2nd Bus? */
     71 
     72 	if (IS_FC(isp)) {
     73 		/*
     74 		 * Give it another chance here to come alive...
     75 		 */
     76 		isp->isp_osinfo._adapter.scsipi_cmd = ispcmd;
     77 		isp->isp_osinfo._link.scsipi_scsi.max_target = MAX_FC_TARG-1;
     78 		/*
     79 		 * But we have to be reasonable until the midlayer is fixed.
     80 		 */
     81 		if (maxluns > 255)
     82 			isp->isp_osinfo._link.scsipi_scsi.max_lun = 255;
     83 	} else {
     84 		sdparam *sdp = isp->isp_param;
     85 		isp->isp_osinfo._adapter.scsipi_cmd = ispcmd_slow;
     86 		isp->isp_osinfo._link.scsipi_scsi.max_target = MAX_TARGETS-1;
     87 		isp->isp_osinfo._link.scsipi_scsi.adapter_target =
     88 		    sdp->isp_initiator_id;
     89 		isp->isp_osinfo.discovered[0] = 1 << sdp->isp_initiator_id;
     90 		/*
     91 		 * But we have to be reasonable until the midlayer is fixed.
     92 		 */
     93 		if (maxluns > 7)
     94 			isp->isp_osinfo._link.scsipi_scsi.max_lun = 7;
     95 		if (IS_DUALBUS(isp)) {
     96 			isp->isp_osinfo._link_b = isp->isp_osinfo._link;
     97 			sdp++;
     98 			isp->isp_osinfo.discovered[1] =
     99 			    1 << sdp->isp_initiator_id;
    100 			isp->isp_osinfo._link_b.scsipi_scsi.adapter_target =
    101 			    sdp->isp_initiator_id;
    102 			isp->isp_osinfo._link_b.scsipi_scsi.channel = 1;
    103 			isp->isp_osinfo._link_b.scsipi_scsi.max_lun =
    104 			    isp->isp_osinfo._link.scsipi_scsi.max_lun;
    105 		}
    106 	}
    107 	isp->isp_osinfo._link.type = BUS_SCSI;
    108 
    109 	/*
    110 	 * Send a SCSI Bus Reset.
    111 	 */
    112 	if (IS_SCSI(isp)) {
    113 		int bus = 0;
    114 		(void) isp_control(isp, ISPCTL_RESET_BUS, &bus);
    115 		if (IS_DUALBUS(isp)) {
    116 			bus++;
    117 			(void) isp_control(isp, ISPCTL_RESET_BUS, &bus);
    118 		}
    119 	} else {
    120 		int i, j;
    121 		fcparam *fcp = isp->isp_param;
    122 		delay(2 * 1000000);
    123 		for (j = 0; j < 5; j++) {
    124 			for (i = 0; i < 5; i++) {
    125 				if (isp_control(isp, ISPCTL_FCLINK_TEST, NULL))
    126 					continue;
    127 #ifdef	ISP2100_FABRIC
    128 				/*
    129 				 * Wait extra time to see if the f/w
    130 				 * eventually completed an FLOGI that
    131 				 * will allow us to know we're on a
    132 				 * fabric.
    133 				 */
    134 				if (fcp->isp_onfabric == 0) {
    135 					delay(1 * 1000000);
    136 					continue;
    137 				}
    138 #endif
    139 				break;
    140 			}
    141 			if (fcp->isp_fwstate == FW_READY &&
    142 			    fcp->isp_loopstate >= LOOP_PDB_RCVD) {
    143 				break;
    144 			}
    145 		}
    146 		isp->isp_osinfo._link.scsipi_scsi.adapter_target =
    147 			fcp->isp_loopid;
    148 	}
    149 
    150 	/*
    151 	 * And attach children (if any).
    152 	 */
    153 	config_found((void *)isp, &isp->isp_osinfo._link, scsiprint);
    154 	if (IS_DUALBUS(isp)) {
    155 		config_found((void *)isp, &isp->isp_osinfo._link_b, scsiprint);
    156 	}
    157 }
    158 
    159 /*
    160  * minphys our xfers
    161  *
    162  * Unfortunately, the buffer pointer describes the target device- not the
    163  * adapter device, so we can't use the pointer to find out what kind of
    164  * adapter we are and adjust accordingly.
    165  */
    166 
    167 static void
    168 ispminphys(bp)
    169 	struct buf *bp;
    170 {
    171 	/*
    172 	 * XX: Only the 1020 has a 24 bit limit.
    173 	 */
    174 	if (bp->b_bcount >= (1 << 24)) {
    175 		bp->b_bcount = (1 << 24);
    176 	}
    177 	minphys(bp);
    178 }
    179 
    180 static int32_t
    181 ispcmd_slow(xs)
    182 	ISP_SCSI_XFER_T *xs;
    183 {
    184 	sdparam *sdp;
    185 	int tgt, chan, s;
    186 	u_int16_t flags;
    187 	struct ispsoftc *isp = XS_ISP(xs);
    188 
    189 	/*
    190 	 * Have we completed discovery for this target on this adapter?
    191 	 */
    192 	tgt = XS_TGT(xs);
    193 	chan = XS_CHANNEL(xs);
    194 	if ((xs->xs_control & XS_CTL_DISCOVERY) != 0 ||
    195 	    (isp->isp_osinfo.discovered[chan] & (1 << tgt)) != 0) {
    196 		return (ispcmd(xs));
    197 	}
    198 
    199 	flags = DPARM_DEFAULT;
    200 	if (xs->sc_link->quirks & SDEV_NOSYNC) {
    201 		flags ^= DPARM_SYNC;
    202 #ifdef	DEBUG
    203 	} else {
    204 		printf("%s: channel %d target %d can do SYNC xfers\n",
    205 		    isp->isp_name, chan, tgt);
    206 #endif
    207 	}
    208 	if (xs->sc_link->quirks & SDEV_NOWIDE) {
    209 		flags ^= DPARM_WIDE;
    210 #ifdef	DEBUG
    211 	} else {
    212 		printf("%s: channel %d target %d can do WIDE xfers\n",
    213 		    isp->isp_name, chan, tgt);
    214 #endif
    215 	}
    216 	if (xs->sc_link->quirks & SDEV_NOTAG) {
    217 		flags ^= DPARM_TQING;
    218 #ifdef	DEBUG
    219 	} else {
    220 		printf("%s: channel %d target %d can do TAGGED xfers\n",
    221 		    isp->isp_name, chan, tgt);
    222 #endif
    223 	}
    224 	/*
    225 	 * Okay, we know about this device now,
    226 	 * so mark parameters to be updated for it.
    227 	 */
    228 	s = splbio();
    229 	isp->isp_osinfo.discovered[chan] |= (1 << tgt);
    230 	sdp = isp->isp_param;
    231 	sdp += chan;
    232 	sdp->isp_devparam[tgt].dev_flags = flags;
    233 	sdp->isp_devparam[tgt].dev_update = 1;
    234 	isp->isp_update |= (1 << chan);
    235 	splx(s);
    236 	return (ispcmd(xs));
    237 }
    238 
    239 static int
    240 ispioctl(sc_link, cmd, addr, flag, p)
    241 	struct scsipi_link *sc_link;
    242 	u_long cmd;
    243 	caddr_t addr;
    244 	int flag;
    245 	struct proc *p;
    246 {
    247 	struct ispsoftc *isp = sc_link->adapter_softc;
    248 	int s, chan, retval = ENOTTY;
    249 
    250 	switch (cmd) {
    251 	case SCBUSIORESET:
    252 		chan = sc_link->scsipi_scsi.channel;
    253 		s = splbio();
    254 		if (isp_control(isp, ISPCTL_RESET_BUS, &chan))
    255 			retval = EIO;
    256 		else
    257 			retval = 0;
    258 		(void) splx(s);
    259 		break;
    260 	default:
    261 		break;
    262 	}
    263 	return (retval);
    264 }
    265 
    266 
    267 static int32_t
    268 ispcmd(xs)
    269 	ISP_SCSI_XFER_T *xs;
    270 {
    271 	struct ispsoftc *isp;
    272 	int result, s;
    273 
    274 	isp = XS_ISP(xs);
    275 	s = splbio();
    276 	if (isp->isp_state < ISP_RUNSTATE) {
    277 		DISABLE_INTS(isp);
    278 		isp_init(isp);
    279                 if (isp->isp_state != ISP_INITSTATE) {
    280 			ENABLE_INTS(isp);
    281                         (void) splx(s);
    282                         XS_SETERR(xs, HBA_BOTCH);
    283                         return (COMPLETE);
    284                 }
    285                 isp->isp_state = ISP_RUNSTATE;
    286 		ENABLE_INTS(isp);
    287         }
    288 
    289 	/*
    290 	 * Check for queue blockage...
    291 	 */
    292 	if (isp->isp_osinfo.blocked) {
    293 		if (xs->xs_control & XS_CTL_POLL) {
    294 			xs->error = XS_DRIVER_STUFFUP;
    295 			splx(s);
    296 			return (TRY_AGAIN_LATER);
    297 		}
    298 		TAILQ_INSERT_TAIL(&isp->isp_osinfo.waitq, xs, adapter_q);
    299 		splx(s);
    300 		return (SUCCESSFULLY_QUEUED);
    301 	}
    302 
    303 	if (xs->xs_control & XS_CTL_POLL) {
    304 		result = isp_polled_cmd(isp, xs);
    305 		(void) splx(s);
    306 		return (result);
    307 	}
    308 
    309 	result = ispscsicmd(xs);
    310 	switch (result) {
    311 	case CMD_QUEUED:
    312 		result = SUCCESSFULLY_QUEUED;
    313 		if (xs->timeout) {
    314 			callout_reset(&xs->xs_callout, _XT(xs), isp_dog, xs);
    315 		}
    316 		break;
    317 	case CMD_EAGAIN:
    318 		result = TRY_AGAIN_LATER;
    319 		break;
    320 	case CMD_RQLATER:
    321 		result = SUCCESSFULLY_QUEUED;
    322 		callout_reset(&xs->xs_callout, hz, isp_command_requeue, xs);
    323 		break;
    324 	case CMD_COMPLETE:
    325 		result = COMPLETE;
    326 		break;
    327 	}
    328 	(void) splx(s);
    329 	return (result);
    330 }
    331 
    332 static int
    333 isp_polled_cmd(isp, xs)
    334 	struct ispsoftc *isp;
    335 	ISP_SCSI_XFER_T *xs;
    336 {
    337 	int result;
    338 	int infinite = 0, mswait;
    339 
    340 	result = ispscsicmd(xs);
    341 
    342 	switch (result) {
    343 	case CMD_QUEUED:
    344 		result = SUCCESSFULLY_QUEUED;
    345 		break;
    346 	case CMD_RQLATER:
    347 	case CMD_EAGAIN:
    348 		if (XS_NOERR(xs)) {
    349 			xs->error = XS_DRIVER_STUFFUP;
    350 		}
    351 		result = TRY_AGAIN_LATER;
    352 		break;
    353 	case CMD_COMPLETE:
    354 		result = COMPLETE;
    355 		break;
    356 
    357 	}
    358 
    359 	if (result != SUCCESSFULLY_QUEUED) {
    360 		return (result);
    361 	}
    362 
    363 	/*
    364 	 * If we can't use interrupts, poll on completion.
    365 	 */
    366 	if ((mswait = XS_TIME(xs)) == 0)
    367 		infinite = 1;
    368 
    369 	while (mswait || infinite) {
    370 		if (isp_intr((void *)isp)) {
    371 			if (XS_CMD_DONE_P(xs)) {
    372 				break;
    373 			}
    374 		}
    375 		SYS_DELAY(1000);
    376 		mswait -= 1;
    377 	}
    378 
    379 	/*
    380 	 * If no other error occurred but we didn't finish,
    381 	 * something bad happened.
    382 	 */
    383 	if (XS_CMD_DONE_P(xs) == 0) {
    384 		if (isp_control(isp, ISPCTL_ABORT_CMD, xs)) {
    385 			isp_restart(isp);
    386 		}
    387 		if (XS_NOERR(xs)) {
    388 			XS_SETERR(xs, HBA_BOTCH);
    389 		}
    390 	}
    391 	result = COMPLETE;
    392 	return (result);
    393 }
    394 
    395 void
    396 isp_done(xs)
    397 	ISP_SCSI_XFER_T *xs;
    398 {
    399 	XS_CMD_S_DONE(xs);
    400 	if (XS_CMD_WDOG_P(xs) == 0) {
    401 		struct ispsoftc *isp = XS_ISP(xs);
    402 		callout_stop(&xs->xs_callout);
    403 		if (XS_CMD_GRACE_P(xs)) {
    404 			PRINTF("%s: finished command on borrowed time\n",
    405 			    isp->isp_name);
    406 		}
    407 		XS_CMD_S_CLEAR(xs);
    408 		scsipi_done(xs);
    409 	}
    410 }
    411 
    412 static void
    413 isp_dog(arg)
    414 	void *arg;
    415 {
    416 	ISP_SCSI_XFER_T *xs = arg;
    417 	struct ispsoftc *isp = XS_ISP(xs);
    418 	u_int32_t handle;
    419 	int s = splbio();
    420 
    421 	/*
    422 	 * We've decided this command is dead. Make sure we're not trying
    423 	 * to kill a command that's already dead by getting it's handle and
    424 	 * and seeing whether it's still alive.
    425 	 */
    426 	handle = isp_find_handle(isp, xs);
    427 	if (handle) {
    428 		u_int16_t r, r1, i;
    429 
    430 		if (XS_CMD_DONE_P(xs)) {
    431 			PRINTF("%s: watchdog found done cmd (handle 0x%x)\n",
    432 			    isp->isp_name, handle);
    433 			(void) splx(s);
    434 			return;
    435 		}
    436 
    437 		if (XS_CMD_WDOG_P(xs)) {
    438 			PRINTF("%s: recursive watchdog (handle 0x%x)\n",
    439 			    isp->isp_name, handle);
    440 			(void) splx(s);
    441 			return;
    442 		}
    443 
    444 		XS_CMD_S_WDOG(xs);
    445 
    446 		i = 0;
    447 		do {
    448 			r = ISP_READ(isp, BIU_ISR);
    449 			SYS_DELAY(1);
    450 			r1 = ISP_READ(isp, BIU_ISR);
    451 		} while (r != r1 && ++i < 1000);
    452 
    453 		if (INT_PENDING(isp, r) && isp_intr(isp) && XS_CMD_DONE_P(xs)) {
    454 			IDPRINTF(1, ("%s: watchdog cleanup (%x, %x)\n",
    455 			    isp->isp_name, handle, r));
    456 			XS_CMD_C_WDOG(xs);
    457 			isp_done(xs);
    458 		} else if (XS_CMD_GRACE_P(xs)) {
    459 			IDPRINTF(1, ("%s: watchdog timeout (%x, %x)\n",
    460 			    isp->isp_name, handle, r));
    461 			/*
    462 			 * Make sure the command is *really* dead before we
    463 			 * release the handle (and DMA resources) for reuse.
    464 			 */
    465 			(void) isp_control(isp, ISPCTL_ABORT_CMD, arg);
    466 
    467 			/*
    468 			 * After this point, the comamnd is really dead.
    469 			 */
    470 			if (XS_XFRLEN(xs)) {
    471 				ISP_DMAFREE(isp, xs, handle);
    472 			}
    473 			isp_destroy_handle(isp, handle);
    474 			XS_SETERR(xs, XS_TIMEOUT);
    475 			XS_CMD_S_CLEAR(xs);
    476 			isp_done(xs);
    477 		} else {
    478 			u_int16_t iptr, optr;
    479 			ispreq_t *mp;
    480 
    481 			IDPRINTF(2, ("%s: possible command timeout (%x, %x)\n",
    482 			    isp->isp_name, handle, r));
    483 
    484 			XS_CMD_C_WDOG(xs);
    485 			callout_reset(&xs->xs_callout, hz, isp_dog, xs);
    486 			if (isp_getrqentry(isp, &iptr, &optr, (void **) &mp)) {
    487 				(void) splx(s);
    488 				return;
    489 			}
    490 			XS_CMD_S_GRACE(xs);
    491 			MEMZERO((void *) mp, sizeof (*mp));
    492 			mp->req_header.rqs_entry_count = 1;
    493 			mp->req_header.rqs_entry_type = RQSTYPE_MARKER;
    494 			mp->req_modifier = SYNC_ALL;
    495 			mp->req_target = XS_CHANNEL(xs) << 7;
    496 			ISP_SWIZZLE_REQUEST(isp, mp);
    497 			MemoryBarrier();
    498 			ISP_ADD_REQUEST(isp, iptr);
    499 		}
    500 	} else if (isp->isp_dblev) {
    501 		PRINTF("%s: watchdog with no command\n", isp->isp_name);
    502 	}
    503 	(void) splx(s);
    504 }
    505 
    506 /*
    507  * Free any associated resources prior to decommissioning and
    508  * set the card to a known state (so it doesn't wake up and kick
    509  * us when we aren't expecting it to).
    510  *
    511  * Locks are held before coming here.
    512  */
    513 void
    514 isp_uninit(isp)
    515 	struct ispsoftc *isp;
    516 {
    517 	ISP_ILOCKVAL_DECL;
    518 	ISP_ILOCK(isp);
    519 	/*
    520 	 * Leave with interrupts disabled.
    521 	 */
    522 	DISABLE_INTS(isp);
    523 
    524 	ISP_IUNLOCK(isp);
    525 }
    526 
    527 /*
    528  * Restart function for a command to be requeued later.
    529  */
    530 static void
    531 isp_command_requeue(arg)
    532 	void *arg;
    533 {
    534 	struct scsipi_xfer *xs = arg;
    535 	struct ispsoftc *isp = XS_ISP(xs);
    536 	int s = splbio();
    537 	switch (ispcmd_slow(xs)) {
    538 	case SUCCESSFULLY_QUEUED:
    539 		printf("%s: isp_command_requeue: requeued for %d.%d\n",
    540 		    isp->isp_name, XS_TGT(xs), XS_LUN(xs));
    541 		if (xs->timeout) {
    542 			callout_reset(&xs->xs_callout, _XT(xs), isp_dog, xs);
    543 		}
    544 		break;
    545 	case TRY_AGAIN_LATER:
    546 		printf("%s: EAGAIN for %d.%d\n",
    547 		    isp->isp_name, XS_TGT(xs), XS_LUN(xs));
    548 		/* FALLTHROUGH */
    549 	case COMPLETE:
    550 		/* can only be an error */
    551 		XS_CMD_S_DONE(xs);
    552 		callout_stop(&xs->xs_callout);
    553 		if (XS_NOERR(xs)) {
    554 			XS_SETERR(xs, HBA_BOTCH);
    555 		}
    556 		scsipi_done(xs);
    557 		break;
    558 	}
    559 	(void) splx(s);
    560 }
    561 
    562 /*
    563  * Restart function after a LOOP UP event (e.g.),
    564  * done as a timeout for some hysteresis.
    565  */
    566 static void
    567 isp_internal_restart(arg)
    568 	void *arg;
    569 {
    570 	struct ispsoftc *isp = arg;
    571 	int result, nrestarted = 0, s;
    572 
    573 	s = splbio();
    574 	if (isp->isp_osinfo.blocked == 0) {
    575 		struct scsipi_xfer *xs;
    576 		while ((xs = TAILQ_FIRST(&isp->isp_osinfo.waitq)) != NULL) {
    577 			TAILQ_REMOVE(&isp->isp_osinfo.waitq, xs, adapter_q);
    578 			result = ispscsicmd(xs);
    579 			if (result != CMD_QUEUED) {
    580 				printf("%s: botched command restart (0x%x)\n",
    581 				    isp->isp_name, result);
    582 				XS_CMD_S_DONE(xs);
    583 				if (xs->error == XS_NOERROR)
    584 					xs->error = XS_DRIVER_STUFFUP;
    585 				callout_stop(&xs->xs_callout);
    586 				scsipi_done(xs);
    587 			} else if (xs->timeout) {
    588 				callout_reset(&xs->xs_callout,
    589 				    _XT(xs), isp_dog, xs);
    590 			}
    591 			nrestarted++;
    592 		}
    593 		printf("%s: requeued %d commands\n", isp->isp_name, nrestarted);
    594 	}
    595 	(void) splx(s);
    596 }
    597 
    598 int
    599 isp_async(isp, cmd, arg)
    600 	struct ispsoftc *isp;
    601 	ispasync_t cmd;
    602 	void *arg;
    603 {
    604 	int bus, tgt;
    605 	int s = splbio();
    606 	switch (cmd) {
    607 	case ISPASYNC_NEW_TGT_PARAMS:
    608 	if (IS_SCSI(isp) && isp->isp_dblev) {
    609 		sdparam *sdp = isp->isp_param;
    610 		char *wt;
    611 		int mhz, flags, period;
    612 
    613 		tgt = *((int *) arg);
    614 		bus = (tgt >> 16) & 0xffff;
    615 		tgt &= 0xffff;
    616 		sdp += bus;
    617 		flags = sdp->isp_devparam[tgt].cur_dflags;
    618 		period = sdp->isp_devparam[tgt].cur_period;
    619 
    620 		if ((flags & DPARM_SYNC) && period &&
    621 		    (sdp->isp_devparam[tgt].cur_offset) != 0) {
    622 #if	0
    623 			/* CAUSES PANICS */
    624 			static char *m = "%s: bus %d now %s mode\n";
    625 			u_int16_t r, l;
    626 			if (bus == 1)
    627 				r = SXP_PINS_DIFF | SXP_BANK1_SELECT;
    628 			else
    629 				r = SXP_PINS_DIFF;
    630 			l = ISP_READ(isp, r) & ISP1080_MODE_MASK;
    631 			switch (l) {
    632 			case ISP1080_LVD_MODE:
    633 				sdp->isp_lvdmode = 1;
    634 				printf(m, isp->isp_name, bus, "LVD");
    635 				break;
    636 			case ISP1080_HVD_MODE:
    637 				sdp->isp_diffmode = 1;
    638 				printf(m, isp->isp_name, bus, "Differential");
    639 				break;
    640 			case ISP1080_SE_MODE:
    641 				sdp->isp_ultramode = 1;
    642 				printf(m, isp->isp_name, bus, "Single-Ended");
    643 				break;
    644 			default:
    645 				printf("%s: unknown mode on bus %d (0x%x)\n",
    646 				    isp->isp_name, bus, l);
    647 				break;
    648 			}
    649 #endif
    650 			/*
    651 			 * There's some ambiguity about our negotiated speed
    652 			 * if we haven't detected LVD mode correctly (which
    653 			 * seems to happen, unfortunately). If we're in LVD
    654 			 * mode, then different rules apply about speed.
    655 			 */
    656 			if (sdp->isp_lvdmode || period < 0xc) {
    657 				switch (period) {
    658 				case 0x9:
    659 					mhz = 80;
    660 					break;
    661 				case 0xa:
    662 					mhz = 40;
    663 					break;
    664 				case 0xb:
    665 					mhz = 33;
    666 					break;
    667 				case 0xc:
    668 					mhz = 25;
    669 					break;
    670 				default:
    671 					mhz = 1000 / (period * 4);
    672 					break;
    673 				}
    674 			} else {
    675 				mhz = 1000 / (period * 4);
    676 			}
    677 		} else {
    678 			mhz = 0;
    679 		}
    680 		switch (flags & (DPARM_WIDE|DPARM_TQING)) {
    681 		case DPARM_WIDE:
    682 			wt = ", 16 bit wide\n";
    683 			break;
    684 		case DPARM_TQING:
    685 			wt = ", Tagged Queueing Enabled\n";
    686 			break;
    687 		case DPARM_WIDE|DPARM_TQING:
    688 			wt = ", 16 bit wide, Tagged Queueing Enabled\n";
    689 			break;
    690 		default:
    691 			wt = "\n";
    692 			break;
    693 		}
    694 		if (mhz) {
    695 			CFGPRINTF("%s: Bus %d Target %d at %dMHz Max "
    696 			    "Offset %d%s", isp->isp_name, bus, tgt, mhz,
    697 			    sdp->isp_devparam[tgt].cur_offset, wt);
    698 		} else {
    699 			CFGPRINTF("%s: Bus %d Target %d Async Mode%s",
    700 			    isp->isp_name, bus, tgt, wt);
    701 		}
    702 		break;
    703 	}
    704 	case ISPASYNC_BUS_RESET:
    705 		if (arg)
    706 			bus = *((int *) arg);
    707 		else
    708 			bus = 0;
    709 		printf("%s: SCSI bus %d reset detected\n", isp->isp_name, bus);
    710 		break;
    711 	case ISPASYNC_LOOP_DOWN:
    712 		/*
    713 		 * Hopefully we get here in time to minimize the number
    714 		 * of commands we are firing off that are sure to die.
    715 		 */
    716 		isp->isp_osinfo.blocked = 1;
    717 		printf("%s: Loop DOWN\n", isp->isp_name);
    718 		break;
    719         case ISPASYNC_LOOP_UP:
    720 		isp->isp_osinfo.blocked = 0;
    721 		callout_reset(&isp->isp_osinfo._restart, 1,
    722 		    isp_internal_restart, isp);
    723 		printf("%s: Loop UP\n", isp->isp_name);
    724 		break;
    725 	case ISPASYNC_PDB_CHANGED:
    726 	if (IS_FC(isp) && isp->isp_dblev) {
    727 		const char *fmt = "%s: Target %d (Loop 0x%x) Port ID 0x%x "
    728 		    "role %s %s\n Port WWN 0x%08x%08x\n Node WWN 0x%08x%08x\n";
    729 		const static char *roles[4] = {
    730 		    "No", "Target", "Initiator", "Target/Initiator"
    731 		};
    732 		char *ptr;
    733 		fcparam *fcp = isp->isp_param;
    734 		int tgt = *((int *) arg);
    735 		struct lportdb *lp = &fcp->portdb[tgt];
    736 
    737 		if (lp->valid) {
    738 			ptr = "arrived";
    739 		} else {
    740 			ptr = "disappeared";
    741 		}
    742 		printf(fmt, isp->isp_name, tgt, lp->loopid, lp->portid,
    743 		    roles[lp->roles & 0x3], ptr,
    744 		    (u_int32_t) (lp->port_wwn >> 32),
    745 		    (u_int32_t) (lp->port_wwn & 0xffffffffLL),
    746 		    (u_int32_t) (lp->node_wwn >> 32),
    747 		    (u_int32_t) (lp->node_wwn & 0xffffffffLL));
    748 		break;
    749 	}
    750 #ifdef	ISP2100_FABRIC
    751 	case ISPASYNC_CHANGE_NOTIFY:
    752 		printf("%s: Name Server Database Changed\n", isp->isp_name);
    753 		break;
    754 	case ISPASYNC_FABRIC_DEV:
    755 	{
    756 		int target;
    757 		struct lportdb *lp;
    758 		sns_scrsp_t *resp = (sns_scrsp_t *) arg;
    759 		u_int32_t portid;
    760 		u_int64_t wwn;
    761 		fcparam *fcp = isp->isp_param;
    762 
    763 		portid =
    764 		    (((u_int32_t) resp->snscb_port_id[0]) << 16) |
    765 		    (((u_int32_t) resp->snscb_port_id[1]) << 8) |
    766 		    (((u_int32_t) resp->snscb_port_id[2]));
    767 		wwn =
    768 		    (((u_int64_t)resp->snscb_portname[0]) << 56) |
    769 		    (((u_int64_t)resp->snscb_portname[1]) << 48) |
    770 		    (((u_int64_t)resp->snscb_portname[2]) << 40) |
    771 		    (((u_int64_t)resp->snscb_portname[3]) << 32) |
    772 		    (((u_int64_t)resp->snscb_portname[4]) << 24) |
    773 		    (((u_int64_t)resp->snscb_portname[5]) << 16) |
    774 		    (((u_int64_t)resp->snscb_portname[6]) <<  8) |
    775 		    (((u_int64_t)resp->snscb_portname[7]));
    776 		printf("%s: Fabric Device (Type 0x%x)@PortID 0x%x WWN "
    777 		    "0x%08x%08x\n", isp->isp_name, resp->snscb_port_type,
    778 		    portid, ((u_int32_t)(wwn >> 32)),
    779 		    ((u_int32_t)(wwn & 0xffffffff)));
    780 		if (resp->snscb_port_type != 2)
    781 			break;
    782 		for (target = FC_SNS_ID+1; target < MAX_FC_TARG; target++) {
    783 			lp = &fcp->portdb[target];
    784 			if (lp->port_wwn == wwn)
    785 				break;
    786 		}
    787 		if (target < MAX_FC_TARG) {
    788 			break;
    789 		}
    790 		for (target = FC_SNS_ID+1; target < MAX_FC_TARG; target++) {
    791 			lp = &fcp->portdb[target];
    792 			if (lp->port_wwn == 0)
    793 				break;
    794 		}
    795 		if (target == MAX_FC_TARG) {
    796 			printf("%s: no more space for fabric devices\n",
    797 			    isp->isp_name);
    798 			return (-1);
    799 		}
    800 		lp->port_wwn = lp->node_wwn = wwn;
    801 		lp->portid = portid;
    802 		break;
    803 	}
    804 #endif
    805 	default:
    806 		break;
    807 	}
    808 	(void) splx(s);
    809 	return (0);
    810 }
    811