xref: /freebsd/sys/dev/isp/isp_freebsd.c (revision f35e5d0ef0a10ebda81a076bbd838d12b916dab5)
1 /* $FreeBSD$ */
2 /*
3  * Platform (FreeBSD) dependent common attachment code for Qlogic adapters.
4  *
5  *---------------------------------------
6  * Copyright (c) 1997, 1998, 1999 by Matthew Jacob
7  * NASA/Ames Research Center
8  * All rights reserved.
9  *---------------------------------------
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice immediately at the beginning of the file, without modification,
16  *    this list of conditions, and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  * 3. The name of the author may not be used to endorse or promote products
21  *    derived from this software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
27  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  */
35 #include <dev/isp/isp_freebsd.h>
36 
37 static void isp_cam_async(void *, u_int32_t, struct cam_path *, void *);
38 static void isp_poll(struct cam_sim *);
39 static void isp_action(struct cam_sim *, union ccb *);
40 static void isp_relsim(void *);
41 
42 /* #define	ISP_LUN0_ONLY	1 */
43 #ifdef	ISP_LUN0_ONLY
44 #undef	_ISP_FC_LUN
45 #undef	_ISP_SCSI_LUN
46 #define	_ISP_FC_LUN(isp)	1
47 #define	_ISP_SCSI_LUN(isp)	1
48 #endif
49 
50 void
51 isp_attach(struct ispsoftc *isp)
52 {
53 	int primary, secondary;
54 	struct ccb_setasync csa;
55 	struct cam_devq *devq;
56 	struct cam_sim *sim;
57 	struct cam_path *path;
58 
59 	/*
60 	 * Establish (in case of 12X0) which bus is the primary.
61 	 */
62 
63 	primary = 0;
64 	secondary = 1;
65 
66 	/*
67 	 * Create the device queue for our SIM(s).
68 	 */
69 	devq = cam_simq_alloc(MAXISPREQUEST);
70 	if (devq == NULL) {
71 		return;
72 	}
73 
74 	/*
75 	 * Construct our SIM entry.
76 	 */
77 	sim = cam_sim_alloc(isp_action, isp_poll, "isp", isp,
78 	    isp->isp_unit, 1, MAXISPREQUEST, devq);
79 	if (sim == NULL) {
80 		cam_simq_free(devq);
81 		return;
82 	}
83 	if (xpt_bus_register(sim, primary) != CAM_SUCCESS) {
84 		cam_sim_free(sim, TRUE);
85 		return;
86 	}
87 
88 	if (xpt_create_path(&path, NULL, cam_sim_path(sim),
89 	    CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
90 		xpt_bus_deregister(cam_sim_path(sim));
91 		cam_sim_free(sim, TRUE);
92 		return;
93 	}
94 
95 	xpt_setup_ccb(&csa.ccb_h, path, 5);
96 	csa.ccb_h.func_code = XPT_SASYNC_CB;
97 	csa.event_enable = AC_LOST_DEVICE;
98 	csa.callback = isp_cam_async;
99 	csa.callback_arg = sim;
100 	xpt_action((union ccb *)&csa);
101 	isp->isp_sim = sim;
102 	isp->isp_path = path;
103 
104 	/*
105 	 * If we have a second channel, construct SIM entry for that.
106 	 */
107 	if (IS_12X0(isp)) {
108 		sim = cam_sim_alloc(isp_action, isp_poll, "isp", isp,
109 		    isp->isp_unit, 1, MAXISPREQUEST, devq);
110 		if (sim == NULL) {
111 			xpt_bus_deregister(cam_sim_path(isp->isp_sim));
112 			xpt_free_path(isp->isp_path);
113 			cam_simq_free(devq);
114 			return;
115 		}
116 		if (xpt_bus_register(sim, secondary) != CAM_SUCCESS) {
117 			xpt_bus_deregister(cam_sim_path(isp->isp_sim));
118 			xpt_free_path(isp->isp_path);
119 			cam_sim_free(sim, TRUE);
120 			return;
121 		}
122 
123 		if (xpt_create_path(&path, NULL, cam_sim_path(sim),
124 		    CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
125 			xpt_bus_deregister(cam_sim_path(isp->isp_sim));
126 			xpt_free_path(isp->isp_path);
127 			xpt_bus_deregister(cam_sim_path(sim));
128 			cam_sim_free(sim, TRUE);
129 			return;
130 		}
131 
132 		xpt_setup_ccb(&csa.ccb_h, path, 5);
133 		csa.ccb_h.func_code = XPT_SASYNC_CB;
134 		csa.event_enable = AC_LOST_DEVICE;
135 		csa.callback = isp_cam_async;
136 		csa.callback_arg = sim;
137 		xpt_action((union ccb *)&csa);
138 		isp->isp_sim2 = sim;
139 		isp->isp_path2 = path;
140 	}
141 	if (isp->isp_state == ISP_INITSTATE) {
142 		isp->isp_state = ISP_RUNSTATE;
143 	}
144 }
145 
146 static void
147 isp_cam_async(void *cbarg, u_int32_t code, struct cam_path *path, void *arg)
148 {
149 	struct cam_sim *sim;
150 	struct ispsoftc *isp;
151 
152 	sim = (struct cam_sim *)cbarg;
153 	isp = (struct ispsoftc *) cam_sim_softc(sim);
154 	switch (code) {
155 	case AC_LOST_DEVICE:
156 		if (isp->isp_type & ISP_HA_SCSI) {
157 			u_int16_t oflags, nflags;
158 			sdparam *sdp = isp->isp_param;
159 			int s, tgt = xpt_path_target_id(path);
160 
161 			s = splcam();
162 			sdp += cam_sim_bus(sim);
163 			isp->isp_update |= (1 << cam_sim_bus(sim));
164 
165 			nflags = DPARM_SAFE_DFLT;
166 			if (ISP_FW_REVX(isp->isp_fwrev) >=
167 			    ISP_FW_REV(7, 55, 0)) {
168 				nflags |= DPARM_NARROW | DPARM_ASYNC;
169 			}
170 			oflags = sdp->isp_devparam[tgt].dev_flags;
171 			sdp->isp_devparam[tgt].dev_flags = nflags;
172 			sdp->isp_devparam[tgt].dev_update = 1;
173 			(void) isp_control(isp, ISPCTL_UPDATE_PARAMS, NULL);
174 			sdp->isp_devparam[tgt].dev_flags = oflags;
175 			(void) splx(s);
176 		}
177 		break;
178 	default:
179 		printf("%s: isp_attach Async Code 0x%x\n", isp->isp_name, code);
180 		break;
181 	}
182 }
183 
184 static void
185 isp_poll(struct cam_sim *sim)
186 {
187 	isp_intr((struct ispsoftc *) cam_sim_softc(sim));
188 }
189 
190 static void
191 isp_relsim(void *arg)
192 {
193 	struct ispsoftc *isp = arg;
194 	int s = splcam();
195 	if (isp->isp_osinfo.simqfrozen & SIMQFRZ_TIMED) {
196 		int wasfrozen = isp->isp_osinfo.simqfrozen & SIMQFRZ_TIMED;
197 		isp->isp_osinfo.simqfrozen &= ~SIMQFRZ_TIMED;
198 		if (wasfrozen && isp->isp_osinfo.simqfrozen == 0) {
199 			xpt_release_simq(isp->isp_sim, 1);
200 			IDPRINTF(3, ("%s: timed relsimq\n", isp->isp_name));
201 		}
202 	}
203 	splx(s);
204 }
205 static void
206 isp_action(struct cam_sim *sim, union ccb *ccb)
207 {
208 	int s, tgt, error;
209 	struct ispsoftc *isp;
210 	struct ccb_trans_settings *cts;
211 
212 	CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("isp_action\n"));
213 
214 	isp = (struct ispsoftc *)cam_sim_softc(sim);
215 	ccb->ccb_h.sim_priv.entries[0].field = 0;
216 	ccb->ccb_h.sim_priv.entries[1].ptr = isp;
217 	if (isp->isp_state != ISP_RUNSTATE &&
218 	    ccb->ccb_h.func_code == XPT_SCSI_IO) {
219 		s = splcam();
220 		DISABLE_INTS(isp);
221 		isp_init(isp);
222 		if (isp->isp_state != ISP_INITSTATE) {
223 			(void) splx(s);
224 			/*
225 			 * Lie. Say it was a selection timeout.
226 			 */
227 			ccb->ccb_h.status = CAM_SEL_TIMEOUT;
228 			ccb->ccb_h.status |= CAM_DEV_QFRZN;
229 			xpt_freeze_devq(ccb->ccb_h.path, 1);
230 			xpt_done(ccb);
231 			return;
232 		}
233 		isp->isp_state = ISP_RUNSTATE;
234 		ENABLE_INTS(isp);
235 		(void) splx(s);
236 	}
237 	IDPRINTF(4, ("%s: isp_action code %x\n", isp->isp_name,
238 	    ccb->ccb_h.func_code));
239 
240 	switch (ccb->ccb_h.func_code) {
241 	case XPT_SCSI_IO:	/* Execute the requested I/O operation */
242 		/*
243 		 * Do a couple of preliminary checks...
244 		 */
245 		if ((ccb->ccb_h.flags & CAM_CDB_POINTER) != 0) {
246 			if ((ccb->ccb_h.flags & CAM_CDB_PHYS) != 0) {
247 				ccb->ccb_h.status = CAM_REQ_INVALID;
248 				xpt_done(ccb);
249 				break;
250 			}
251 		}
252 #ifdef	DIAGNOSTIC
253 		if (ccb->ccb_h.target_id > (ISP_MAX_TARGETS(isp) - 1)) {
254 			ccb->ccb_h.status = CAM_PATH_INVALID;
255 		} else if (ccb->ccb_h.target_lun > (ISP_MAX_LUNS(isp) - 1)) {
256 			ccb->ccb_h.status = CAM_PATH_INVALID;
257 		}
258 		if (ccb->ccb_h.status == CAM_PATH_INVALID) {
259 			printf("%s: invalid tgt/lun (%d.%d) in XPT_SCSI_IO\n",
260 			    isp->isp_name, ccb->ccb_h.target_id,
261 			    ccb->ccb_h.target_lun);
262 			xpt_done(ccb);
263 			break;
264 		}
265 #endif
266 		((struct ccb_scsiio *) ccb)->scsi_status = SCSI_STATUS_OK;
267 		s = splcam();
268 		DISABLE_INTS(isp);
269 		error = ispscsicmd((ISP_SCSI_XFER_T *) ccb);
270 		ENABLE_INTS(isp);
271 		splx(s);
272 		switch (error) {
273 		case CMD_QUEUED:
274 			ccb->ccb_h.status |= CAM_SIM_QUEUED;
275 			break;
276 		case CMD_RQLATER:
277 			if (isp->isp_osinfo.simqfrozen == 0) {
278 				IDPRINTF(3, ("%s: RQLATER freeze simq\n",
279 				    isp->isp_name));
280 				isp->isp_osinfo.simqfrozen |= SIMQFRZ_TIMED;
281 				timeout(isp_relsim, isp, 500);
282 				xpt_freeze_simq(sim, 1);
283 			}
284 			ccb->ccb_h.status &= ~CAM_STATUS_MASK;
285                         ccb->ccb_h.status |= CAM_REQUEUE_REQ;
286 			xpt_done(ccb);
287 			break;
288 		case CMD_EAGAIN:
289 			if (isp->isp_osinfo.simqfrozen == 0) {
290 				xpt_freeze_simq(sim, 1);
291 				IDPRINTF(3, ("%s: EAGAIN freeze simq\n",
292 				    isp->isp_name));
293 			}
294 			isp->isp_osinfo.simqfrozen |= SIMQFRZ_RESOURCE;
295 			ccb->ccb_h.status &= ~CAM_STATUS_MASK;
296                         ccb->ccb_h.status |= CAM_REQUEUE_REQ;
297 			xpt_done(ccb);
298 			break;
299 		case CMD_COMPLETE:
300 			isp_done((struct ccb_scsiio *) ccb);
301 			break;
302 		default:
303 			printf("%s: What's this? 0x%x at %d in file %s\n",
304 			    isp->isp_name, error, __LINE__, __FILE__);
305 			ccb->ccb_h.status &= ~CAM_STATUS_MASK;
306 			ccb->ccb_h.status |= CAM_REQ_CMP_ERR;
307 			xpt_done(ccb);
308 		}
309 		break;
310 
311 	case XPT_EN_LUN:		/* Enable LUN as a target */
312 	case XPT_TARGET_IO:		/* Execute target I/O request */
313 	case XPT_ACCEPT_TARGET_IO:	/* Accept Host Target Mode CDB */
314 	case XPT_CONT_TARGET_IO:	/* Continue Host Target I/O Connection*/
315 		ccb->ccb_h.status = CAM_REQ_INVALID;
316 		xpt_done(ccb);
317 		break;
318 
319 	case XPT_RESET_DEV:		/* BDR the specified SCSI device */
320 		tgt = ccb->ccb_h.target_id; /* XXX: Which Bus? */
321 		s = splcam();
322 		error = isp_control(isp, ISPCTL_RESET_DEV, &tgt);
323 		(void) splx(s);
324 		if (error) {
325 			ccb->ccb_h.status = CAM_REQ_CMP_ERR;
326 		} else {
327 			ccb->ccb_h.status = CAM_REQ_CMP;
328 		}
329 		xpt_done(ccb);
330 		break;
331 	case XPT_ABORT:			/* Abort the specified CCB */
332 		s = splcam();
333 		error = isp_control(isp, ISPCTL_ABORT_CMD, ccb);
334 		(void) splx(s);
335 		if (error) {
336 			ccb->ccb_h.status = CAM_REQ_CMP_ERR;
337 		} else {
338 			ccb->ccb_h.status = CAM_REQ_CMP;
339 		}
340 		xpt_done(ccb);
341 		break;
342 
343 	case XPT_SET_TRAN_SETTINGS:	/* Nexus Settings */
344 
345 		cts = &ccb->cts;
346 		tgt = cts->ccb_h.target_id;
347 		s = splcam();
348 		if (isp->isp_type & ISP_HA_FC) {
349 			;	/* nothing to change */
350 		} else {
351 			sdparam *sdp = isp->isp_param;
352 			u_int16_t *dptr;
353 			int bus = cam_sim_bus(xpt_path_sim(cts->ccb_h.path));
354 
355 			sdp += bus;
356 #if	0
357 			if (cts->flags & CCB_TRANS_CURRENT_SETTINGS)
358 				dptr = &sdp->isp_devparam[tgt].cur_dflags;
359 			else
360 				dptr = &sdp->isp_devparam[tgt].dev_flags;
361 #else
362 			/*
363 			 * We always update (internally) from dev_flags
364 			 * so any request to change settings just gets
365 			 * vectored to that location.
366 			 */
367 			dptr = &sdp->isp_devparam[tgt].dev_flags;
368 #endif
369 
370 			/*
371 			 * Note that these operations affect the
372 			 * the goal flags (dev_flags)- not
373 			 * the current state flags. Then we mark
374 			 * things so that the next operation to
375 			 * this HBA will cause the update to occur.
376 			 */
377 			if (cts->valid & CCB_TRANS_DISC_VALID) {
378 				if ((cts->flags & CCB_TRANS_DISC_ENB) != 0) {
379 					*dptr |= DPARM_DISC;
380 				} else {
381 					*dptr &= ~DPARM_DISC;
382 				}
383 			}
384 			if (cts->valid & CCB_TRANS_TQ_VALID) {
385 				if ((cts->flags & CCB_TRANS_TAG_ENB) != 0) {
386 					*dptr |= DPARM_TQING;
387 				} else {
388 					*dptr &= ~DPARM_TQING;
389 				}
390 			}
391 			if (cts->valid & CCB_TRANS_BUS_WIDTH_VALID) {
392 				switch (cts->bus_width) {
393 				case MSG_EXT_WDTR_BUS_16_BIT:
394 					*dptr |= DPARM_WIDE;
395 					break;
396 				default:
397 					*dptr &= ~DPARM_WIDE;
398 				}
399 			}
400 			/*
401 			 * Any SYNC RATE of nonzero and SYNC_OFFSET
402 			 * of nonzero will cause us to go to the
403 			 * selected (from NVRAM) maximum value for
404 			 * this device. At a later point, we'll
405 			 * allow finer control.
406 			 */
407 			if ((cts->valid & CCB_TRANS_SYNC_RATE_VALID) &&
408 			    (cts->valid & CCB_TRANS_SYNC_OFFSET_VALID) &&
409 			    (cts->sync_offset > 0)) {
410 				*dptr |= DPARM_SYNC;
411 			} else {
412 				*dptr &= ~DPARM_SYNC;
413 			}
414 			if (bootverbose || isp->isp_dblev >= 3)
415 				printf("%s: %d.%d set %s period 0x%x offset "
416 				    "0x%x flags 0x%x\n", isp->isp_name, bus,
417 				    tgt,
418 				    (cts->flags & CCB_TRANS_CURRENT_SETTINGS)?
419 				    "current" : "user",
420 				    sdp->isp_devparam[tgt].sync_period,
421 				    sdp->isp_devparam[tgt].sync_offset,
422 				    sdp->isp_devparam[tgt].dev_flags);
423 			s = splcam();
424 			sdp->isp_devparam[tgt].dev_update = 1;
425 			isp->isp_update |= (1 << bus);
426 			(void) isp_control(isp, ISPCTL_UPDATE_PARAMS, NULL);
427 			(void) splx(s);
428 		}
429 		(void) splx(s);
430 		ccb->ccb_h.status = CAM_REQ_CMP;
431 		xpt_done(ccb);
432 		break;
433 
434 	case XPT_GET_TRAN_SETTINGS:
435 
436 		cts = &ccb->cts;
437 		tgt = cts->ccb_h.target_id;
438 		if (isp->isp_type & ISP_HA_FC) {
439 			/*
440 			 * a lot of normal SCSI things don't make sense.
441 			 */
442 			cts->flags = CCB_TRANS_TAG_ENB | CCB_TRANS_DISC_ENB;
443 			cts->valid = CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID;
444 			/*
445 			 * How do you measure the width of a high
446 			 * speed serial bus? Well, in bytes.
447 			 *
448 			 * Offset and period make no sense, though, so we set
449 			 * (above) a 'base' transfer speed to be gigabit.
450 			 */
451 			cts->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
452 		} else {
453 			sdparam *sdp = isp->isp_param;
454 			u_int16_t dval, pval, oval;
455 			int bus = cam_sim_bus(xpt_path_sim(cts->ccb_h.path));
456 
457 			sdp += bus;
458 			if (cts->flags & CCB_TRANS_CURRENT_SETTINGS) {
459 				s = splcam();
460 				/*
461 				 * First do a refresh to see if things
462 				 * have changed recently!
463 				 */
464 				sdp->isp_devparam[tgt].dev_refresh = 1;
465 				isp->isp_update |= (1 << bus);
466 				(void) isp_control(isp, ISPCTL_UPDATE_PARAMS,
467 				    NULL);
468 				(void) splx(s);
469 				dval = sdp->isp_devparam[tgt].cur_dflags;
470 				oval = sdp->isp_devparam[tgt].cur_offset;
471 				pval = sdp->isp_devparam[tgt].cur_period;
472 			} else {
473 				dval = sdp->isp_devparam[tgt].dev_flags;
474 				oval = sdp->isp_devparam[tgt].sync_offset;
475 				pval = sdp->isp_devparam[tgt].sync_period;
476 			}
477 
478 			s = splcam();
479 			cts->flags &= ~(CCB_TRANS_DISC_ENB|CCB_TRANS_TAG_ENB);
480 
481 			if (dval & DPARM_DISC) {
482 				cts->flags |= CCB_TRANS_DISC_ENB;
483 			}
484 			if (dval & DPARM_TQING) {
485 				cts->flags |= CCB_TRANS_TAG_ENB;
486 			}
487 			if (dval & DPARM_WIDE) {
488 				cts->bus_width = MSG_EXT_WDTR_BUS_16_BIT;
489 			} else {
490 				cts->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
491 			}
492 			cts->valid = CCB_TRANS_BUS_WIDTH_VALID |
493 			    CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID;
494 
495 			if ((dval & DPARM_SYNC) && oval != 0) {
496 				cts->sync_period = pval;
497 				cts->sync_offset = oval;
498 				cts->valid |=
499 				    CCB_TRANS_SYNC_RATE_VALID |
500 				    CCB_TRANS_SYNC_OFFSET_VALID;
501 			}
502 			splx(s);
503 			if (bootverbose || isp->isp_dblev >= 3)
504 				printf("%s: %d.%d get %s period 0x%x offset "
505 				    "0x%x flags 0x%x\n", isp->isp_name, bus,
506 				    tgt,
507 			    	    (cts->flags & CCB_TRANS_CURRENT_SETTINGS)?
508 				    "current" : "user", pval, oval, dval);
509 		}
510 		ccb->ccb_h.status = CAM_REQ_CMP;
511 		xpt_done(ccb);
512 		break;
513 
514 	case XPT_CALC_GEOMETRY:
515 	{
516 		struct ccb_calc_geometry *ccg;
517 		u_int32_t secs_per_cylinder;
518 		u_int32_t size_mb;
519 
520 		ccg = &ccb->ccg;
521 		if (ccg->block_size == 0) {
522 			printf("%s: %d.%d XPT_CALC_GEOMETRY block size 0?\n",
523 				isp->isp_name, ccg->ccb_h.target_id,
524 				ccg->ccb_h.target_lun);
525 			ccb->ccb_h.status = CAM_REQ_INVALID;
526 			xpt_done(ccb);
527 			break;
528 		}
529 		size_mb = ccg->volume_size /((1024L * 1024L) / ccg->block_size);
530 		if (size_mb > 1024) {
531 			ccg->heads = 255;
532 			ccg->secs_per_track = 63;
533 		} else {
534 			ccg->heads = 64;
535 			ccg->secs_per_track = 32;
536 		}
537 		secs_per_cylinder = ccg->heads * ccg->secs_per_track;
538 		ccg->cylinders = ccg->volume_size / secs_per_cylinder;
539 		ccb->ccb_h.status = CAM_REQ_CMP;
540 		xpt_done(ccb);
541 		break;
542 	}
543 	case XPT_RESET_BUS:		/* Reset the specified bus */
544 		tgt = cam_sim_bus(sim);
545 		s = splcam();
546 		error = isp_control(isp, ISPCTL_RESET_BUS, &tgt);
547 		(void) splx(s);
548 		if (error)
549 			ccb->ccb_h.status = CAM_REQ_CMP_ERR;
550 		else {
551 			if (cam_sim_bus(sim) && isp->isp_path2 != NULL)
552 				xpt_async(AC_BUS_RESET, isp->isp_path2, NULL);
553 			else if (isp->isp_path != NULL)
554 				xpt_async(AC_BUS_RESET, isp->isp_path, NULL);
555 			ccb->ccb_h.status = CAM_REQ_CMP;
556 		}
557 		xpt_done(ccb);
558 		break;
559 
560 	case XPT_TERM_IO:		/* Terminate the I/O process */
561 		/* Does this need to be implemented? */
562 		ccb->ccb_h.status = CAM_REQ_INVALID;
563 		xpt_done(ccb);
564 		break;
565 
566 	case XPT_PATH_INQ:		/* Path routing inquiry */
567 	{
568 		struct ccb_pathinq *cpi = &ccb->cpi;
569 
570 		cpi->version_num = 1;
571 		cpi->target_sprt = 0;
572 		cpi->hba_eng_cnt = 0;
573 		cpi->max_target = ISP_MAX_TARGETS(isp) - 1;
574 		cpi->max_lun = ISP_MAX_LUNS(isp) - 1;
575 		cpi->bus_id = cam_sim_bus(sim);
576 		if (IS_FC(isp)) {
577 			cpi->hba_misc = PIM_NOBUSRESET;
578 
579 			/*
580 			 * Because our loop ID can shift from time to time,
581 			 * make our initiator ID out of range of our bus.
582 			 */
583 			cpi->initiator_id = cpi->max_target + 1;
584 
585 			/*
586 			 * Set base transfer capabilities for Fibre Channel.
587 			 * Technically not correct because we don't know
588 			 * what media we're running on top of- but we'll
589 			 * look good if we always say 100MB/s.
590 			 */
591 			cpi->base_transfer_speed = 100000;
592 			cpi->hba_inquiry = PI_TAG_ABLE;
593 		} else {
594 			sdparam *sdp = isp->isp_param;
595 			sdp += cam_sim_bus(xpt_path_sim(cpi->ccb_h.path));
596 
597 			cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE|PI_WIDE_16;
598 			cpi->hba_misc = 0;
599 			cpi->initiator_id = sdp->isp_initiator_id;
600 			cpi->base_transfer_speed = 3300;
601 		}
602 		strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
603 		strncpy(cpi->hba_vid, "Qlogic", HBA_IDLEN);
604 		strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
605 		cpi->unit_number = cam_sim_unit(sim);
606 		cpi->ccb_h.status = CAM_REQ_CMP;
607 		xpt_done(ccb);
608 		break;
609 	}
610 	default:
611 		ccb->ccb_h.status = CAM_REQ_INVALID;
612 		xpt_done(ccb);
613 		break;
614 	}
615 }
616 
617 #define	ISPDDB	(CAM_DEBUG_INFO|CAM_DEBUG_TRACE|CAM_DEBUG_CDB)
618 void
619 isp_done(struct ccb_scsiio *sccb)
620 {
621 	struct ispsoftc *isp = XS_ISP(sccb);
622 
623 	if (XS_NOERR(sccb))
624 		XS_SETERR(sccb, CAM_REQ_CMP);
625 	sccb->ccb_h.status &= ~CAM_STATUS_MASK;
626 	sccb->ccb_h.status |= sccb->ccb_h.spriv_field0;
627 	if ((sccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP &&
628 	    (sccb->scsi_status != SCSI_STATUS_OK)) {
629 		sccb->ccb_h.status &= ~CAM_STATUS_MASK;
630 		sccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR;
631 	}
632 	sccb->ccb_h.status &= ~CAM_SIM_QUEUED;
633 	if ((sccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
634 		if ((sccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
635 			sccb->ccb_h.status |= CAM_DEV_QFRZN;
636 			xpt_freeze_devq(sccb->ccb_h.path, 1);
637 			if (sccb->scsi_status != SCSI_STATUS_OK)
638 				IDPRINTF(3, ("%s: fdevq %d.%d %x %x\n",
639 				    isp->isp_name, sccb->ccb_h.target_id,
640 				    sccb->ccb_h.target_lun, sccb->ccb_h.status,
641 				    sccb->scsi_status));
642 		}
643 	}
644 	/*
645 	 * If we were frozen waiting resources, clear that we were frozen
646 	 * waiting for resources. If we are no longer frozen, and the devq
647 	 * isn't frozen, mark the completing CCB to have the XPT layer
648 	 * release the simq.
649 	 */
650 	if (isp->isp_osinfo.simqfrozen & SIMQFRZ_RESOURCE) {
651 		isp->isp_osinfo.simqfrozen &= ~SIMQFRZ_RESOURCE;
652 		if (isp->isp_osinfo.simqfrozen == 0) {
653 			if ((sccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
654 				IDPRINTF(3, ("%s: isp_done -> relsimq\n",
655 				    isp->isp_name));
656 				sccb->ccb_h.status |= CAM_RELEASE_SIMQ;
657 			} else {
658 				IDPRINTF(3, ("%s: isp_done -> devq frozen\n",
659 				    isp->isp_name));
660 			}
661 		} else {
662 			IDPRINTF(3, ("%s: isp_done -> simqfrozen = %x\n",
663 			    isp->isp_name, isp->isp_osinfo.simqfrozen));
664 		}
665 	}
666 	if (CAM_DEBUGGED(sccb->ccb_h.path, ISPDDB) &&
667 	    (sccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
668 		xpt_print_path(sccb->ccb_h.path);
669 		printf("cam completion status 0x%x\n", sccb->ccb_h.status);
670 	}
671 	xpt_done((union ccb *) sccb);
672 }
673 
674 int
675 isp_async(struct ispsoftc *isp, ispasync_t cmd, void *arg)
676 {
677 	int bus, rv = 0;
678 	switch (cmd) {
679 	case ISPASYNC_NEW_TGT_PARAMS:
680 	{
681 		int flags, tgt;
682 		sdparam *sdp = isp->isp_param;
683 		struct ccb_trans_settings neg;
684 		struct cam_path *tmppath;
685 
686 		tgt = *((int *)arg);
687 		bus = (tgt >> 16) & 0xffff;
688 		tgt &= 0xffff;
689 		sdp += bus;
690 		if (xpt_create_path(&tmppath, NULL,
691 		    cam_sim_path(bus? isp->isp_sim2 : isp->isp_sim),
692 		    tgt, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
693 			xpt_print_path(isp->isp_path);
694 			printf("isp_async cannot make temp path for "
695 			    "target %d bus %d\n", tgt, bus);
696 			rv = -1;
697 			break;
698 		}
699 		flags = sdp->isp_devparam[tgt].cur_dflags;
700 		neg.valid = CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID;
701 		if (flags & DPARM_DISC) {
702 			neg.flags |= CCB_TRANS_DISC_ENB;
703 		}
704 		if (flags & DPARM_TQING) {
705 			neg.flags |= CCB_TRANS_TAG_ENB;
706 		}
707 		neg.valid |= CCB_TRANS_BUS_WIDTH_VALID;
708 		neg.bus_width = (flags & DPARM_WIDE)?
709 		    MSG_EXT_WDTR_BUS_8_BIT : MSG_EXT_WDTR_BUS_16_BIT;
710 		neg.sync_period = sdp->isp_devparam[tgt].cur_period;
711 		neg.sync_offset = sdp->isp_devparam[tgt].cur_offset;
712 		if (flags & DPARM_SYNC) {
713 			neg.valid |=
714 			    CCB_TRANS_SYNC_RATE_VALID |
715 			    CCB_TRANS_SYNC_OFFSET_VALID;
716 		}
717 		IDPRINTF(3, ("%s: NEW_TGT_PARAMS bus %d tgt %d period "
718 		    "0x%x offset 0x%x flags 0x%x\n", isp->isp_name,
719 		    bus, tgt, neg.sync_period, neg.sync_offset, flags));
720 		xpt_setup_ccb(&neg.ccb_h, tmppath, 1);
721 		xpt_async(AC_TRANSFER_NEG, tmppath, &neg);
722 		xpt_free_path(tmppath);
723 		break;
724 	}
725 	case ISPASYNC_BUS_RESET:
726 		bus = *((int *)arg);
727 		printf("%s: SCSI bus reset on bus %d detected\n",
728 		    isp->isp_name, bus);
729 		if (bus > 0 && isp->isp_path2) {
730 			xpt_async(AC_BUS_RESET, isp->isp_path2, NULL);
731 		} else if (isp->isp_path) {
732 			xpt_async(AC_BUS_RESET, isp->isp_path, NULL);
733 		}
734 		break;
735 	case ISPASYNC_LOOP_DOWN:
736 		if (isp->isp_path) {
737 			if (isp->isp_osinfo.simqfrozen == 0) {
738 				IDPRINTF(3, ("%s: loop down freeze simq\n",
739 				    isp->isp_name));
740 				xpt_freeze_simq(isp->isp_sim, 1);
741 			}
742 			isp->isp_osinfo.simqfrozen |= SIMQFRZ_LOOPDOWN;
743 		}
744 		printf("%s: Loop DOWN\n", isp->isp_name);
745 #if	defined(DDB)
746 		if (isp->isp_dblev > DFLT_DBLEVEL) {
747 			Debugger("Loop Down");
748 		}
749 #endif
750 		break;
751 	case ISPASYNC_LOOP_UP:
752 		if (isp->isp_path) {
753 			int wasfrozen =
754 			    isp->isp_osinfo.simqfrozen & SIMQFRZ_LOOPDOWN;
755 			isp->isp_osinfo.simqfrozen &= ~SIMQFRZ_LOOPDOWN;
756 			if (wasfrozen && isp->isp_osinfo.simqfrozen == 0) {
757 				xpt_release_simq(isp->isp_sim, 1);
758 				IDPRINTF(3, ("%s: loop up release simq\n",
759 					isp->isp_name));
760 			}
761 		}
762 		printf("%s: Loop UP\n", isp->isp_name);
763 		break;
764 	case ISPASYNC_PDB_CHANGED:
765 	{
766 		const char *fmt = "%s: Target %d (Loop 0x%x) Port ID 0x%x "
767 		    "role %s %s\n Port WWN 0x%08x%08x\n Node WWN 0x%08x%08x\n";
768 		const static char *roles[4] = {
769 		    "(none)", "Target", "Initiator", "Target/Initiator"
770 		};
771 		char *ptr;
772 		fcparam *fcp = isp->isp_param;
773 		int tgt = *((int *) arg);
774 		struct lportdb *lp = &fcp->portdb[tgt];
775 
776 		if (lp->valid) {
777 			ptr = "arrived";
778 		} else {
779 			ptr = "disappeared";
780 		}
781 		printf(fmt, isp->isp_name, tgt, lp->loopid, lp->portid,
782 		    roles[lp->roles & 0x3], ptr,
783 		    (u_int32_t) (lp->port_wwn >> 32),
784 		    (u_int32_t) (lp->port_wwn & 0xffffffffLL),
785 		    (u_int32_t) (lp->node_wwn >> 32),
786 		    (u_int32_t) (lp->node_wwn & 0xffffffffLL));
787 		break;
788 	}
789 	case ISPASYNC_CHANGE_NOTIFY:
790 		printf("%s: Name Server Database Changed\n", isp->isp_name);
791 		break;
792 #ifdef	ISP2100_FABRIC
793 	case ISPASYNC_FABRIC_DEV:
794 	{
795 		int target;
796 		struct lportdb *lp;
797 		sns_scrsp_t *resp = (sns_scrsp_t *) arg;
798 		u_int32_t portid;
799 		u_int64_t wwn;
800 		fcparam *fcp = isp->isp_param;
801 
802 		rv = -1;
803 
804 		portid =
805 		    (((u_int32_t) resp->snscb_port_id[0]) << 16) |
806 		    (((u_int32_t) resp->snscb_port_id[1]) << 8) |
807 		    (((u_int32_t) resp->snscb_port_id[2]));
808 		wwn =
809 		    (((u_int64_t)resp->snscb_portname[0]) << 56) |
810 		    (((u_int64_t)resp->snscb_portname[1]) << 48) |
811 		    (((u_int64_t)resp->snscb_portname[2]) << 40) |
812 		    (((u_int64_t)resp->snscb_portname[3]) << 32) |
813 		    (((u_int64_t)resp->snscb_portname[4]) << 24) |
814 		    (((u_int64_t)resp->snscb_portname[5]) << 16) |
815 		    (((u_int64_t)resp->snscb_portname[6]) <<  8) |
816 		    (((u_int64_t)resp->snscb_portname[7]));
817 		printf("%s: type 0x%x@portid 0x%x 0x%08x%08x\n", isp->isp_name,
818 		    resp->snscb_port_type, portid,
819 		    ((u_int32_t) (wwn >> 32)), ((u_int32_t) wwn));
820 		if (resp->snscb_port_type != 2) {
821 			rv = 0;
822 			break;
823 		}
824 		for (target = FC_SNS_ID+1; target < MAX_FC_TARG; target++) {
825 			lp = &fcp->portdb[target];
826 			if (lp->port_wwn == wwn)
827 				break;
828 		}
829 		if (target < MAX_FC_TARG) {
830 			rv = 0;
831 			break;
832 		}
833 		for (target = FC_SNS_ID+1; target < MAX_FC_TARG; target++) {
834 			lp = &fcp->portdb[target];
835 			if (lp->port_wwn == 0)
836 				break;
837 		}
838 		if (target == MAX_FC_TARG) {
839 			printf("%s: no more space for fabric devices\n",
840 			    isp->isp_name);
841 			break;
842 		}
843 		lp->port_wwn = lp->node_wwn = wwn;
844 		lp->portid = portid;
845 		rv = 0;
846 		break;
847 	}
848 #endif
849 	default:
850 		rv = -1;
851 		break;
852 	}
853 	return (rv);
854 }
855 
856 
857 /*
858  * Locks are held before coming here.
859  */
860 void
861 isp_uninit(struct ispsoftc *isp)
862 {
863 	ISP_WRITE(isp, HCCR, HCCR_CMD_RESET);
864 	DISABLE_INTS(isp);
865 }
866