xref: /freebsd/sys/dev/isp/isp_freebsd.c (revision 6e8394b8baa7d5d9153ab90de6824bcd19b3b4e1)
1 /* $Id: isp_freebsd.c,v 1.18 1999/05/11 05:10:06 mjacob Exp $ */
2 /* release_5_11_99 */
3 /*
4  * Platform (FreeBSD) dependent common attachment code for Qlogic adapters.
5  *
6  *---------------------------------------
7  * Copyright (c) 1997, 1998 by Matthew Jacob
8  * NASA/Ames Research Center
9  * All rights reserved.
10  *---------------------------------------
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice immediately at the beginning of the file, without modification,
17  *    this list of conditions, and the following disclaimer.
18  * 2. Redistributions in binary form must reproduce the above copyright
19  *    notice, this list of conditions and the following disclaimer in the
20  *    documentation and/or other materials provided with the distribution.
21  * 3. The name of the author may not be used to endorse or promote products
22  *    derived from this software without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
28  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34  * SUCH DAMAGE.
35  */
36 #include <dev/isp/isp_freebsd.h>
37 
38 #if	__FreeBSD_version >= 300004
39 
40 static void isp_cam_async __P((void *, u_int32_t, struct cam_path *, void *));
41 static void isp_poll __P((struct cam_sim *));
42 static void isp_action __P((struct cam_sim *, union ccb *));
43 
44 void
45 isp_attach(struct ispsoftc *isp)
46 {
47 	int primary, secondary;
48 	struct ccb_setasync csa;
49 	struct cam_devq *devq;
50 	struct cam_sim *sim;
51 	struct cam_path *path;
52 
53 	/*
54 	 * Establish (in case of 12X0) which bus is the primary.
55 	 */
56 
57 	primary = 0;
58 	secondary = 1;
59 
60 	/*
61 	 * Create the device queue for our SIM(s).
62 	 */
63 	devq = cam_simq_alloc(MAXISPREQUEST);
64 	if (devq == NULL) {
65 		return;
66 	}
67 
68 	/*
69 	 * Construct our SIM entry.
70 	 */
71 	sim = cam_sim_alloc(isp_action, isp_poll, "isp", isp,
72 	    isp->isp_unit, 1, MAXISPREQUEST, devq);
73 	if (sim == NULL) {
74 		cam_simq_free(devq);
75 		return;
76 	}
77 	if (xpt_bus_register(sim, primary) != CAM_SUCCESS) {
78 		cam_sim_free(sim, TRUE);
79 		return;
80 	}
81 
82 	if (xpt_create_path(&path, NULL, cam_sim_path(sim),
83 	    CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
84 		xpt_bus_deregister(cam_sim_path(sim));
85 		cam_sim_free(sim, TRUE);
86 		return;
87 	}
88 
89 	xpt_setup_ccb(&csa.ccb_h, path, 5);
90 	csa.ccb_h.func_code = XPT_SASYNC_CB;
91 	csa.event_enable = AC_LOST_DEVICE;
92 	csa.callback = isp_cam_async;
93 	csa.callback_arg = sim;
94 	xpt_action((union ccb *)&csa);
95 	isp->isp_sim = sim;
96 	isp->isp_path = path;
97 
98 	/*
99 	 * If we have a second channel, construct SIM entry for that.
100 	 */
101 	if (IS_12X0(isp)) {
102 		sim = cam_sim_alloc(isp_action, isp_poll, "isp", isp,
103 		    isp->isp_unit, 1, MAXISPREQUEST, devq);
104 		if (sim == NULL) {
105 			xpt_bus_deregister(cam_sim_path(isp->isp_sim));
106 			xpt_free_path(isp->isp_path);
107 			cam_simq_free(devq);
108 			return;
109 		}
110 		if (xpt_bus_register(sim, secondary) != CAM_SUCCESS) {
111 			xpt_bus_deregister(cam_sim_path(isp->isp_sim));
112 			xpt_free_path(isp->isp_path);
113 			cam_sim_free(sim, TRUE);
114 			return;
115 		}
116 
117 		if (xpt_create_path(&path, NULL, cam_sim_path(sim),
118 		    CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
119 			xpt_bus_deregister(cam_sim_path(isp->isp_sim));
120 			xpt_free_path(isp->isp_path);
121 			xpt_bus_deregister(cam_sim_path(sim));
122 			cam_sim_free(sim, TRUE);
123 			return;
124 		}
125 
126 		xpt_setup_ccb(&csa.ccb_h, path, 5);
127 		csa.ccb_h.func_code = XPT_SASYNC_CB;
128 		csa.event_enable = AC_LOST_DEVICE;
129 		csa.callback = isp_cam_async;
130 		csa.callback_arg = sim;
131 		xpt_action((union ccb *)&csa);
132 		isp->isp_sim2 = sim;
133 		isp->isp_path2 = path;
134 	}
135 	if (isp->isp_state == ISP_INITSTATE)
136 		isp->isp_state = ISP_RUNSTATE;
137 }
138 
139 static void
140 isp_cam_async(void *cbarg, u_int32_t code, struct cam_path *path, void *arg)
141 {
142 	struct cam_sim *sim;
143 	struct ispsoftc *isp;
144 
145 	sim = (struct cam_sim *)cbarg;
146 	isp = (struct ispsoftc *) cam_sim_softc(sim);
147 	switch (code) {
148 	case AC_LOST_DEVICE:
149 		if (isp->isp_type & ISP_HA_SCSI) {
150 			u_int16_t oflags, nflags;
151 			sdparam *sdp = isp->isp_param;
152 			int s, tgt = xpt_path_target_id(path);
153 
154 			s = splcam();
155 			sdp += cam_sim_bus(sim);
156 			isp->isp_update |= (1 << cam_sim_bus(sim));
157 
158 			nflags = DPARM_SAFE_DFLT;
159 			if (ISP_FW_REVX(isp->isp_fwrev) >=
160 			    ISP_FW_REV(7, 55, 0)) {
161 				nflags |= DPARM_NARROW | DPARM_ASYNC;
162 			}
163 			oflags = sdp->isp_devparam[tgt].dev_flags;
164 			sdp->isp_devparam[tgt].dev_flags = nflags;
165 			sdp->isp_devparam[tgt].dev_update = 1;
166 			(void) isp_control(isp, ISPCTL_UPDATE_PARAMS, NULL);
167 			sdp->isp_devparam[tgt].dev_flags = oflags;
168 			(void) splx(s);
169 		}
170 		break;
171 	default:
172 		break;
173 	}
174 }
175 
176 static void
177 isp_poll(struct cam_sim *sim)
178 {
179 	isp_intr((struct ispsoftc *) cam_sim_softc(sim));
180 }
181 
182 
183 static void
184 isp_action(struct cam_sim *sim, union ccb *ccb)
185 {
186 	int s, tgt, error;
187 	struct ispsoftc *isp;
188 	struct ccb_trans_settings *cts;
189 
190 	CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("isp_action\n"));
191 
192 	isp = (struct ispsoftc *)cam_sim_softc(sim);
193 	ccb->ccb_h.sim_priv.entries[0].field = 0;
194 	ccb->ccb_h.sim_priv.entries[1].ptr = isp;
195 	/*
196 	 * This should only happen for Fibre Channel adapters.
197 	 * We want to pass through all but XPT_SCSI_IO (e.g.,
198 	 * path inquiry) but fail if we can't get good Fibre
199 	 * Channel link status.
200 	 */
201 	if (ccb->ccb_h.func_code == XPT_SCSI_IO &&
202 	    isp->isp_state != ISP_RUNSTATE) {
203 		s = splcam();
204 		DISABLE_INTS(isp);
205 		isp_init(isp);
206 		if (isp->isp_state != ISP_INITSTATE) {
207 			(void) splx(s);
208 			/*
209 			 * Lie. Say it was a selection timeout.
210 			 */
211 			ccb->ccb_h.status = CAM_SEL_TIMEOUT;
212 			xpt_done(ccb);
213 			return;
214 		}
215 		isp->isp_state = ISP_RUNSTATE;
216 		ENABLE_INTS(isp);
217 		(void) splx(s);
218 	}
219 
220 	IDPRINTF(4, ("%s: isp_action code %x\n", isp->isp_name,
221 	    ccb->ccb_h.func_code));
222 
223 	switch (ccb->ccb_h.func_code) {
224 	case XPT_SCSI_IO:	/* Execute the requested I/O operation */
225 		/*
226 		 * Do a couple of preliminary checks...
227 		 */
228 		if ((ccb->ccb_h.flags & CAM_CDB_POINTER) != 0) {
229 			if ((ccb->ccb_h.flags & CAM_CDB_PHYS) != 0) {
230 				ccb->ccb_h.status = CAM_REQ_INVALID;
231 				xpt_done(ccb);
232 				break;
233 			}
234 		}
235 
236 
237 		if (isp->isp_type & ISP_HA_SCSI) {
238 			if (ccb->ccb_h.target_id > (MAX_TARGETS-1)) {
239 				ccb->ccb_h.status = CAM_PATH_INVALID;
240 			} else if (ISP_FW_REVX(isp->isp_fwrev) >=
241 			    ISP_FW_REV(7, 55, 0)) {
242 				/*
243 				 * Too much breakage.
244 				 */
245 #if	0
246 				if (ccb->ccb_h.target_lun > 31) {
247 					ccb->ccb_h.status = CAM_PATH_INVALID;
248 				}
249 #else
250 				if (ccb->ccb_h.target_lun > 7) {
251 					ccb->ccb_h.status = CAM_PATH_INVALID;
252 				}
253 #endif
254 			} else if (ccb->ccb_h.target_lun > 7) {
255 				ccb->ccb_h.status = CAM_PATH_INVALID;
256 			}
257 		} else {
258 			if (ccb->ccb_h.target_id > (MAX_FC_TARG-1)) {
259 				ccb->ccb_h.status = CAM_PATH_INVALID;
260 #ifdef	SCCLUN
261 			} else if (ccb->ccb_h.target_lun > 15) {
262 				ccb->ccb_h.status = CAM_PATH_INVALID;
263 #else
264 			} else if (ccb->ccb_h.target_lun > 65535) {
265 				ccb->ccb_h.status = CAM_PATH_INVALID;
266 #endif
267 			}
268 		}
269 		if (ccb->ccb_h.status == CAM_PATH_INVALID) {
270 			printf("%s: invalid tgt/lun (%d.%d) in XPT_SCSI_IO\n",
271 			    isp->isp_name, ccb->ccb_h.target_id,
272 			    ccb->ccb_h.target_lun);
273 			xpt_done(ccb);
274 			break;
275 		}
276 		s = splcam();
277 		DISABLE_INTS(isp);
278 		switch (ispscsicmd((ISP_SCSI_XFER_T *) ccb)) {
279 		case CMD_QUEUED:
280 			ccb->ccb_h.status |= CAM_SIM_QUEUED;
281 			break;
282 		case CMD_EAGAIN:
283 			if (!(isp->isp_osinfo.simqfrozen & SIMQFRZ_RESOURCE)) {
284 				xpt_freeze_simq(sim, 1);
285 				isp->isp_osinfo.simqfrozen |= SIMQFRZ_RESOURCE;
286 			}
287 			ccb->ccb_h.status &= ~CAM_STATUS_MASK;
288                         ccb->ccb_h.status |= CAM_REQUEUE_REQ;
289 			xpt_done(ccb);
290 			break;
291 		case CMD_COMPLETE:
292 			/*
293 			 * Just make sure that we didn't get it returned
294 			 * as completed, but with the request still in
295 			 * progress. In theory, 'cannot happen'.
296 			 */
297 			if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
298 			    CAM_REQ_INPROG) {
299 				ccb->ccb_h.status &= ~CAM_STATUS_MASK;
300 				ccb->ccb_h.status |= CAM_REQ_CMP_ERR;
301 			}
302 			xpt_done(ccb);
303 			break;
304 		}
305 		ENABLE_INTS(isp);
306 		splx(s);
307 		break;
308 
309 	case XPT_EN_LUN:		/* Enable LUN as a target */
310 	case XPT_TARGET_IO:		/* Execute target I/O request */
311 	case XPT_ACCEPT_TARGET_IO:	/* Accept Host Target Mode CDB */
312 	case XPT_CONT_TARGET_IO:	/* Continue Host Target I/O Connection*/
313 		ccb->ccb_h.status = CAM_REQ_INVALID;
314 		xpt_done(ccb);
315 		break;
316 
317 	case XPT_RESET_DEV:		/* BDR the specified SCSI device */
318 		tgt = ccb->ccb_h.target_id; /* XXX: Which Bus? */
319 		s = splcam();
320 		error = isp_control(isp, ISPCTL_RESET_DEV, &tgt);
321 		(void) splx(s);
322 		if (error) {
323 			ccb->ccb_h.status = CAM_REQ_CMP_ERR;
324 		} else {
325 			ccb->ccb_h.status = CAM_REQ_CMP;
326 		}
327 		xpt_done(ccb);
328 		break;
329 	case XPT_ABORT:			/* Abort the specified CCB */
330 		s = splcam();
331 		error = isp_control(isp, ISPCTL_ABORT_CMD, ccb);
332 		(void) splx(s);
333 		if (error) {
334 			ccb->ccb_h.status = CAM_REQ_CMP_ERR;
335 		} else {
336 			ccb->ccb_h.status = CAM_REQ_CMP;
337 		}
338 		xpt_done(ccb);
339 		break;
340 
341 	case XPT_SET_TRAN_SETTINGS:	/* Nexus Settings */
342 
343 		cts = &ccb->cts;
344 		tgt = cts->ccb_h.target_id;
345 		s = splcam();
346 		if (isp->isp_type & ISP_HA_FC) {
347 			;	/* nothing to change */
348 		} else {
349 			sdparam *sdp = isp->isp_param;
350 			u_int16_t *dptr;
351 			int bus = cam_sim_bus(xpt_path_sim(cts->ccb_h.path));
352 
353 			sdp += bus;
354 #if	0
355 			if (cts->flags & CCB_TRANS_CURRENT_SETTINGS)
356 				dptr = &sdp->isp_devparam[tgt].cur_dflags;
357 			else
358 				dptr = &sdp->isp_devparam[tgt].dev_flags;
359 #else
360 			/*
361 			 * We always update (internally) from dev_flags
362 			 * so any request to change settings just gets
363 			 * vectored to that location.
364 			 */
365 			dptr = &sdp->isp_devparam[tgt].dev_flags;
366 #endif
367 
368 			/*
369 			 * Note that these operations affect the
370 			 * the goal flags (dev_flags)- not
371 			 * the current state flags. Then we mark
372 			 * things so that the next operation to
373 			 * this HBA will cause the update to occur.
374 			 */
375 			if (cts->valid & CCB_TRANS_DISC_VALID) {
376 				if ((cts->flags & CCB_TRANS_DISC_ENB) != 0) {
377 					*dptr |= DPARM_DISC;
378 				} else {
379 					*dptr &= ~DPARM_DISC;
380 				}
381 			}
382 			if (cts->valid & CCB_TRANS_TQ_VALID) {
383 				if ((cts->flags & CCB_TRANS_TAG_ENB) != 0) {
384 					*dptr |= DPARM_TQING;
385 				} else {
386 					*dptr &= ~DPARM_TQING;
387 				}
388 			}
389 			if (cts->valid & CCB_TRANS_BUS_WIDTH_VALID) {
390 				switch (cts->bus_width) {
391 				case MSG_EXT_WDTR_BUS_16_BIT:
392 					*dptr |= DPARM_WIDE;
393 					break;
394 				default:
395 					*dptr &= ~DPARM_WIDE;
396 				}
397 			}
398 			/*
399 			 * Any SYNC RATE of nonzero and SYNC_OFFSET
400 			 * of nonzero will cause us to go to the
401 			 * selected (from NVRAM) maximum value for
402 			 * this device. At a later point, we'll
403 			 * allow finer control.
404 			 */
405 			if ((cts->valid & CCB_TRANS_SYNC_RATE_VALID) &&
406 			    (cts->valid & CCB_TRANS_SYNC_OFFSET_VALID) &&
407 			    (cts->sync_offset > 0)) {
408 				*dptr |= DPARM_SYNC;
409 			} else {
410 				*dptr &= ~DPARM_SYNC;
411 			}
412 			if (bootverbose || isp->isp_dblev >= 3)
413 				printf("%s: %d.%d set %s period 0x%x offset "
414 				    "0x%x flags 0x%x\n", isp->isp_name, bus,
415 				    tgt,
416 				    (cts->flags & CCB_TRANS_CURRENT_SETTINGS)?
417 				    "current" : "user",
418 				    sdp->isp_devparam[tgt].sync_period,
419 				    sdp->isp_devparam[tgt].sync_offset,
420 				    sdp->isp_devparam[tgt].dev_flags);
421 			s = splcam();
422 			sdp->isp_devparam[tgt].dev_update = 1;
423 			isp->isp_update |= (1 << bus);
424 			(void) isp_control(isp, ISPCTL_UPDATE_PARAMS, NULL);
425 			(void) splx(s);
426 		}
427 		(void) splx(s);
428 		ccb->ccb_h.status = CAM_REQ_CMP;
429 		xpt_done(ccb);
430 		break;
431 
432 	case XPT_GET_TRAN_SETTINGS:
433 
434 		cts = &ccb->cts;
435 		tgt = cts->ccb_h.target_id;
436 		if (isp->isp_type & ISP_HA_FC) {
437 			/*
438 			 * a lot of normal SCSI things don't make sense.
439 			 */
440 			cts->flags = CCB_TRANS_TAG_ENB | CCB_TRANS_DISC_ENB;
441 			cts->valid = CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID;
442 			/*
443 			 * How do you measure the width of a high
444 			 * speed serial bus? Well, in bytes.
445 			 *
446 			 * Offset and period make no sense, though, so we set
447 			 * (above) a 'base' transfer speed to be gigabit.
448 			 */
449 			cts->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
450 		} else {
451 			sdparam *sdp = isp->isp_param;
452 			u_int16_t dval, pval, oval;
453 			int bus = cam_sim_bus(xpt_path_sim(cts->ccb_h.path));
454 
455 			sdp += bus;
456 			if (cts->flags & CCB_TRANS_CURRENT_SETTINGS) {
457 				s = splcam();
458 				/*
459 				 * First do a refresh to see if things
460 				 * have changed recently!
461 				 */
462 				sdp->isp_devparam[tgt].dev_refresh = 1;
463 				isp->isp_update |= (1 << bus);
464 				(void) isp_control(isp, ISPCTL_UPDATE_PARAMS,
465 				    NULL);
466 				(void) splx(s);
467 				dval = sdp->isp_devparam[tgt].cur_dflags;
468 				oval = sdp->isp_devparam[tgt].cur_offset;
469 				pval = sdp->isp_devparam[tgt].cur_period;
470 			} else {
471 				dval = sdp->isp_devparam[tgt].dev_flags;
472 				oval = sdp->isp_devparam[tgt].sync_offset;
473 				pval = sdp->isp_devparam[tgt].sync_period;
474 			}
475 
476 			s = splcam();
477 			cts->flags &= ~(CCB_TRANS_DISC_ENB|CCB_TRANS_TAG_ENB);
478 
479 			if (dval & DPARM_DISC) {
480 				cts->flags |= CCB_TRANS_DISC_ENB;
481 			}
482 			if (dval & DPARM_TQING) {
483 				cts->flags |= CCB_TRANS_TAG_ENB;
484 			}
485 			if (dval & DPARM_WIDE) {
486 				cts->bus_width = MSG_EXT_WDTR_BUS_16_BIT;
487 			} else {
488 				cts->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
489 			}
490 			cts->valid = CCB_TRANS_BUS_WIDTH_VALID |
491 			    CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID;
492 
493 			if ((dval & DPARM_SYNC) && oval != 0) {
494 				cts->sync_period = pval;
495 				cts->sync_offset = oval;
496 				cts->valid |=
497 				    CCB_TRANS_SYNC_RATE_VALID |
498 				    CCB_TRANS_SYNC_OFFSET_VALID;
499 			}
500 			splx(s);
501 			if (bootverbose || isp->isp_dblev >= 3)
502 				printf("%s: %d.%d get %s period 0x%x offset "
503 				    "0x%x flags 0x%x\n", isp->isp_name, bus,
504 				    tgt,
505 			    	    (cts->flags & CCB_TRANS_CURRENT_SETTINGS)?
506 				    "current" : "user", pval, oval, dval);
507 		}
508 		ccb->ccb_h.status = CAM_REQ_CMP;
509 		xpt_done(ccb);
510 		break;
511 
512 	case XPT_CALC_GEOMETRY:
513 	{
514 		struct ccb_calc_geometry *ccg;
515 		u_int32_t secs_per_cylinder;
516 		u_int32_t size_mb;
517 
518 		ccg = &ccb->ccg;
519 		if (ccg->block_size == 0) {
520 			printf("%s: %d.%d XPT_CALC_GEOMETRY block size 0?\n",
521 				isp->isp_name, ccg->ccb_h.target_id,
522 				ccg->ccb_h.target_lun);
523 			ccb->ccb_h.status = CAM_REQ_INVALID;
524 			xpt_done(ccb);
525 			break;
526 		}
527 		size_mb = ccg->volume_size /((1024L * 1024L) / ccg->block_size);
528 		if (size_mb > 1024) {
529 			ccg->heads = 255;
530 			ccg->secs_per_track = 63;
531 		} else {
532 			ccg->heads = 64;
533 			ccg->secs_per_track = 32;
534 		}
535 		secs_per_cylinder = ccg->heads * ccg->secs_per_track;
536 		ccg->cylinders = ccg->volume_size / secs_per_cylinder;
537 		ccb->ccb_h.status = CAM_REQ_CMP;
538 		xpt_done(ccb);
539 		break;
540 	}
541 	case XPT_RESET_BUS:		/* Reset the specified bus */
542 		tgt = cam_sim_bus(sim);
543 		s = splcam();
544 		error = isp_control(isp, ISPCTL_RESET_BUS, &tgt);
545 		(void) splx(s);
546 		if (error)
547 			ccb->ccb_h.status = CAM_REQ_CMP_ERR;
548 		else {
549 			if (cam_sim_bus(sim) && isp->isp_path2 != NULL)
550 				xpt_async(AC_BUS_RESET, isp->isp_path2, NULL);
551 			else if (isp->isp_path != NULL)
552 				xpt_async(AC_BUS_RESET, isp->isp_path, NULL);
553 			ccb->ccb_h.status = CAM_REQ_CMP;
554 		}
555 		xpt_done(ccb);
556 		break;
557 
558 	case XPT_TERM_IO:		/* Terminate the I/O process */
559 		/* Does this need to be implemented? */
560 		ccb->ccb_h.status = CAM_REQ_INVALID;
561 		xpt_done(ccb);
562 		break;
563 
564 	case XPT_PATH_INQ:		/* Path routing inquiry */
565 	{
566 		struct ccb_pathinq *cpi = &ccb->cpi;
567 
568 		cpi->version_num = 1;
569 		cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE|PI_WIDE_16;
570 		cpi->target_sprt = 0;
571 		cpi->hba_eng_cnt = 0;
572 		if (IS_FC(isp)) {
573 			cpi->hba_misc = PIM_NOBUSRESET;
574 			cpi->max_target = MAX_FC_TARG-1;
575 			cpi->initiator_id =
576 			    ((fcparam *)isp->isp_param)->isp_loopid;
577 #ifdef	SCCLUN
578 			cpi->max_lun = (1 << 16) - 1;
579 #else
580 			cpi->max_lun = (1 << 4) - 1;
581 #endif
582 			/*
583 			 * Set base transfer capabilities for Fibre Channel.
584 			 * Technically not correct because we don't know
585 			 * what media we're running on top of- but we'll
586 			 * look good if we always say 100MB/s.
587 			 */
588 			cpi->base_transfer_speed = 100000;
589 		} else {
590 			sdparam *sdp = isp->isp_param;
591 			sdp += cam_sim_bus(xpt_path_sim(cpi->ccb_h.path));
592 			cpi->hba_misc = 0;
593 			cpi->initiator_id = sdp->isp_initiator_id;
594 			cpi->max_target =  MAX_TARGETS-1;
595 			if (ISP_FW_REVX(isp->isp_fwrev) >=
596 			    ISP_FW_REV(7, 55, 0)) {
597 #if	0
598 				/*
599 				 * Too much breakage.
600 				 */
601 				cpi->max_lun = (1 << 5) - 1;
602 #else
603 				cpi->max_lun = (1 << 3) - 1;
604 #endif
605 			} else {
606 				cpi->max_lun = (1 << 3) - 1;
607 			}
608 			cpi->base_transfer_speed = 3300;
609 		}
610 
611 		cpi->bus_id = cam_sim_bus(sim);
612 		strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
613 		strncpy(cpi->hba_vid, "Qlogic", HBA_IDLEN);
614 		strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
615 		cpi->unit_number = cam_sim_unit(sim);
616 		cpi->ccb_h.status = CAM_REQ_CMP;
617 		xpt_done(ccb);
618 		break;
619 	}
620 	default:
621 		ccb->ccb_h.status = CAM_REQ_INVALID;
622 		xpt_done(ccb);
623 		break;
624 	}
625 }
626 
627 #define	ISPDDB	(CAM_DEBUG_INFO|CAM_DEBUG_TRACE|CAM_DEBUG_CDB)
628 void
629 isp_done(struct ccb_scsiio *sccb)
630 {
631 	struct ispsoftc *isp = XS_ISP(sccb);
632 
633 	if (XS_NOERR(sccb))
634 		XS_SETERR(sccb, CAM_REQ_CMP);
635 	sccb->ccb_h.status &= ~CAM_STATUS_MASK;
636 	sccb->ccb_h.status |= sccb->ccb_h.spriv_field0;
637 	if ((sccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP &&
638 	    (sccb->scsi_status != SCSI_STATUS_OK)) {
639 		sccb->ccb_h.status &= ~CAM_STATUS_MASK;
640 		sccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR;
641 	}
642 	if ((sccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
643 		if ((sccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
644 			IDPRINTF(3, ("%s: freeze devq %d.%d ccbstat 0x%x\n",
645 			    isp->isp_name, sccb->ccb_h.target_id,
646 			    sccb->ccb_h.target_lun, sccb->ccb_h.status));
647 			xpt_freeze_devq(sccb->ccb_h.path, 1);
648 			sccb->ccb_h.status |= CAM_DEV_QFRZN;
649 		}
650 	}
651 	if (isp->isp_osinfo.simqfrozen & SIMQFRZ_RESOURCE) {
652 		isp->isp_osinfo.simqfrozen &= ~SIMQFRZ_RESOURCE;
653 		sccb->ccb_h.status |= CAM_RELEASE_SIMQ;
654 		xpt_release_simq(isp->isp_sim, 1);
655 	}
656 	sccb->ccb_h.status &= ~CAM_SIM_QUEUED;
657 	if (CAM_DEBUGGED(sccb->ccb_h.path, ISPDDB) &&
658 	    (sccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
659 		xpt_print_path(sccb->ccb_h.path);
660 		printf("cam completion status 0x%x\n", sccb->ccb_h.status);
661 	}
662 	xpt_done((union ccb *) sccb);
663 }
664 
665 int
666 isp_async(isp, cmd, arg)
667 	struct ispsoftc *isp;
668 	ispasync_t cmd;
669 	void *arg;
670 {
671 	int bus, rv = 0;
672 	switch (cmd) {
673 	case ISPASYNC_NEW_TGT_PARAMS:
674 		if (isp->isp_type & ISP_HA_SCSI) {
675 			int flags, tgt;
676 			sdparam *sdp = isp->isp_param;
677 			struct ccb_trans_settings neg;
678 			struct cam_path *tmppath;
679 
680 			tgt = *((int *)arg);
681 			bus = (tgt >> 16) & 0xffff;
682 			tgt &= 0xffff;
683 			sdp += bus;
684 			if (xpt_create_path(&tmppath, NULL,
685 			    cam_sim_path(bus? isp->isp_sim2 : isp->isp_sim),
686 			    tgt, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
687 				xpt_print_path(isp->isp_path);
688 				printf("isp_async cannot make temp path for "
689 				    "target %d bus %d\n", tgt, bus);
690 				rv = -1;
691 				break;
692 			}
693 			flags = sdp->isp_devparam[tgt].cur_dflags;
694 			neg.valid = CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID;
695 			if (flags & DPARM_DISC) {
696 				neg.flags |= CCB_TRANS_DISC_ENB;
697 			}
698 			if (flags & DPARM_TQING) {
699 				neg.flags |= CCB_TRANS_TAG_ENB;
700 			}
701 			neg.valid |= CCB_TRANS_BUS_WIDTH_VALID;
702 			neg.bus_width = (flags & DPARM_WIDE)?
703 			    MSG_EXT_WDTR_BUS_8_BIT : MSG_EXT_WDTR_BUS_16_BIT;
704 			neg.sync_period = sdp->isp_devparam[tgt].cur_period;
705 			neg.sync_offset = sdp->isp_devparam[tgt].cur_offset;
706 			if (flags & DPARM_SYNC) {
707 				neg.valid |=
708 				    CCB_TRANS_SYNC_RATE_VALID |
709 				    CCB_TRANS_SYNC_OFFSET_VALID;
710 			}
711 			IDPRINTF(3, ("%s: NEW_TGT_PARAMS bus %d tgt %d period "
712 			    "0x%x offset 0x%x flags 0x%x\n", isp->isp_name,
713 			    bus, tgt, neg.sync_period, neg.sync_offset, flags));
714 			xpt_setup_ccb(&neg.ccb_h, tmppath, 1);
715 			xpt_async(AC_TRANSFER_NEG, tmppath, &neg);
716 			xpt_free_path(tmppath);
717 		}
718 		break;
719 	case ISPASYNC_BUS_RESET:
720 		bus = *((int *)arg);
721 		printf("%s: SCSI bus reset on bus %d detected\n",
722 		    isp->isp_name, bus);
723 		if (bus > 0 && isp->isp_path2) {
724 			xpt_async(AC_BUS_RESET, isp->isp_path2, NULL);
725 		} else if (isp->isp_path) {
726 			xpt_async(AC_BUS_RESET, isp->isp_path, NULL);
727 		}
728 		break;
729 	case ISPASYNC_LOOP_DOWN:
730 		if (isp->isp_path) {
731 			/*
732 			 * We can get multiple LOOP downs, so only count one.
733 			 */
734 			if (!(isp->isp_osinfo.simqfrozen & SIMQFRZ_LOOPDOWN)) {
735 				xpt_freeze_simq(isp->isp_sim, 1);
736 				isp->isp_osinfo.simqfrozen |= SIMQFRZ_LOOPDOWN;
737 				printf("%s: Loop DOWN- freezing SIMQ until Loop"
738 				    " comes up\n", isp->isp_name);
739 			}
740 		} else {
741 			printf("%s: Loop DOWN\n", isp->isp_name);
742 		}
743 		break;
744 	case ISPASYNC_LOOP_UP:
745 		if (isp->isp_path) {
746 			if (isp->isp_osinfo.simqfrozen & SIMQFRZ_LOOPDOWN) {
747 				xpt_release_simq(isp->isp_sim, 1);
748 				isp->isp_osinfo.simqfrozen &= ~SIMQFRZ_LOOPDOWN;
749 				if (isp->isp_osinfo.simqfrozen) {
750 					printf("%s: Loop UP- SIMQ still "
751 					    "frozen\n", isp->isp_name);
752 				} else {
753 					printf("%s: Loop UP-releasing frozen "
754 					    "SIMQ\n", isp->isp_name);
755 				}
756 			}
757 		} else {
758 			printf("%s: Loop UP\n", isp->isp_name);
759 		}
760 		break;
761 	case ISPASYNC_PDB_CHANGE_COMPLETE:
762 	if (IS_FC(isp)) {
763 		long i = (long) arg;
764 		static char *roles[4] = {
765 		    "No", "Target", "Initiator", "Target/Initiator"
766 		};
767 		isp_pdb_t *pdbp = &((fcparam *)isp->isp_param)->isp_pdb[i];
768 		if (pdbp->pdb_options == INVALID_PDB_OPTIONS) {
769 			break;
770 		}
771 		printf("%s: Loop ID %d, %s role\n", isp->isp_name,
772 		    pdbp->pdb_loopid, roles[(pdbp->pdb_prli_svc3 >> 4) & 0x3]);
773 		printf("     Node Address 0x%x WWN 0x"
774 		    "%02x%02x%02x%02x%02x%02x%02x%02x\n",
775 		    BITS2WORD(pdbp->pdb_portid_bits),
776 		    pdbp->pdb_portname[0], pdbp->pdb_portname[1],
777 		    pdbp->pdb_portname[2], pdbp->pdb_portname[3],
778 		    pdbp->pdb_portname[4], pdbp->pdb_portname[5],
779 		    pdbp->pdb_portname[6], pdbp->pdb_portname[7]);
780 		if (pdbp->pdb_options & PDB_OPTIONS_ADISC)
781 			printf("     Hard Address 0x%x WWN 0x"
782 			    "%02x%02x%02x%02x%02x%02x%02x%02x\n",
783 			    BITS2WORD(pdbp->pdb_hardaddr_bits),
784 			    pdbp->pdb_nodename[0], pdbp->pdb_nodename[1],
785 			    pdbp->pdb_nodename[2], pdbp->pdb_nodename[3],
786 			    pdbp->pdb_nodename[4], pdbp->pdb_nodename[5],
787 			    pdbp->pdb_nodename[6], pdbp->pdb_nodename[7]);
788 		switch (pdbp->pdb_prli_svc3 & SVC3_ROLE_MASK) {
789 		case SVC3_TGT_ROLE|SVC3_INI_ROLE:
790 			printf("     Master State=%s, Slave State=%s\n",
791 			    isp2100_pdb_statename(pdbp->pdb_mstate),
792 			    isp2100_pdb_statename(pdbp->pdb_sstate));
793 			break;
794 		case SVC3_TGT_ROLE:
795 			printf("     Master State=%s\n",
796 			    isp2100_pdb_statename(pdbp->pdb_mstate));
797 			break;
798 		case SVC3_INI_ROLE:
799 			printf("     Slave State=%s\n",
800 			    isp2100_pdb_statename(pdbp->pdb_sstate));
801 			break;
802 		default:
803 			break;
804 		}
805 		break;
806 	}
807 	case ISPASYNC_CHANGE_NOTIFY:
808 		printf("%s: Name Server Database Changed\n", isp->isp_name);
809 		break;
810 	default:
811 		break;
812 	}
813 	return (rv);
814 }
815 
816 
817 /*
818  * Locks are held before coming here.
819  */
820 void
821 isp_uninit(struct ispsoftc *isp)
822 {
823 	ISP_WRITE(isp, HCCR, HCCR_CMD_RESET);
824 	DISABLE_INTS(isp);
825 }
826 #else
827 
828 #define WATCH_INTERVAL          30
829 
830 static void ispminphys __P((struct buf *));
831 static u_int32_t isp_adapter_info __P((int));
832 static int ispcmd __P((ISP_SCSI_XFER_T *));
833 static void isp_watch __P((void *arg));
834 
835 static struct scsi_adapter isp_switch = {
836 	ispcmd, ispminphys, 0, 0, isp_adapter_info, "isp", { 0, 0 }
837 };
838 static struct scsi_device isp_dev = {
839 	NULL, NULL, NULL, NULL, "isp", 0, { 0, 0 }
840 };
841 static int isp_poll __P((struct ispsoftc *, ISP_SCSI_XFER_T *, int));
842 
843 
844 /*
845  * Complete attachment of hardware, include subdevices.
846  */
847 void
848 isp_attach(struct ispsoftc *isp)
849 {
850 	struct scsibus_data *scbus;
851 
852 	scbus = scsi_alloc_bus();
853 	if(!scbus) {
854 		return;
855 	}
856 	if (isp->isp_state == ISP_INITSTATE)
857 		isp->isp_state = ISP_RUNSTATE;
858 
859         timeout(isp_watch, isp, WATCH_INTERVAL * hz);
860 	isp->isp_dogactive = 1;
861 
862 	isp->isp_osinfo._link.adapter_unit = isp->isp_osinfo.unit;
863 	isp->isp_osinfo._link.adapter_softc = isp;
864 	isp->isp_osinfo._link.adapter = &isp_switch;
865 	isp->isp_osinfo._link.device = &isp_dev;
866 	isp->isp_osinfo._link.flags = 0;
867 	if (isp->isp_type & ISP_HA_FC) {
868 		isp->isp_osinfo._link.adapter_targ =
869 			((fcparam *)isp->isp_param)->isp_loopid;
870 		scbus->maxtarg = MAX_FC_TARG-1;
871 	} else {
872 		int tmp = 0;	/* XXXX: Which Bus? */
873 		isp->isp_osinfo.delay_throttle_count = 1;
874 		isp->isp_osinfo._link.adapter_targ =
875 			((sdparam *)isp->isp_param)->isp_initiator_id;
876 		scbus->maxtarg = MAX_TARGETS-1;
877 		(void) isp_control(isp, ISPCTL_RESET_BUS, &tmp);
878 	}
879 
880 	/*
881 	 * Prepare the scsibus_data area for the upperlevel scsi code.
882 	 */
883 	scbus->adapter_link = &isp->isp_osinfo._link;
884 
885 	/*
886 	 * ask the adapter what subunits are present
887 	 */
888 	scsi_attachdevs(scbus);
889 }
890 
891 
892 /*
893  * minphys our xfers
894  *
895  * Unfortunately, the buffer pointer describes the target device- not the
896  * adapter device, so we can't use the pointer to find out what kind of
897  * adapter we are and adjust accordingly.
898  */
899 
900 static void
901 ispminphys(struct buf *bp)
902 {
903 	/*
904 	 * Only the 10X0 has a 24 bit limit.
905 	 */
906 	if (bp->b_bcount >= (1 << 24)) {
907 		bp->b_bcount = (1 << 24);
908 	}
909 }
910 
911 static u_int32_t
912 isp_adapter_info(int unit)
913 {
914 	/*
915  	 * XXX: FIND ISP BASED UPON UNIT AND GET REAL QUEUE LIMIT FROM THAT
916 	 */
917 	return (2);
918 }
919 
920 static int
921 ispcmd(ISP_SCSI_XFER_T *xs)
922 {
923 	struct ispsoftc *isp;
924 	int r, s;
925 
926 	isp = XS_ISP(xs);
927 	s = splbio();
928 	DISABLE_INTS(isp);
929 	if (isp->isp_state != ISP_RUNSTATE) {
930 		isp_init(isp);
931 		if (isp->isp_state != ISP_INITSTATE) {
932 			ENABLE_INTS(isp);
933 			(void) splx(s);
934 			XS_SETERR(xs, HBA_BOTCH);
935 			return (CMD_COMPLETE);
936 		}
937 		isp->isp_state = ISP_RUNSTATE;
938 	}
939 	r = ispscsicmd(xs);
940 	ENABLE_INTS(isp);
941 	if (r != CMD_QUEUED || (xs->flags & SCSI_NOMASK) == 0) {
942 		(void) splx(s);
943 		return (r);
944 	}
945 
946 	/*
947 	 * If we can't use interrupts, poll on completion.
948 	 */
949 	if (isp_poll(isp, xs, XS_TIME(xs))) {
950 		/*
951 		 * If no other error occurred but we didn't finish,
952 		 * something bad happened.
953 		 */
954 		if (XS_IS_CMD_DONE(xs) == 0) {
955 			isp->isp_nactive--;
956 			if (isp->isp_nactive < 0)
957 				isp->isp_nactive = 0;
958 			if (XS_NOERR(xs)) {
959 				isp_lostcmd(isp, xs);
960 				XS_SETERR(xs, HBA_BOTCH);
961 			}
962 		}
963 	}
964 	(void) splx(s);
965 	return (CMD_COMPLETE);
966 }
967 
968 static int
969 isp_poll(struct ispsoftc *isp, ISP_SCSI_XFER_T *xs, int mswait)
970 {
971 
972 	while (mswait) {
973 		/* Try the interrupt handling routine */
974 		(void)isp_intr((void *)isp);
975 
976 		/* See if the xs is now done */
977 		if (XS_IS_CMD_DONE(xs))
978 			return (0);
979 		SYS_DELAY(1000);	/* wait one millisecond */
980 		mswait--;
981 	}
982 	return (1);
983 }
984 
985 static void
986 isp_watch(void *arg)
987 {
988 	int i;
989 	struct ispsoftc *isp = arg;
990 	ISP_SCSI_XFER_T *xs;
991 	int s;
992 
993 	/*
994 	 * Look for completely dead commands (but not polled ones).
995 	 */
996 	s = splbio();
997 	for (i = 0; i < RQUEST_QUEUE_LEN; i++) {
998 		if ((xs = (ISP_SCSI_XFER_T *) isp->isp_xflist[i]) == NULL) {
999 			continue;
1000 		}
1001 		if (XS_TIME(xs) == 0) {
1002 			continue;
1003 		}
1004 		XS_TIME(xs) -= (WATCH_INTERVAL * 1000);
1005 
1006 		/*
1007 		 * Avoid later thinking that this
1008 		 * transaction is not being timed.
1009 		 * Then give ourselves to watchdog
1010 		 * periods of grace.
1011 		 */
1012 		if (XS_TIME(xs) == 0)
1013 			XS_TIME(xs) = 1;
1014 		else if (XS_TIME(xs) > -(2 * WATCH_INTERVAL * 1000)) {
1015 			continue;
1016 		}
1017 		if (IS_SCSI(isp)) {
1018 			isp->isp_osinfo.delay_throttle_count = 1;
1019 		}
1020 		if (isp_control(isp, ISPCTL_ABORT_CMD, xs)) {
1021 			printf("%s: isp_watch failed to abort command\n",
1022 			    isp->isp_name);
1023 			isp_restart(isp);
1024 			break;
1025 		}
1026 	}
1027 	if (isp->isp_osinfo.delay_throttle_count) {
1028 		if (--isp->isp_osinfo.delay_throttle_count == 0) {
1029 			sdparam *sdp = isp->isp_param;
1030 			for (i = 0; i < MAX_TARGETS; i++) {
1031 				sdp->isp_devparam[i].dev_flags |=
1032 					DPARM_WIDE|DPARM_SYNC|DPARM_TQING;
1033 				sdp->isp_devparam[i].dev_update = 1;
1034 			}
1035 			isp->isp_update = 1;
1036 		}
1037 	}
1038         timeout(isp_watch, isp, WATCH_INTERVAL * hz);
1039 	isp->isp_dogactive = 1;
1040 	splx(s);
1041 }
1042 
1043 int
1044 isp_async(isp, cmd, arg)
1045 	struct ispsoftc *isp;
1046 	ispasync_t cmd;
1047 	void *arg;
1048 {
1049 	switch (cmd) {
1050 	case ISPASYNC_NEW_TGT_PARAMS:
1051 		if (isp->isp_type & ISP_HA_SCSI) {
1052 			sdparam *sdp = isp->isp_param;
1053 			char *wt;
1054 			int mhz, flags, tgt, period;
1055 
1056 			tgt = *((int *) arg);
1057 
1058 			flags = sdp->isp_devparam[tgt].cur_dflags;
1059 			period = sdp->isp_devparam[tgt].cur_period;
1060 			if ((flags & DPARM_SYNC) && period &&
1061 			    (sdp->isp_devparam[tgt].cur_offset) != 0) {
1062 				if (sdp->isp_lvdmode) {
1063 					switch (period) {
1064 					case 0xa:
1065 						mhz = 40;
1066 						break;
1067 					case 0xb:
1068 						mhz = 33;
1069 						break;
1070 					case 0xc:
1071 						mhz = 25;
1072 						break;
1073 					default:
1074 						mhz = 1000 / (period * 4);
1075 						break;
1076 					}
1077 				} else {
1078 					mhz = 1000 / (period * 4);
1079 				}
1080 			} else {
1081 				mhz = 0;
1082 			}
1083 			switch (flags & (DPARM_WIDE|DPARM_TQING)) {
1084 			case DPARM_WIDE:
1085 				wt = ", 16 bit wide\n";
1086 				break;
1087 			case DPARM_TQING:
1088 				wt = ", Tagged Queueing Enabled\n";
1089 				break;
1090 			case DPARM_WIDE|DPARM_TQING:
1091 				wt = ", 16 bit wide, Tagged Queueing Enabled\n";
1092 				break;
1093 			default:
1094 				wt = "\n";
1095 				break;
1096 			}
1097 			if (mhz) {
1098 				printf("%s: Target %d at %dMHz Max Offset %d%s",
1099 				    isp->isp_name, tgt, mhz,
1100 				    sdp->isp_devparam[tgt].cur_offset, wt);
1101 			} else {
1102 				printf("%s: Target %d Async Mode%s",
1103 				    isp->isp_name, tgt, wt);
1104 			}
1105 		}
1106 		break;
1107 	case ISPASYNC_BUS_RESET:
1108 		printf("%s: SCSI bus reset detected\n", isp->isp_name);
1109 		break;
1110 	case ISPASYNC_LOOP_DOWN:
1111 		printf("%s: Loop DOWN\n", isp->isp_name);
1112 		break;
1113 	case ISPASYNC_LOOP_UP:
1114 		printf("%s: Loop UP\n", isp->isp_name);
1115 		break;
1116 	case ISPASYNC_PDB_CHANGE_COMPLETE:
1117 	if (isp->isp_type & ISP_HA_FC) {
1118 		int i;
1119 		static char *roles[4] = {
1120 		    "No", "Target", "Initiator", "Target/Initiator"
1121 		};
1122 		for (i = 0; i < MAX_FC_TARG; i++)  {
1123 			isp_pdb_t *pdbp =
1124 			    &((fcparam *)isp->isp_param)->isp_pdb[i];
1125 			if (pdbp->pdb_options == INVALID_PDB_OPTIONS)
1126 				continue;
1127 			printf("%s: Loop ID %d, %s role\n",
1128 			    isp->isp_name, pdbp->pdb_loopid,
1129 			    roles[(pdbp->pdb_prli_svc3 >> 4) & 0x3]);
1130 			printf("     Node Address 0x%x WWN 0x"
1131 			    "%02x%02x%02x%02x%02x%02x%02x%02x\n",
1132 			    BITS2WORD(pdbp->pdb_portid_bits),
1133 			    pdbp->pdb_portname[0], pdbp->pdb_portname[1],
1134 			    pdbp->pdb_portname[2], pdbp->pdb_portname[3],
1135 			    pdbp->pdb_portname[4], pdbp->pdb_portname[5],
1136 			    pdbp->pdb_portname[6], pdbp->pdb_portname[7]);
1137 			if (pdbp->pdb_options & PDB_OPTIONS_ADISC)
1138 				printf("     Hard Address 0x%x WWN 0x"
1139 				    "%02x%02x%02x%02x%02x%02x%02x%02x\n",
1140 				    BITS2WORD(pdbp->pdb_hardaddr_bits),
1141 				    pdbp->pdb_nodename[0],
1142 				    pdbp->pdb_nodename[1],
1143 				    pdbp->pdb_nodename[2],
1144 				    pdbp->pdb_nodename[3],
1145 				    pdbp->pdb_nodename[4],
1146 				    pdbp->pdb_nodename[5],
1147 				    pdbp->pdb_nodename[6],
1148 				    pdbp->pdb_nodename[7]);
1149 			switch (pdbp->pdb_prli_svc3 & SVC3_ROLE_MASK) {
1150 			case SVC3_TGT_ROLE|SVC3_INI_ROLE:
1151 				printf("     Master State=%s, Slave State=%s\n",
1152 				    isp2100_pdb_statename(pdbp->pdb_mstate),
1153 				    isp2100_pdb_statename(pdbp->pdb_sstate));
1154 				break;
1155 			case SVC3_TGT_ROLE:
1156 				printf("     Master State=%s\n",
1157 				    isp2100_pdb_statename(pdbp->pdb_mstate));
1158 				break;
1159 			case SVC3_INI_ROLE:
1160 				printf("     Slave State=%s\n",
1161 				    isp2100_pdb_statename(pdbp->pdb_sstate));
1162 				break;
1163 			default:
1164 				break;
1165 			}
1166 		}
1167 		break;
1168 	}
1169 	case ISPASYNC_CHANGE_NOTIFY:
1170 		printf("%s: Name Server Database Changed\n", isp->isp_name);
1171 		break;
1172 	default:
1173 		break;
1174 	}
1175 	return (0);
1176 }
1177 
1178 /*
1179  * Free any associated resources prior to decommissioning and
1180  * set the card to a known state (so it doesn't wake up and kick
1181  * us when we aren't expecting it to).
1182  *
1183  * Locks are held before coming here.
1184  */
1185 void
1186 isp_uninit(isp)
1187 	struct ispsoftc *isp;
1188 {
1189 	int s = splbio();
1190 	/*
1191 	 * Leave with interrupts disabled.
1192 	 */
1193 	ISP_WRITE(isp, HCCR, HCCR_CMD_RESET);
1194 	DISABLE_INTS(isp);
1195 
1196 	/*
1197 	 * Turn off the watchdog (if active).
1198 	 */
1199 	if (isp->isp_dogactive) {
1200 		untimeout(isp_watch, isp);
1201 		isp->isp_dogactive = 0;
1202 	}
1203 	/*
1204 	 * And out...
1205 	 */
1206 	splx(s);
1207 }
1208 #endif
1209