xref: /freebsd/sys/dev/isp/isp_freebsd.c (revision 2ad872c5794e4c26fdf6ed219ad3f09ca0d5304a)
1 /* $Id: $ */
2 /* release_12_28_98_A */
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_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 	struct ccb_setasync csa;
48 	struct cam_devq *devq;
49 
50 	/*
51 	 * Create the device queue for our SIM.
52 	 */
53 	devq = cam_simq_alloc(MAXISPREQUEST);
54 	if (devq == NULL) {
55 		return;
56 	}
57 
58 	/*
59 	 * Construct our SIM entry
60 	 */
61 	isp->isp_sim = cam_sim_alloc(isp_action, isp_poll, "isp", isp,
62 	    isp->isp_unit, 1, MAXISPREQUEST, devq);
63 	if (isp->isp_sim == NULL) {
64 		cam_simq_free(devq);
65 		return;
66 	}
67 	if (xpt_bus_register(isp->isp_sim, 0) != CAM_SUCCESS) {
68 		cam_sim_free(isp->isp_sim, TRUE);
69 		return;
70 	}
71 
72 	if (xpt_create_path(&isp->isp_path, NULL, cam_sim_path(isp->isp_sim),
73 	    CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
74 		xpt_bus_deregister(cam_sim_path(isp->isp_sim));
75 		cam_sim_free(isp->isp_sim, TRUE);
76 		return;
77 	}
78 
79 	xpt_setup_ccb(&csa.ccb_h, isp->isp_path, 5);
80 	csa.ccb_h.func_code = XPT_SASYNC_CB;
81 	csa.event_enable = AC_LOST_DEVICE;
82 	csa.callback = isp_async;
83 	csa.callback_arg = isp->isp_sim;
84 	xpt_action((union ccb *)&csa);
85 
86 	/*
87 	 * Set base transfer capabilities for Fibre Channel.
88 	 * Technically not correct because we don't know
89 	 * what media we're running on top of- but we'll
90 	 * look good if we always say 100MB/s.
91 	 */
92 	if (isp->isp_type & ISP_HA_FC) {
93 		isp->isp_sim->base_transfer_speed = 100000;
94 	}
95 	isp->isp_state = ISP_RUNSTATE;
96 }
97 
98 static void
99 isp_async(void *cbarg, u_int32_t code, struct cam_path *path, void *arg)
100 {
101 	struct cam_sim *sim;
102 	struct ispsoftc *isp;
103 
104 	sim = (struct cam_sim *)cbarg;
105 	isp = (struct ispsoftc *) cam_sim_softc(sim);
106 	switch (code) {
107 	case AC_LOST_DEVICE:
108 		if (isp->isp_type & ISP_HA_SCSI) {
109 			u_int16_t oflags, nflags;
110 			sdparam *sdp = isp->isp_param;
111 			int s, tgt = xpt_path_target_id(path);
112 
113 			nflags = DPARM_SAFE_DFLT;
114 			if (isp->isp_fwrev >= ISP_FW_REV(7, 55)) {
115 				nflags |= DPARM_NARROW | DPARM_ASYNC;
116 			}
117 			oflags = sdp->isp_devparam[tgt].dev_flags;
118 			sdp->isp_devparam[tgt].dev_flags = nflags;
119 			sdp->isp_devparam[tgt].dev_update = 1;
120 
121 			s = splcam();
122 			(void) isp_control(isp, ISPCTL_UPDATE_PARAMS, NULL);
123 			(void) splx(s);
124 			sdp->isp_devparam[tgt].dev_flags = oflags;
125 		}
126 		break;
127 	default:
128 		break;
129 	}
130 }
131 
132 static void
133 isp_poll(struct cam_sim *sim)
134 {
135 	isp_intr((struct ispsoftc *) cam_sim_softc(sim));
136 }
137 
138 
139 static void
140 isp_action(struct cam_sim *sim, union ccb *ccb)
141 {
142 	int s, tgt, error;
143 	struct ispsoftc *isp;
144 	struct ccb_trans_settings *cts;
145 
146 	CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("isp_action\n"));
147 
148 	isp = (struct ispsoftc *)cam_sim_softc(sim);
149 	ccb->ccb_h.sim_priv.entries[0].field = 0;
150 	ccb->ccb_h.sim_priv.entries[1].ptr = isp;
151 
152 	IDPRINTF(4, ("%s: isp_action code %x\n", isp->isp_name,
153 	    ccb->ccb_h.func_code));
154 
155 	switch (ccb->ccb_h.func_code) {
156 	case XPT_SCSI_IO:	/* Execute the requested I/O operation */
157 		/*
158 		 * Do a couple of preliminary checks...
159 		 */
160 		if ((ccb->ccb_h.flags & CAM_CDB_POINTER) != 0) {
161 			if ((ccb->ccb_h.flags & CAM_CDB_PHYS) != 0) {
162 				ccb->ccb_h.status = CAM_REQ_INVALID;
163 				xpt_done(ccb);
164 				break;
165 			}
166 		}
167 
168 
169 		if (isp->isp_type & ISP_HA_SCSI) {
170 			if (ccb->ccb_h.target_id > (MAX_TARGETS-1)) {
171 				ccb->ccb_h.status = CAM_PATH_INVALID;
172 			} else if (isp->isp_fwrev >= ISP_FW_REV(7, 55)) {
173 				/*
174 				 * Too much breakage.
175 				 */
176 #if	0
177 				if (ccb->ccb_h.target_lun > 31) {
178 					ccb->ccb_h.status = CAM_PATH_INVALID;
179 				}
180 #else
181 				if (ccb->ccb_h.target_lun > 7) {
182 					ccb->ccb_h.status = CAM_PATH_INVALID;
183 				}
184 #endif
185 			} else if (ccb->ccb_h.target_lun > 7) {
186 				ccb->ccb_h.status = CAM_PATH_INVALID;
187 			}
188 		} else {
189 			if (ccb->ccb_h.target_id > (MAX_FC_TARG-1)) {
190 				ccb->ccb_h.status = CAM_PATH_INVALID;
191 #ifdef	SCCLUN
192 			} else if (ccb->ccb_h.target_lun > 15) {
193 				ccb->ccb_h.status = CAM_PATH_INVALID;
194 #else
195 			} else if (ccb->ccb_h.target_lun > 65535) {
196 				ccb->ccb_h.status = CAM_PATH_INVALID;
197 #endif
198 			}
199 		}
200 		if (ccb->ccb_h.status == CAM_PATH_INVALID) {
201 			printf("%s: invalid tgt/lun (%d.%d) in XPT_SCSI_IO\n",
202 			    isp->isp_name, ccb->ccb_h.target_id,
203 			    ccb->ccb_h.target_lun);
204 			xpt_done(ccb);
205 			break;
206 		}
207 
208 		CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_INFO,
209 		    ("cdb[0]=0x%x dlen%d\n",
210 		    (ccb->ccb_h.flags & CAM_CDB_POINTER)?
211 			ccb->csio.cdb_io.cdb_ptr[0]:
212 			ccb->csio.cdb_io.cdb_bytes[0], ccb->csio.dxfer_len));
213 
214 		s = splcam();
215 		DISABLE_INTS(isp);
216 		switch (ispscsicmd((ISP_SCSI_XFER_T *) ccb)) {
217 		case CMD_QUEUED:
218 			ccb->ccb_h.status |= CAM_SIM_QUEUED;
219 			break;
220 		case CMD_EAGAIN:
221 			if (isp->isp_osinfo.simqfrozen == 0) {
222 				xpt_freeze_simq(sim, 1);
223 				isp->isp_osinfo.simqfrozen = 1;
224 			}
225 			ccb->ccb_h.status &= ~CAM_STATUS_MASK;
226                         ccb->ccb_h.status |= CAM_REQUEUE_REQ;
227 			xpt_done(ccb);
228 			break;
229 		case CMD_COMPLETE:
230 			/*
231 			 * Just make sure that we didn't get it returned
232 			 * as completed, but with the request still in
233 			 * progress. In theory, 'cannot happen'.
234 			 */
235 			if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
236 			    CAM_REQ_INPROG) {
237 				ccb->ccb_h.status &= ~CAM_STATUS_MASK;
238 				ccb->ccb_h.status |= CAM_REQ_CMP_ERR;
239 			}
240 			xpt_done(ccb);
241 			break;
242 		}
243 		ENABLE_INTS(isp);
244 		splx(s);
245 		break;
246 
247 	case XPT_EN_LUN:		/* Enable LUN as a target */
248 	case XPT_TARGET_IO:		/* Execute target I/O request */
249 	case XPT_ACCEPT_TARGET_IO:	/* Accept Host Target Mode CDB */
250 	case XPT_CONT_TARGET_IO:	/* Continue Host Target I/O Connection*/
251 		ccb->ccb_h.status = CAM_REQ_INVALID;
252 		xpt_done(ccb);
253 		break;
254 
255 	case XPT_RESET_DEV:		/* BDR the specified SCSI device */
256 		tgt = ccb->ccb_h.target_id;
257 		s = splcam();
258 		error =
259 		    isp_control(isp, ISPCTL_RESET_DEV, (void *)(intptr_t) tgt);
260 		(void) splx(s);
261 		if (error) {
262 			ccb->ccb_h.status = CAM_REQ_CMP_ERR;
263 		} else {
264 			ccb->ccb_h.status = CAM_REQ_CMP;
265 		}
266 		xpt_done(ccb);
267 		break;
268 	case XPT_ABORT:			/* Abort the specified CCB */
269 		s = splcam();
270 		error = isp_control(isp, ISPCTL_ABORT_CMD, ccb);
271 		(void) splx(s);
272 		if (error) {
273 			ccb->ccb_h.status = CAM_REQ_CMP_ERR;
274 		} else {
275 			ccb->ccb_h.status = CAM_REQ_CMP;
276 		}
277 		xpt_done(ccb);
278 		break;
279 
280 	case XPT_SET_TRAN_SETTINGS:	/* Nexus Settings */
281 
282 		cts = &ccb->cts;
283 		tgt = cts->ccb_h.target_id;
284 		s = splcam();
285 		if (isp->isp_type & ISP_HA_FC) {
286 			;	/* nothing to change */
287 		} else {
288 			sdparam *sdp = isp->isp_param;
289 			u_int16_t *dptr;
290 
291 #if	0
292 			if (cts->flags & CCB_TRANS_CURRENT_SETTINGS)
293 				dptr = &sdp->isp_devparam[tgt].cur_dflags;
294 			else
295 				dptr = &sdp->isp_devparam[tgt].dev_flags;
296 #else
297 			/*
298 			 * We always update (internally) from dev_flags
299 			 * so any request to change settings just gets
300 			 * vectored to that location.
301 			 */
302 			dptr = &sdp->isp_devparam[tgt].dev_flags;
303 #endif
304 
305 			/*
306 			 * Note that these operations affect the
307 			 * the permanent flags (dev_flags)- not
308 			 * the current state flags. Then we mark
309 			 * things so that the next operation to
310 			 * this HBA will cause the update to occur.
311 			 */
312 			if (cts->valid & CCB_TRANS_DISC_VALID) {
313 				if ((cts->flags & CCB_TRANS_DISC_ENB) != 0) {
314 					*dptr |= DPARM_DISC;
315 				} else {
316 					*dptr &= ~DPARM_DISC;
317 				}
318 			}
319 			if (cts->valid & CCB_TRANS_TQ_VALID) {
320 				if ((cts->flags & CCB_TRANS_TAG_ENB) != 0) {
321 					*dptr |= DPARM_TQING;
322 				} else {
323 					*dptr &= ~DPARM_TQING;
324 				}
325 			}
326 			if (cts->valid & CCB_TRANS_BUS_WIDTH_VALID) {
327 				switch (cts->bus_width) {
328 				case MSG_EXT_WDTR_BUS_16_BIT:
329 					*dptr |= DPARM_WIDE;
330 					break;
331 				default:
332 					*dptr &= ~DPARM_WIDE;
333 				}
334 			}
335 			/*
336 			 * Any SYNC RATE of nonzero and SYNC_OFFSET
337 			 * of nonzero will cause us to go to the
338 			 * selected (from NVRAM) maximum value for
339 			 * this device. At a later point, we'll
340 			 * allow finer control.
341 			 */
342 			if ((cts->valid & CCB_TRANS_SYNC_RATE_VALID) &&
343 			    (cts->valid & CCB_TRANS_SYNC_OFFSET_VALID) &&
344 			    (cts->sync_offset > 0)) {
345 				*dptr |= DPARM_SYNC;
346 			} else {
347 				*dptr &= ~DPARM_SYNC;
348 			}
349 			IDPRINTF(3, ("%s: target %d new dev_flags 0x%x\n",
350 			    isp->isp_name, tgt,
351 			    sdp->isp_devparam[tgt].dev_flags));
352 			s = splcam();
353 			sdp->isp_devparam[tgt].dev_update = 1;
354 			isp->isp_update = 1;
355 			(void) isp_control(isp, ISPCTL_UPDATE_PARAMS, NULL);
356 			(void) splx(s);
357 		}
358 		(void) splx(s);
359 		ccb->ccb_h.status = CAM_REQ_CMP;
360 		xpt_done(ccb);
361 		break;
362 
363 	case XPT_GET_TRAN_SETTINGS:
364 
365 		cts = &ccb->cts;
366 		tgt = cts->ccb_h.target_id;
367 		if (isp->isp_type & ISP_HA_FC) {
368 			/*
369 			 * a lot of normal SCSI things don't make sense.
370 			 */
371 			cts->flags = CCB_TRANS_TAG_ENB | CCB_TRANS_DISC_ENB;
372 			cts->valid = CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID;
373 			/*
374 			 * How do you measure the width of a high
375 			 * speed serial bus? Well, in bytes.
376 			 *
377 			 * Offset and period make no sense, though, so we set
378 			 * (above) a 'base' transfer speed to be gigabit.
379 			 */
380 			cts->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
381 		} else {
382 			sdparam *sdp = isp->isp_param;
383 			u_int16_t dval;
384 
385 			if (cts->flags & CCB_TRANS_CURRENT_SETTINGS)
386 				dval = sdp->isp_devparam[tgt].cur_dflags;
387 			else
388 				dval = sdp->isp_devparam[tgt].dev_flags;
389 
390 			s = splcam();
391 			cts->flags &= ~(CCB_TRANS_DISC_ENB|CCB_TRANS_TAG_ENB);
392 
393 			if (dval & DPARM_DISC) {
394 				cts->flags |= CCB_TRANS_DISC_ENB;
395 			}
396 			if (dval & DPARM_TQING) {
397 				cts->flags |= CCB_TRANS_TAG_ENB;
398 			}
399 			if (dval & DPARM_WIDE) {
400 				cts->bus_width = MSG_EXT_WDTR_BUS_16_BIT;
401 			} else {
402 				cts->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
403 			}
404 			cts->valid = CCB_TRANS_BUS_WIDTH_VALID |
405 			    CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID;
406 
407 			if ((dval & DPARM_SYNC) &&
408 			    (sdp->isp_devparam[tgt].sync_offset)) {
409 				cts->sync_period =
410 				    sdp->isp_devparam[tgt].sync_period;
411 				cts->sync_offset =
412 				    sdp->isp_devparam[tgt].sync_offset;
413 				cts->valid |=
414 				    CCB_TRANS_SYNC_RATE_VALID |
415 				    CCB_TRANS_SYNC_OFFSET_VALID;
416 			}
417 			splx(s);
418 		}
419 		ccb->ccb_h.status = CAM_REQ_CMP;
420 		xpt_done(ccb);
421 		break;
422 
423 	case XPT_CALC_GEOMETRY:
424 	{
425 		struct ccb_calc_geometry *ccg;
426 		u_int32_t secs_per_cylinder;
427 		u_int32_t size_mb;
428 
429 		ccg = &ccb->ccg;
430 		if (ccg->block_size == 0) {
431 			printf("%s: %d.%d XPT_CALC_GEOMETRY block size 0?\n",
432 				isp->isp_name, ccg->ccb_h.target_id,
433 				ccg->ccb_h.target_lun);
434 			ccb->ccb_h.status = CAM_REQ_INVALID;
435 			xpt_done(ccb);
436 			break;
437 		}
438 		size_mb = ccg->volume_size /((1024L * 1024L) / ccg->block_size);
439 		if (size_mb > 1024) {
440 			ccg->heads = 255;
441 			ccg->secs_per_track = 63;
442 		} else {
443 			ccg->heads = 64;
444 			ccg->secs_per_track = 32;
445 		}
446 		secs_per_cylinder = ccg->heads * ccg->secs_per_track;
447 		ccg->cylinders = ccg->volume_size / secs_per_cylinder;
448 		ccb->ccb_h.status = CAM_REQ_CMP;
449 		xpt_done(ccb);
450 		break;
451 	}
452 	case XPT_RESET_BUS:		/* Reset the specified bus */
453 		if (isp->isp_type & ISP_HA_FC) {
454 			ccb->ccb_h.status = CAM_REQ_CMP;
455 			xpt_done(ccb);
456                 	break;
457 		}
458 		s = splcam();
459 		error = isp_control(isp, ISPCTL_RESET_BUS, NULL);
460 		(void) splx(s);
461 		if (error)
462 			ccb->ccb_h.status = CAM_REQ_CMP_ERR;
463 		else
464 			ccb->ccb_h.status = CAM_REQ_CMP;
465 		xpt_done(ccb);
466 		break;
467 
468 	case XPT_TERM_IO:		/* Terminate the I/O process */
469 		/* Does this need to be implemented? */
470 		ccb->ccb_h.status = CAM_REQ_INVALID;
471 		xpt_done(ccb);
472 		break;
473 
474 	case XPT_PATH_INQ:		/* Path routing inquiry */
475 	{
476 		struct ccb_pathinq *cpi = &ccb->cpi;
477 
478 		cpi->version_num = 1;
479 		cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE|PI_WIDE_16;
480 		cpi->target_sprt = 0;
481 		cpi->hba_misc = 0;
482 		cpi->hba_eng_cnt = 0;
483 		if (isp->isp_type & ISP_HA_FC) {
484 			cpi->max_target = MAX_FC_TARG-1;
485 			cpi->initiator_id =
486 			    ((fcparam *)isp->isp_param)->isp_loopid;
487 #ifdef	SCCLUN
488 			cpi->max_lun = (1 << 16) - 1;
489 #else
490 			cpi->max_lun = (1 << 4) - 1;
491 #endif
492 		} else {
493 			cpi->initiator_id =
494 			    ((sdparam *)isp->isp_param)->isp_initiator_id;
495 			cpi->max_target =  MAX_TARGETS-1;
496 			if (isp->isp_fwrev >= ISP_FW_REV(7, 55)) {
497 #if	0
498 				/*
499 				 * Too much breakage.
500 				 */
501 				cpi->max_lun = (1 << 5) - 1;
502 #else
503 				cpi->max_lun = (1 << 3) - 1;
504 #endif
505 			} else {
506 				cpi->max_lun = (1 << 3) - 1;
507 			}
508 		}
509 
510 		cpi->bus_id = cam_sim_bus(sim);
511 		strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
512 		strncpy(cpi->hba_vid, "Qlogic", HBA_IDLEN);
513 		strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
514 		cpi->unit_number = cam_sim_unit(sim);
515 		cpi->ccb_h.status = CAM_REQ_CMP;
516 		xpt_done(ccb);
517 		break;
518 	}
519 	default:
520 		ccb->ccb_h.status = CAM_REQ_INVALID;
521 		xpt_done(ccb);
522 		break;
523 	}
524 }
525 
526 #define	ISPDDB	(CAM_DEBUG_INFO|CAM_DEBUG_TRACE|CAM_DEBUG_CDB)
527 void
528 isp_done(struct ccb_scsiio *sccb)
529 {
530 	struct ispsoftc *isp = XS_ISP(sccb);
531 
532 	if (XS_NOERR(sccb))
533 		XS_SETERR(sccb, CAM_REQ_CMP);
534 	sccb->ccb_h.status &= ~CAM_STATUS_MASK;
535 	sccb->ccb_h.status |= sccb->ccb_h.spriv_field0;
536 	if ((sccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP &&
537 	    (sccb->scsi_status != SCSI_STATUS_OK)) {
538 		sccb->ccb_h.status &= ~CAM_STATUS_MASK;
539 		sccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR;
540 	}
541 	if ((sccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
542 		if ((sccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
543 			IDPRINTF(3, ("%s: freeze devq %d.%d ccbstat 0x%x\n",
544 			    isp->isp_name, sccb->ccb_h.target_id,
545 			    sccb->ccb_h.target_lun, sccb->ccb_h.status));
546 			xpt_freeze_devq(sccb->ccb_h.path, 1);
547 			sccb->ccb_h.status |= CAM_DEV_QFRZN;
548 		}
549 	}
550 	if (isp->isp_osinfo.simqfrozen) {
551 		sccb->ccb_h.status |= CAM_RELEASE_SIMQ;
552 		isp->isp_osinfo.simqfrozen = 0;
553 	}
554 	sccb->ccb_h.status &= ~CAM_SIM_QUEUED;
555 	if (CAM_DEBUGGED(sccb->ccb_h.path, ISPDDB) &&
556 	    (sccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
557 		xpt_print_path(sccb->ccb_h.path);
558 		printf("cam completion status 0x%x\n", sccb->ccb_h.status);
559 	}
560 	xpt_done((union ccb *) sccb);
561 }
562 
563 #else
564 
565 static void ispminphys __P((struct buf *));
566 static u_int32_t isp_adapter_info __P((int));
567 static int ispcmd __P((ISP_SCSI_XFER_T *));
568 static void isp_watch __P((void *arg));
569 
570 static struct scsi_adapter isp_switch = {
571 	ispcmd, ispminphys, 0, 0, isp_adapter_info, "isp", { 0, 0 }
572 };
573 static struct scsi_device isp_dev = {
574 	NULL, NULL, NULL, NULL, "isp", 0, { 0, 0 }
575 };
576 static int isp_poll __P((struct ispsoftc *, ISP_SCSI_XFER_T *, int));
577 
578 
579 /*
580  * Complete attachment of hardware, include subdevices.
581  */
582 void
583 isp_attach(struct ispsoftc *isp)
584 {
585 	struct scsibus_data *scbus;
586 
587 	scbus = scsi_alloc_bus();
588 	if(!scbus) {
589 		return;
590 	}
591 	isp->isp_state = ISP_RUNSTATE;
592 	START_WATCHDOG(isp);
593 
594 	isp->isp_osinfo._link.adapter_unit = isp->isp_osinfo.unit;
595 	isp->isp_osinfo._link.adapter_softc = isp;
596 	isp->isp_osinfo._link.adapter = &isp_switch;
597 	isp->isp_osinfo._link.device = &isp_dev;
598 	isp->isp_osinfo._link.flags = 0;
599 	if (isp->isp_type & ISP_HA_FC) {
600 		isp->isp_osinfo._link.adapter_targ =
601 			((fcparam *)isp->isp_param)->isp_loopid;
602 		scbus->maxtarg = MAX_FC_TARG-1;
603 	} else {
604 		isp->isp_osinfo._link.adapter_targ =
605 			((sdparam *)isp->isp_param)->isp_initiator_id;
606 		scbus->maxtarg = MAX_TARGETS-1;
607 	}
608 	/*
609 	 * Prepare the scsibus_data area for the upperlevel scsi code.
610 	 */
611 	scbus->adapter_link = &isp->isp_osinfo._link;
612 
613 	/*
614 	 * ask the adapter what subunits are present
615 	 */
616 	scsi_attachdevs(scbus);
617 }
618 
619 
620 /*
621  * minphys our xfers
622  *
623  * Unfortunately, the buffer pointer describes the target device- not the
624  * adapter device, so we can't use the pointer to find out what kind of
625  * adapter we are and adjust accordingly.
626  */
627 
628 static void
629 ispminphys(struct buf *bp)
630 {
631 	/*
632 	 * Only the 10X0 has a 24 bit limit.
633 	 */
634 	if (bp->b_bcount >= (1 << 24)) {
635 		bp->b_bcount = (1 << 24);
636 	}
637 }
638 
639 static u_int32_t
640 isp_adapter_info(int unit)
641 {
642 	/*
643  	 * XXX: FIND ISP BASED UPON UNIT AND GET REAL QUEUE LIMIT FROM THAT
644 	 */
645 	return (2);
646 }
647 
648 static int
649 ispcmd(ISP_SCSI_XFER_T *xs)
650 {
651 	struct ispsoftc *isp;
652 	int r;
653 	ISP_LOCKVAL_DECL;
654 
655 	isp = XS_ISP(xs);
656 	ISP_LOCK;
657 	r = ispscsicmd(xs);
658 	if (r != CMD_QUEUED || (xs->flags & SCSI_NOMASK) == 0) {
659 		ISP_UNLOCK;
660 		return (r);
661 	}
662 
663 	/*
664 	 * If we can't use interrupts, poll on completion.
665 	 */
666 	if (isp_poll(isp, xs, XS_TIME(xs))) {
667 		/*
668 		 * If no other error occurred but we didn't finish,
669 		 * something bad happened.
670 		 */
671 		if (XS_IS_CMD_DONE(xs) == 0) {
672 			isp->isp_nactive--;
673 			if (isp->isp_nactive < 0)
674 				isp->isp_nactive = 0;
675 			if (XS_NOERR(xs)) {
676 				isp_lostcmd(isp, xs);
677 				XS_SETERR(xs, HBA_BOTCH);
678 			}
679 		}
680 	}
681 	ISP_UNLOCK;
682 	return (CMD_COMPLETE);
683 }
684 
685 static int
686 isp_poll(struct ispsoftc *isp, ISP_SCSI_XFER_T *xs, int mswait)
687 {
688 
689 	while (mswait) {
690 		/* Try the interrupt handling routine */
691 		(void)isp_intr((void *)isp);
692 
693 		/* See if the xs is now done */
694 		if (XS_IS_CMD_DONE(xs))
695 			return (0);
696 		SYS_DELAY(1000);	/* wait one millisecond */
697 		mswait--;
698 	}
699 	return (1);
700 }
701 
702 static void
703 isp_watch(void *arg)
704 {
705 	int i;
706 	struct ispsoftc *isp = arg;
707 	ISP_SCSI_XFER_T *xs;
708 	ISP_ILOCKVAL_DECL;
709 
710 	/*
711 	 * Look for completely dead commands (but not polled ones).
712 	 */
713 	ISP_ILOCK(isp);
714 	for (i = 0; i < RQUEST_QUEUE_LEN; i++) {
715 		if ((xs = (ISP_SCSI_XFER_T *) isp->isp_xflist[i]) == NULL) {
716 			continue;
717 		}
718 		if (XS_TIME(xs) == 0) {
719 			continue;
720 		}
721 		XS_TIME(xs) -= (WATCH_INTERVAL * 1000);
722 		/*
723 		 * Avoid later thinking that this
724 		 * transaction is not being timed.
725 		 * Then give ourselves to watchdog
726 		 * periods of grace.
727 		 */
728 		if (XS_TIME(xs) == 0)
729 			XS_TIME(xs) = 1;
730 		else if (XS_TIME(xs) > -(2 * WATCH_INTERVAL * 1000)) {
731 			continue;
732 		}
733 		if (isp_control(isp, ISPCTL_ABORT_CMD, xs)) {
734 			printf("%s: isp_watch failed to abort command\n",
735 			    isp->isp_name);
736 			isp_restart(isp);
737 			break;
738 		}
739 	}
740 	RESTART_WATCHDOG(isp_watch, arg);
741 	ISP_IUNLOCK(isp);
742 }
743 #endif
744 
745 /*
746  * Free any associated resources prior to decommissioning and
747  * set the card to a known state (so it doesn't wake up and kick
748  * us when we aren't expecting it to).
749  *
750  * Locks are held before coming here.
751  */
752 void
753 isp_uninit(struct ispsoftc *isp)
754 {
755 	ISP_ILOCKVAL_DECL;
756 	ISP_ILOCK(isp);
757 	/*
758 	 * Leave with interrupts disabled.
759 	 */
760 	DISABLE_INTS(isp);
761 
762 	/*
763 	 * Turn off the watchdog (if active).
764 	 */
765 	STOP_WATCHDOG(isp_watch, isp);
766 
767 	/*
768 	 * And out...
769 	 */
770 	ISP_IUNLOCK(isp);
771 }
772