Home | History | Annotate | Line # | Download | only in ic
isp_netbsd.c revision 1.21
      1 /* $NetBSD: isp_netbsd.c,v 1.21 1999/12/16 05:35:43 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 static void ispminphys __P((struct buf *));
     37 static int32_t ispcmd_slow __P((ISP_SCSI_XFER_T *));
     38 static int32_t ispcmd __P((ISP_SCSI_XFER_T *));
     39 static int
     40 ispioctl __P((struct scsipi_link *, u_long, caddr_t, int, struct proc *));
     41 
     42 static struct scsipi_device isp_dev = { NULL, NULL, NULL, NULL };
     43 static int isp_poll __P((struct ispsoftc *, ISP_SCSI_XFER_T *, int));
     44 static void isp_watch __P((void *));
     45 static void isp_command_requeue __P((void *));
     46 static void isp_internal_restart __P((void *));
     47 
     48 /*
     49  * Complete attachment of hardware, include subdevices.
     50  */
     51 void
     52 isp_attach(isp)
     53 	struct ispsoftc *isp;
     54 {
     55 
     56 	isp->isp_osinfo._adapter.scsipi_minphys = ispminphys;
     57 	isp->isp_osinfo._adapter.scsipi_ioctl = ispioctl;
     58 
     59 	isp->isp_state = ISP_RUNSTATE;
     60 	isp->isp_osinfo._link.scsipi_scsi.channel =
     61 	    (IS_DUALBUS(isp))? 0 : SCSI_CHANNEL_ONLY_ONE;
     62 	isp->isp_osinfo._link.adapter_softc = isp;
     63 	isp->isp_osinfo._link.device = &isp_dev;
     64 	isp->isp_osinfo._link.adapter = &isp->isp_osinfo._adapter;
     65 	isp->isp_osinfo._link.openings = isp->isp_maxcmds;
     66 	TAILQ_INIT(&isp->isp_osinfo.waitq);	/* XXX 2nd Bus? */
     67 
     68 	if (IS_FC(isp)) {
     69 		/*
     70 		 * Give it another chance here to come alive...
     71 		 */
     72 		isp->isp_osinfo._adapter.scsipi_cmd = ispcmd;
     73 		isp->isp_osinfo._link.scsipi_scsi.max_target = MAX_FC_TARG-1;
     74 #ifdef	ISP2100_SCCLUN
     75 		/*
     76 		 * 16 bits worth, but let's be reasonable..
     77 		 */
     78 		isp->isp_osinfo._link.scsipi_scsi.max_lun = 255;
     79 #else
     80 		isp->isp_osinfo._link.scsipi_scsi.max_lun = 15;
     81 #endif
     82 		/* set below */
     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 		if (isp->isp_bustype == ISP_BT_SBUS) {
     88 			isp->isp_osinfo._link.scsipi_scsi.max_lun = 7;
     89 		} else {
     90 			/*
     91 			 * Too much target breakage at present.
     92 			 */
     93 #if	0
     94 			if (isp->isp_fwrev >= ISP_FW_REV(7,55,0))
     95 				isp->isp_osinfo._link.scsipi_scsi.max_lun = 31;
     96 			else
     97 #endif
     98 				isp->isp_osinfo._link.scsipi_scsi.max_lun = 7;
     99 		}
    100 		isp->isp_osinfo._link.scsipi_scsi.adapter_target =
    101 		    sdp->isp_initiator_id;
    102 		isp->isp_osinfo.discovered[0] = 1 << sdp->isp_initiator_id;
    103 		if (IS_DUALBUS(isp)) {
    104 			isp->isp_osinfo._link_b = isp->isp_osinfo._link;
    105 			sdp++;
    106 			isp->isp_osinfo.discovered[1] =
    107 			    1 << sdp->isp_initiator_id;
    108 			isp->isp_osinfo._link_b.scsipi_scsi.adapter_target =
    109 			    sdp->isp_initiator_id;
    110 			isp->isp_osinfo._link_b.scsipi_scsi.channel = 1;
    111 		}
    112 	}
    113 	isp->isp_osinfo._link.type = BUS_SCSI;
    114 
    115 	/*
    116 	 * Send a SCSI Bus Reset (used to be done as part of attach,
    117 	 * but now left to the OS outer layers).
    118 	 */
    119 	if (IS_SCSI(isp)) {
    120 		int bus = 0;
    121 		(void) isp_control(isp, ISPCTL_RESET_BUS, &bus);
    122 		if (IS_DUALBUS(isp)) {
    123 			bus++;
    124 			(void) isp_control(isp, ISPCTL_RESET_BUS, &bus);
    125 		}
    126 		SYS_DELAY(2*1000000);
    127 	} else {
    128 		int i, j;
    129 		fcparam *fcp = isp->isp_param;
    130 		delay(2 * 1000000);
    131 		for (j = 0; j < 5; j++) {
    132 			for (i = 0; i < 5; i++) {
    133 				if (isp_control(isp, ISPCTL_FCLINK_TEST, NULL))
    134 					continue;
    135 #ifdef	ISP2100_FABRIC
    136 				/*
    137 				 * Wait extra time to see if the f/w
    138 				 * eventually completed an FLOGI that
    139 				 * will allow us to know we're on a
    140 				 * fabric.
    141 				 */
    142 				if (fcp->isp_onfabric == 0) {
    143 					delay(1 * 1000000);
    144 					continue;
    145 				}
    146 #endif
    147 				break;
    148 			}
    149 			if (fcp->isp_fwstate == FW_READY &&
    150 			    fcp->isp_loopstate >= LOOP_PDB_RCVD) {
    151 				break;
    152 			}
    153 		}
    154 		isp->isp_osinfo._link.scsipi_scsi.adapter_target =
    155 			fcp->isp_loopid;
    156 	}
    157 
    158 	/*
    159 	 * Start the watchdog.
    160 	 */
    161 	isp->isp_dogactive = 1;
    162 	timeout(isp_watch, isp, WATCH_INTERVAL * hz);
    163 
    164 	/*
    165 	 * And attach children (if any).
    166 	 */
    167 	config_found((void *)isp, &isp->isp_osinfo._link, scsiprint);
    168 	if (IS_DUALBUS(isp)) {
    169 		config_found((void *)isp, &isp->isp_osinfo._link_b, scsiprint);
    170 	}
    171 }
    172 
    173 /*
    174  * minphys our xfers
    175  *
    176  * Unfortunately, the buffer pointer describes the target device- not the
    177  * adapter device, so we can't use the pointer to find out what kind of
    178  * adapter we are and adjust accordingly.
    179  */
    180 
    181 static void
    182 ispminphys(bp)
    183 	struct buf *bp;
    184 {
    185 	/*
    186 	 * XX: Only the 1020 has a 24 bit limit.
    187 	 */
    188 	if (bp->b_bcount >= (1 << 24)) {
    189 		bp->b_bcount = (1 << 24);
    190 	}
    191 	minphys(bp);
    192 }
    193 
    194 static int32_t
    195 ispcmd_slow(xs)
    196 	ISP_SCSI_XFER_T *xs;
    197 {
    198 	sdparam *sdp;
    199 	int tgt, chan, s;
    200 	u_int16_t flags;
    201 	struct ispsoftc *isp = XS_ISP(xs);
    202 
    203 	/*
    204 	 * Have we completed discovery for this target on this adapter?
    205 	 */
    206 	tgt = XS_TGT(xs);
    207 	chan = XS_CHANNEL(xs);
    208 	if ((xs->xs_control & XS_CTL_DISCOVERY) != 0 ||
    209 	    (isp->isp_osinfo.discovered[chan] & (1 << tgt)) != 0) {
    210 		return (ispcmd(xs));
    211 	}
    212 
    213 	flags = DPARM_DEFAULT;
    214 	if (xs->sc_link->quirks & SDEV_NOSYNC) {
    215 		flags ^= DPARM_SYNC;
    216 #ifdef	DEBUG
    217 	} else {
    218 		printf("%s: channel %d target %d can do SYNC xfers\n",
    219 		    isp->isp_name, chan, tgt);
    220 #endif
    221 	}
    222 	if (xs->sc_link->quirks & SDEV_NOWIDE) {
    223 		flags ^= DPARM_WIDE;
    224 #ifdef	DEBUG
    225 	} else {
    226 		printf("%s: channel %d target %d can do WIDE xfers\n",
    227 		    isp->isp_name, chan, tgt);
    228 #endif
    229 	}
    230 	if (xs->sc_link->quirks & SDEV_NOTAG) {
    231 		flags ^= DPARM_TQING;
    232 #ifdef	DEBUG
    233 	} else {
    234 		printf("%s: channel %d target %d can do TAGGED xfers\n",
    235 		    isp->isp_name, chan, tgt);
    236 #endif
    237 	}
    238 	/*
    239 	 * Okay, we know about this device now,
    240 	 * so mark parameters to be updated for it.
    241 	 */
    242 	s = splbio();
    243 	isp->isp_osinfo.discovered[chan] |= (1 << tgt);
    244 	sdp = isp->isp_param;
    245 	sdp += chan;
    246 	sdp->isp_devparam[tgt].dev_flags = flags;
    247 	sdp->isp_devparam[tgt].dev_update = 1;
    248 	isp->isp_update |= (1 << chan);
    249 	splx(s);
    250 	return (ispcmd(xs));
    251 }
    252 
    253 static int
    254 ispioctl(sc_link, cmd, addr, flag, p)
    255 	struct scsipi_link *sc_link;
    256 	u_long cmd;
    257 	caddr_t addr;
    258 	int flag;
    259 	struct proc *p;
    260 {
    261 	struct ispsoftc *isp = sc_link->adapter_softc;
    262 	int s, chan, retval = ENOTTY;
    263 
    264 	switch (cmd) {
    265 	case SCBUSIORESET:
    266 		chan = sc_link->scsipi_scsi.channel;
    267 		s = splbio();
    268 		if (isp_control(isp, ISPCTL_RESET_BUS, &chan))
    269 			retval = EIO;
    270 		else
    271 			retval = 0;
    272 		(void) splx(s);
    273 		break;
    274 	default:
    275 		break;
    276 	}
    277 	return (retval);
    278 }
    279 
    280 
    281 static int32_t
    282 ispcmd(xs)
    283 	ISP_SCSI_XFER_T *xs;
    284 {
    285 	struct ispsoftc *isp;
    286 	int result, s;
    287 
    288 	isp = XS_ISP(xs);
    289 	s = splbio();
    290 	if (isp->isp_state < ISP_RUNSTATE) {
    291 		DISABLE_INTS(isp);
    292 		isp_init(isp);
    293                 if (isp->isp_state != ISP_INITSTATE) {
    294 			ENABLE_INTS(isp);
    295                         (void) splx(s);
    296                         XS_SETERR(xs, HBA_BOTCH);
    297                         return (COMPLETE);
    298                 }
    299                 isp->isp_state = ISP_RUNSTATE;
    300 		ENABLE_INTS(isp);
    301         }
    302 
    303 	/*
    304 	 * Check for queue blockage...
    305 	 */
    306 	if (isp->isp_osinfo.blocked) {
    307 		if (xs->xs_control & XS_CTL_POLL) {
    308 			xs->error = XS_DRIVER_STUFFUP;
    309 			splx(s);
    310 			return (TRY_AGAIN_LATER);
    311 		}
    312 		TAILQ_INSERT_TAIL(&isp->isp_osinfo.waitq, xs, adapter_q);
    313 		splx(s);
    314 		return (SUCCESSFULLY_QUEUED);
    315 	}
    316 	DISABLE_INTS(isp);
    317 	result = ispscsicmd(xs);
    318 	ENABLE_INTS(isp);
    319 
    320 	if ((xs->xs_control & XS_CTL_POLL) == 0) {
    321 		switch (result) {
    322 		case CMD_QUEUED:
    323 			result = SUCCESSFULLY_QUEUED;
    324 			break;
    325 		case CMD_EAGAIN:
    326 			result = TRY_AGAIN_LATER;
    327 			break;
    328 		case CMD_RQLATER:
    329 			result = SUCCESSFULLY_QUEUED;
    330 			timeout(isp_command_requeue, xs, hz);
    331 			break;
    332 		case CMD_COMPLETE:
    333 			result = COMPLETE;
    334 			break;
    335 		}
    336 		(void) splx(s);
    337 		return (result);
    338 	}
    339 
    340 	switch (result) {
    341 	case CMD_QUEUED:
    342 		result = SUCCESSFULLY_QUEUED;
    343 		break;
    344 	case CMD_RQLATER:
    345 	case CMD_EAGAIN:
    346 		if (XS_NOERR(xs)) {
    347 			xs->error = XS_DRIVER_STUFFUP;
    348 		}
    349 		result = TRY_AGAIN_LATER;
    350 		break;
    351 	case CMD_COMPLETE:
    352 		result = COMPLETE;
    353 		break;
    354 
    355 	}
    356 	/*
    357 	 * If we can't use interrupts, poll on completion.
    358 	 */
    359 	if (result == SUCCESSFULLY_QUEUED) {
    360 		if (isp_poll(isp, xs, XS_TIME(xs))) {
    361 			/*
    362 			 * If no other error occurred but we didn't finish,
    363 			 * something bad happened.
    364 			 */
    365 			if (XS_IS_CMD_DONE(xs) == 0) {
    366 				if (isp_control(isp, ISPCTL_ABORT_CMD, xs)) {
    367 					isp_restart(isp);
    368 				}
    369 				if (XS_NOERR(xs)) {
    370 					XS_SETERR(xs, HBA_BOTCH);
    371 				}
    372 			}
    373 		}
    374 		result = COMPLETE;
    375 	}
    376 	(void) splx(s);
    377 	return (result);
    378 }
    379 
    380 static int
    381 isp_poll(isp, xs, mswait)
    382 	struct ispsoftc *isp;
    383 	ISP_SCSI_XFER_T *xs;
    384 	int mswait;
    385 {
    386 
    387 	while (mswait) {
    388 		/* Try the interrupt handling routine */
    389 		(void)isp_intr((void *)isp);
    390 
    391 		/* See if the xs is now done */
    392 		if (XS_IS_CMD_DONE(xs)) {
    393 			return (0);
    394 		}
    395 		SYS_DELAY(1000);	/* wait one millisecond */
    396 		mswait--;
    397 	}
    398 	return (1);
    399 }
    400 
    401 static void
    402 isp_watch(arg)
    403 	void *arg;
    404 {
    405 	int i;
    406 	struct ispsoftc *isp = arg;
    407 	struct scsipi_xfer *xs;
    408 	int s;
    409 
    410 	/*
    411 	 * Look for completely dead commands (but not polled ones).
    412 	 */
    413 	s = splbio();
    414 	for (i = 0; i < isp->isp_maxcmds; i++) {
    415 		xs = isp->isp_xflist[i];
    416 		if (xs == NULL) {
    417 			continue;
    418 		}
    419 		if (xs->timeout == 0 || (xs->xs_control & XS_CTL_POLL)) {
    420 			continue;
    421 		}
    422 		xs->timeout -= (WATCH_INTERVAL * 1000);
    423 		/*
    424 		 * Avoid later thinking that this
    425 		 * transaction is not being timed.
    426 		 * Then give ourselves to watchdog
    427 		 * periods of grace.
    428 		 */
    429 		if (xs->timeout == 0) {
    430 			xs->timeout = 1;
    431 		} else if (xs->timeout > -(2 * WATCH_INTERVAL * 1000)) {
    432 			continue;
    433 		}
    434 		if (isp_control(isp, ISPCTL_ABORT_CMD, xs)) {
    435 			printf("%s: isp_watch failed to abort command\n",
    436 			    isp->isp_name);
    437 			isp_restart(isp);
    438 			break;
    439 		}
    440 	}
    441 	timeout(isp_watch, isp, WATCH_INTERVAL * hz);
    442 	isp->isp_dogactive = 1;
    443 	(void) splx(s);
    444 }
    445 
    446 /*
    447  * Free any associated resources prior to decommissioning and
    448  * set the card to a known state (so it doesn't wake up and kick
    449  * us when we aren't expecting it to).
    450  *
    451  * Locks are held before coming here.
    452  */
    453 void
    454 isp_uninit(isp)
    455 	struct ispsoftc *isp;
    456 {
    457 	ISP_ILOCKVAL_DECL;
    458 	ISP_ILOCK(isp);
    459 	/*
    460 	 * Leave with interrupts disabled.
    461 	 */
    462 	DISABLE_INTS(isp);
    463 
    464 	/*
    465 	 * Turn off the watchdog (if active).
    466 	 */
    467 	if (isp->isp_dogactive) {
    468 		untimeout(isp_watch, isp);
    469 		isp->isp_dogactive = 0;
    470 	}
    471 
    472 	ISP_IUNLOCK(isp);
    473 }
    474 
    475 /*
    476  * Restart function for a command to be requeued later.
    477  */
    478 static void
    479 isp_command_requeue(arg)
    480 	void *arg;
    481 {
    482 	struct scsipi_xfer *xs = arg;
    483 	struct ispsoftc *isp = XS_ISP(xs);
    484 	int s = splbio();
    485 	switch (ispcmd_slow(xs)) {
    486 	case SUCCESSFULLY_QUEUED:
    487 		printf("%s: isp_command_requeue: requeued for %d.%d\n",
    488 		    isp->isp_name, XS_TGT(xs), XS_LUN(xs));
    489 		break;
    490 	case TRY_AGAIN_LATER:
    491 		printf("%s: EAGAIN for %d.%d\n",
    492 		    isp->isp_name, XS_TGT(xs), XS_LUN(xs));
    493 		/* FALLTHROUGH */
    494 	case COMPLETE:
    495 		/* can only be an error */
    496 		xs->xs_status |= XS_STS_DONE;
    497 		if (XS_NOERR(xs)) {
    498 			XS_SETERR(xs, HBA_BOTCH);
    499 		}
    500 		scsipi_done(xs);
    501 		break;
    502 	}
    503 	(void) splx(s);
    504 }
    505 
    506 /*
    507  * Restart function after a LOOP UP event (e.g.),
    508  * done as a timeout for some hysteresis.
    509  */
    510 static void
    511 isp_internal_restart(arg)
    512 	void *arg;
    513 {
    514 	struct ispsoftc *isp = arg;
    515 	int result, nrestarted = 0, s;
    516 
    517 	s = splbio();
    518 	if (isp->isp_osinfo.blocked == 0) {
    519 		struct scsipi_xfer *xs;
    520 		while ((xs = TAILQ_FIRST(&isp->isp_osinfo.waitq)) != NULL) {
    521 			TAILQ_REMOVE(&isp->isp_osinfo.waitq, xs, adapter_q);
    522 			DISABLE_INTS(isp);
    523 			result = ispscsicmd(xs);
    524 			ENABLE_INTS(isp);
    525 			if (result != CMD_QUEUED) {
    526 				printf("%s: botched command restart (0x%x)\n",
    527 				    isp->isp_name, result);
    528 				xs->xs_status |= XS_STS_DONE;
    529 				if (xs->error == XS_NOERROR)
    530 					xs->error = XS_DRIVER_STUFFUP;
    531 				scsipi_done(xs);
    532 			}
    533 			nrestarted++;
    534 		}
    535 		printf("%s: requeued %d commands\n", isp->isp_name, nrestarted);
    536 	}
    537 	(void) splx(s);
    538 }
    539 
    540 int
    541 isp_async(isp, cmd, arg)
    542 	struct ispsoftc *isp;
    543 	ispasync_t cmd;
    544 	void *arg;
    545 {
    546 	int bus, tgt;
    547 	int s = splbio();
    548 	switch (cmd) {
    549 	case ISPASYNC_NEW_TGT_PARAMS:
    550 	if (IS_SCSI(isp) && isp->isp_dblev) {
    551 		sdparam *sdp = isp->isp_param;
    552 		char *wt;
    553 		int mhz, flags, period;
    554 
    555 		tgt = *((int *) arg);
    556 		bus = (tgt >> 16) & 0xffff;
    557 		tgt &= 0xffff;
    558 		sdp += bus;
    559 		flags = sdp->isp_devparam[tgt].cur_dflags;
    560 		period = sdp->isp_devparam[tgt].cur_period;
    561 
    562 		if ((flags & DPARM_SYNC) && period &&
    563 		    (sdp->isp_devparam[tgt].cur_offset) != 0) {
    564 #if	0
    565 			/* CAUSES PANICS */
    566 			static char *m = "%s: bus %d now %s mode\n";
    567 			u_int16_t r, l;
    568 			if (bus == 1)
    569 				r = SXP_PINS_DIFF | SXP_BANK1_SELECT;
    570 			else
    571 				r = SXP_PINS_DIFF;
    572 			l = ISP_READ(isp, r) & ISP1080_MODE_MASK;
    573 			switch (l) {
    574 			case ISP1080_LVD_MODE:
    575 				sdp->isp_lvdmode = 1;
    576 				printf(m, isp->isp_name, bus, "LVD");
    577 				break;
    578 			case ISP1080_HVD_MODE:
    579 				sdp->isp_diffmode = 1;
    580 				printf(m, isp->isp_name, bus, "Differential");
    581 				break;
    582 			case ISP1080_SE_MODE:
    583 				sdp->isp_ultramode = 1;
    584 				printf(m, isp->isp_name, bus, "Single-Ended");
    585 				break;
    586 			default:
    587 				printf("%s: unknown mode on bus %d (0x%x)\n",
    588 				    isp->isp_name, bus, l);
    589 				break;
    590 			}
    591 #endif
    592 			/*
    593 			 * There's some ambiguity about our negotiated speed
    594 			 * if we haven't detected LVD mode correctly (which
    595 			 * seems to happen, unfortunately). If we're in LVD
    596 			 * mode, then different rules apply about speed.
    597 			 */
    598 			if (sdp->isp_lvdmode || period < 0xc) {
    599 				switch (period) {
    600 				case 0xa:
    601 					mhz = 40;
    602 					break;
    603 				case 0xb:
    604 					mhz = 33;
    605 					break;
    606 				case 0xc:
    607 					mhz = 25;
    608 					break;
    609 				default:
    610 					mhz = 1000 / (period * 4);
    611 					break;
    612 				}
    613 			} else {
    614 				mhz = 1000 / (period * 4);
    615 			}
    616 		} else {
    617 			mhz = 0;
    618 		}
    619 		switch (flags & (DPARM_WIDE|DPARM_TQING)) {
    620 		case DPARM_WIDE:
    621 			wt = ", 16 bit wide\n";
    622 			break;
    623 		case DPARM_TQING:
    624 			wt = ", Tagged Queueing Enabled\n";
    625 			break;
    626 		case DPARM_WIDE|DPARM_TQING:
    627 			wt = ", 16 bit wide, Tagged Queueing Enabled\n";
    628 			break;
    629 		default:
    630 			wt = "\n";
    631 			break;
    632 		}
    633 		if (mhz) {
    634 			CFGPRINTF("%s: Bus %d Target %d at %dMHz Max "
    635 			    "Offset %d%s", isp->isp_name, bus, tgt, mhz,
    636 			    sdp->isp_devparam[tgt].cur_offset, wt);
    637 		} else {
    638 			CFGPRINTF("%s: Bus %d Target %d Async Mode%s",
    639 			    isp->isp_name, bus, tgt, wt);
    640 		}
    641 		break;
    642 	}
    643 	case ISPASYNC_BUS_RESET:
    644 		if (arg)
    645 			bus = *((int *) arg);
    646 		else
    647 			bus = 0;
    648 		printf("%s: SCSI bus %d reset detected\n", isp->isp_name, bus);
    649 		break;
    650 	case ISPASYNC_LOOP_DOWN:
    651 		/*
    652 		 * Hopefully we get here in time to minimize the number
    653 		 * of commands we are firing off that are sure to die.
    654 		 */
    655 		isp->isp_osinfo.blocked = 1;
    656 		printf("%s: Loop DOWN\n", isp->isp_name);
    657 		break;
    658         case ISPASYNC_LOOP_UP:
    659 		isp->isp_osinfo.blocked = 0;
    660 		timeout(isp_internal_restart, isp, 1);
    661 		printf("%s: Loop UP\n", isp->isp_name);
    662 		break;
    663 	case ISPASYNC_PDB_CHANGED:
    664 	if (IS_FC(isp) && isp->isp_dblev) {
    665 		const char *fmt = "%s: Target %d (Loop 0x%x) Port ID 0x%x "
    666 		    "role %s %s\n Port WWN 0x%08x%08x\n Node WWN 0x%08x%08x\n";
    667 		const static char *roles[4] = {
    668 		    "No", "Target", "Initiator", "Target/Initiator"
    669 		};
    670 		char *ptr;
    671 		fcparam *fcp = isp->isp_param;
    672 		int tgt = *((int *) arg);
    673 		struct lportdb *lp = &fcp->portdb[tgt];
    674 
    675 		if (lp->valid) {
    676 			ptr = "arrived";
    677 		} else {
    678 			ptr = "disappeared";
    679 		}
    680 		printf(fmt, isp->isp_name, tgt, lp->loopid, lp->portid,
    681 		    roles[lp->roles & 0x3], ptr,
    682 		    (u_int32_t) (lp->port_wwn >> 32),
    683 		    (u_int32_t) (lp->port_wwn & 0xffffffffLL),
    684 		    (u_int32_t) (lp->node_wwn >> 32),
    685 		    (u_int32_t) (lp->node_wwn & 0xffffffffLL));
    686 		break;
    687 	}
    688 #ifdef	ISP2100_FABRIC
    689 	case ISPASYNC_CHANGE_NOTIFY:
    690 		printf("%s: Name Server Database Changed\n", isp->isp_name);
    691 		break;
    692 	case ISPASYNC_FABRIC_DEV:
    693 	{
    694 		int target;
    695 		struct lportdb *lp;
    696 		sns_scrsp_t *resp = (sns_scrsp_t *) arg;
    697 		u_int32_t portid;
    698 		u_int64_t wwn;
    699 		fcparam *fcp = isp->isp_param;
    700 
    701 		portid =
    702 		    (((u_int32_t) resp->snscb_port_id[0]) << 16) |
    703 		    (((u_int32_t) resp->snscb_port_id[1]) << 8) |
    704 		    (((u_int32_t) resp->snscb_port_id[2]));
    705 		wwn =
    706 		    (((u_int64_t)resp->snscb_portname[0]) << 56) |
    707 		    (((u_int64_t)resp->snscb_portname[1]) << 48) |
    708 		    (((u_int64_t)resp->snscb_portname[2]) << 40) |
    709 		    (((u_int64_t)resp->snscb_portname[3]) << 32) |
    710 		    (((u_int64_t)resp->snscb_portname[4]) << 24) |
    711 		    (((u_int64_t)resp->snscb_portname[5]) << 16) |
    712 		    (((u_int64_t)resp->snscb_portname[6]) <<  8) |
    713 		    (((u_int64_t)resp->snscb_portname[7]));
    714 		printf("%s: Fabric Device (Type 0x%x)@PortID 0x%x WWN "
    715 		    "0x%08x%08x\n", isp->isp_name, resp->snscb_port_type,
    716 		    portid, ((u_int32_t)(wwn >> 32)),
    717 		    ((u_int32_t)(wwn & 0xffffffff)));
    718 		if (resp->snscb_port_type != 2)
    719 			break;
    720 		for (target = FC_SNS_ID+1; target < MAX_FC_TARG; target++) {
    721 			lp = &fcp->portdb[target];
    722 			if (lp->port_wwn == wwn)
    723 				break;
    724 		}
    725 		if (target < MAX_FC_TARG) {
    726 			break;
    727 		}
    728 		for (target = FC_SNS_ID+1; target < MAX_FC_TARG; target++) {
    729 			lp = &fcp->portdb[target];
    730 			if (lp->port_wwn == 0)
    731 				break;
    732 		}
    733 		if (target == MAX_FC_TARG) {
    734 			printf("%s: no more space for fabric devices\n",
    735 			    isp->isp_name);
    736 			return (-1);
    737 		}
    738 		lp->port_wwn = lp->node_wwn = wwn;
    739 		lp->portid = portid;
    740 		break;
    741 	}
    742 #endif
    743 	default:
    744 		break;
    745 	}
    746 	(void) splx(s);
    747 	return (0);
    748 }
    749