xref: /freebsd/sys/dev/isp/isp_freebsd.c (revision a8445737e740901f5f2c8d24c12ef7fc8b00134e)
1 /* $FreeBSD$ */
2 /* $Id: isp_freebsd.c,v 1.11 1998/09/14 23:22:12 mjacob Exp $ */
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 #ifdef	SCSI_CAM
39 static void isp_async __P((void *, u_int32_t, struct cam_path *, void *));
40 static void isp_poll __P((struct cam_sim *));
41 static void isp_action __P((struct cam_sim *, union ccb *));
42 
43 void
44 isp_attach(isp)
45 	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(cbarg, code, path, arg)
100 	void *cbarg;
101 	u_int32_t code;
102 	struct cam_path *path;
103 	void *arg;
104 {
105 	struct cam_sim *sim;
106 	struct ispsoftc *isp;
107 
108 	sim = (struct cam_sim *)cbarg;
109 	isp = (struct ispsoftc *) cam_sim_softc(sim);
110 	switch (code) {
111 	case AC_LOST_DEVICE:
112 		if (isp->isp_type & ISP_HA_SCSI) {
113 			u_int16_t oflags, nflags;
114 			sdparam *sdp = isp->isp_param;
115 			int s, tgt = xpt_path_target_id(path);
116 
117 			nflags = DPARM_SAFE_DFLT;
118 			if (isp->isp_fwrev >= ISP_FW_REV(7, 55)) {
119 				nflags |= DPARM_NARROW | DPARM_ASYNC;
120 			}
121 			oflags = sdp->isp_devparam[tgt].dev_flags;
122 			sdp->isp_devparam[tgt].dev_flags = nflags;
123 			sdp->isp_devparam[tgt].dev_update = 1;
124 
125 			s = splcam();
126 			(void) isp_control(isp, ISPCTL_UPDATE_PARAMS, NULL);
127 			(void) splx(s);
128 			sdp->isp_devparam[tgt].dev_flags = oflags;
129 		}
130 		break;
131 	default:
132 		break;
133 	}
134 }
135 
136 static void
137 isp_poll(sim)
138 	struct cam_sim *sim;
139 {
140 	isp_intr((struct ispsoftc *) cam_sim_softc(sim));
141 }
142 
143 
144 static void
145 isp_action(sim, ccb)
146 	struct cam_sim *sim;
147 	union ccb *ccb;
148 {
149 	int s, tgt, error;
150 	struct ispsoftc *isp;
151 	struct ccb_trans_settings *cts, set;
152 
153 	CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("isp_action\n"));
154 
155 	isp = (struct ispsoftc *)cam_sim_softc(sim);
156 	ccb->ccb_h.sim_priv.entries[0].field = 0;
157 	ccb->ccb_h.sim_priv.entries[1].ptr = isp;
158 
159 	IDPRINTF(4, ("%s: isp_action code %x\n", isp->isp_name,
160 	    ccb->ccb_h.func_code));
161 
162 	switch (ccb->ccb_h.func_code) {
163 	case XPT_SCSI_IO:	/* Execute the requested I/O operation */
164 		/*
165 		 * Do a couple of preliminary checks...
166 		 */
167 		if ((ccb->ccb_h.flags & CAM_CDB_POINTER) != 0) {
168 			if ((ccb->ccb_h.flags & CAM_CDB_PHYS) != 0) {
169 				ccb->ccb_h.status = CAM_REQ_INVALID;
170 				xpt_done(ccb);
171 				break;
172 			}
173 		}
174 
175 
176 		if (isp->isp_type & ISP_HA_SCSI) {
177 			if (ccb->ccb_h.target_id > (MAX_TARGETS-1)) {
178 				ccb->ccb_h.status = CAM_PATH_INVALID;
179 			} else if (isp->isp_fwrev >= ISP_FW_REV(7, 55)) {
180 				/*
181 				 * Too much breakage.
182 				 */
183 #if	0
184 				if (ccb->ccb_h.target_lun > 31) {
185 					ccb->ccb_h.status = CAM_PATH_INVALID;
186 				}
187 #else
188 				if (ccb->ccb_h.target_lun > 7) {
189 					ccb->ccb_h.status = CAM_PATH_INVALID;
190 				}
191 #endif
192 			} else if (ccb->ccb_h.target_lun > 7) {
193 				ccb->ccb_h.status = CAM_PATH_INVALID;
194 			}
195 		} else {
196 			if (ccb->ccb_h.target_id > (MAX_FC_TARG-1)) {
197 				ccb->ccb_h.status = CAM_PATH_INVALID;
198 			} else if (ccb->ccb_h.target_lun > 15) {
199 				ccb->ccb_h.status = CAM_PATH_INVALID;
200 			}
201 		}
202 		if (ccb->ccb_h.status == CAM_PATH_INVALID) {
203 			printf("%s: invalid tgt/lun (%d.%d) in XPT_SCSI_IO\n",
204 			    isp->isp_name, ccb->ccb_h.target_id,
205 			    ccb->ccb_h.target_lun);
206 			xpt_done(ccb);
207 			break;
208 		}
209 
210 		s = splcam();
211 		switch (ispscsicmd((ISP_SCSI_XFER_T *) ccb)) {
212 		case CMD_QUEUED:
213 			ccb->ccb_h.status |= CAM_SIM_QUEUED;
214 			break;
215 		case CMD_EAGAIN:
216 			printf("%s: EAGAINed %d.%d\n", isp->isp_name,
217 			    ccb->ccb_h.target_id, ccb->ccb_h.target_lun);
218 			printf("%s: %d EAGAIN\n", __FILE__, __LINE__);
219 			xpt_freeze_simq(sim, 1);
220 			ccb->ccb_h.status &= ~CAM_STATUS_MASK;
221                         ccb->ccb_h.status |= CAM_REQUEUE_REQ;
222 			xpt_done(ccb);
223 			break;
224 		case CMD_COMPLETE:
225 			printf("%s: COMPLETEd for %d.%d with cam status 0%x\n",
226 			    isp->isp_name, ccb->ccb_h.target_id,
227 			    ccb->ccb_h.target_lun, ccb->ccb_h.status);
228 			if ((ccb->ccb_h.status & CAM_STATUS_MASK) !=
229 			    CAM_REQ_INPROG) {
230 				/* XXX: Cannot Happen */
231 				ccb->ccb_h.status &= ~CAM_STATUS_MASK;
232 				ccb->ccb_h.status |= CAM_REQ_CMP_ERR;
233 			}
234 			xpt_done(ccb);
235 			break;
236 		}
237 		splx(s);
238 		break;
239 
240 	case XPT_EN_LUN:		/* Enable LUN as a target */
241 	case XPT_TARGET_IO:		/* Execute target I/O request */
242 	case XPT_ACCEPT_TARGET_IO:	/* Accept Host Target Mode CDB */
243 	case XPT_CONT_TARGET_IO:	/* Continue Host Target I/O Connection*/
244 		ccb->ccb_h.status = CAM_REQ_INVALID;
245 		xpt_done(ccb);
246 		break;
247 
248 	case XPT_RESET_DEV:		/* BDR the specified SCSI device */
249 		tgt = ccb->ccb_h.target_id;
250 		s = splcam();
251 		error = isp_control(isp, ISPCTL_RESET_DEV, (void *) tgt);
252 		(void) splx(s);
253 		if (error) {
254 			ccb->ccb_h.status = CAM_REQ_CMP_ERR;
255 		} else {
256 			ccb->ccb_h.status = CAM_REQ_CMP;
257 		}
258 		xpt_done(ccb);
259 		break;
260 	case XPT_ABORT:			/* Abort the specified CCB */
261 		s = splcam();
262 		error = isp_control(isp, ISPCTL_ABORT_CMD, ccb);
263 		(void) splx(s);
264 		if (error) {
265 			ccb->ccb_h.status = CAM_REQ_CMP_ERR;
266 		} else {
267 			ccb->ccb_h.status = CAM_REQ_CMP;
268 		}
269 		xpt_done(ccb);
270 		break;
271 
272 	case XPT_SET_TRAN_SETTINGS:	/* Nexus Settings */
273 
274 		cts = &ccb->cts;
275 		tgt = cts->ccb_h.target_id;
276 		s = splcam();
277 		if (isp->isp_type & ISP_HA_FC) {
278 			;	/* nothing to change */
279 		} else {
280 			sdparam *sdp = isp->isp_param;
281 			u_int16_t *dptr;
282 
283 #if	0
284 			if (cts->flags & CCB_TRANS_CURRENT_SETTINGS)
285 				dptr = &sdp->isp_devparam[tgt].cur_dflags;
286 			else
287 				dptr = &sdp->isp_devparam[tgt].dev_flags;
288 #else
289 			/*
290 			 * We always update (internally) from dev_flags
291 			 * so any request to change settings just gets
292 			 * vectored to that location.
293 			 */
294 			dptr = &sdp->isp_devparam[tgt].dev_flags;
295 #endif
296 
297 			/*
298 			 * Note that these operations affect the
299 			 * the permanent flags (dev_flags)- not
300 			 * the current state flags. Then we mark
301 			 * things so that the next operation to
302 			 * this HBA will cause the update to occur.
303 			 */
304 			if (cts->valid & CCB_TRANS_DISC_VALID) {
305 				if ((cts->flags & CCB_TRANS_DISC_ENB) != 0) {
306 					*dptr |= DPARM_DISC;
307 				} else {
308 					*dptr &= ~DPARM_DISC;
309 				}
310 			}
311 			if (cts->valid & CCB_TRANS_TQ_VALID) {
312 				if ((cts->flags & CCB_TRANS_TAG_ENB) != 0) {
313 					*dptr |= DPARM_TQING;
314 				} else {
315 					*dptr &= ~DPARM_TQING;
316 				}
317 			}
318 			if (cts->valid & CCB_TRANS_BUS_WIDTH_VALID) {
319 				switch (cts->bus_width) {
320 				case MSG_EXT_WDTR_BUS_16_BIT:
321 					*dptr |= DPARM_WIDE;
322 					break;
323 				default:
324 					*dptr &= ~DPARM_WIDE;
325 				}
326 			}
327 			/*
328 			 * Any SYNC RATE of nonzero and SYNC_OFFSET
329 			 * of nonzero will cause us to go to the
330 			 * selected (from NVRAM) maximum value for
331 			 * this device. At a later point, we'll
332 			 * allow finer control.
333 			 */
334 			if ((cts->valid & CCB_TRANS_SYNC_RATE_VALID) &&
335 			    (cts->valid & CCB_TRANS_SYNC_OFFSET_VALID) &&
336 			    (cts->sync_offset > 0)) {
337 				*dptr |= DPARM_SYNC;
338 			} else {
339 				*dptr &= ~DPARM_SYNC;
340 			}
341 			IDPRINTF(3, ("%s: target %d new dev_flags 0x%x\n",
342 			    isp->isp_name, tgt,
343 			    sdp->isp_devparam[tgt].dev_flags));
344 			s = splcam();
345 			sdp->isp_devparam[tgt].dev_update = 1;
346 			isp->isp_update = 1;
347 			(void) isp_control(isp, ISPCTL_UPDATE_PARAMS, NULL);
348 			(void) splx(s);
349 		}
350 		(void) splx(s);
351 		ccb->ccb_h.status = CAM_REQ_CMP;
352 		xpt_done(ccb);
353 		break;
354 
355 	case XPT_GET_TRAN_SETTINGS:
356 
357 		cts = &ccb->cts;
358 		tgt = cts->ccb_h.target_id;
359 		if (isp->isp_type & ISP_HA_FC) {
360 			/*
361 			 * a lot of normal SCSI things don't make sense.
362 			 */
363 			cts->flags = CCB_TRANS_TAG_ENB | CCB_TRANS_DISC_ENB;
364 			cts->valid = CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID;
365 			/*
366 			 * How do you measure the width of a high
367 			 * speed serial bus? Well, in bytes.
368 			 *
369 			 * Offset and period make no sense, though, so we set
370 			 * (above) a 'base' transfer speed to be gigabit.
371 			 */
372 			cts->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
373 		} else {
374 			sdparam *sdp = isp->isp_param;
375 			u_int16_t dval;
376 
377 			if (cts->flags & CCB_TRANS_CURRENT_SETTINGS)
378 				dval = sdp->isp_devparam[tgt].cur_dflags;
379 			else
380 				dval = sdp->isp_devparam[tgt].dev_flags;
381 
382 			s = splcam();
383 			cts->flags &= ~(CCB_TRANS_DISC_ENB|CCB_TRANS_TAG_ENB);
384 
385 			if (dval & DPARM_DISC) {
386 				cts->flags |= CCB_TRANS_DISC_ENB;
387 			}
388 			if (dval & DPARM_TQING) {
389 				cts->flags |= CCB_TRANS_TAG_ENB;
390 			}
391 			if (dval & DPARM_WIDE) {
392 				cts->bus_width = MSG_EXT_WDTR_BUS_16_BIT;
393 			} else {
394 				cts->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
395 			}
396 			cts->valid = CCB_TRANS_BUS_WIDTH_VALID |
397 			    CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID;
398 
399 			if ((dval & DPARM_SYNC) &&
400 			    (sdp->isp_devparam[tgt].sync_offset)) {
401 				cts->sync_period =
402 				    sdp->isp_devparam[tgt].sync_period;
403 				cts->sync_offset =
404 				    sdp->isp_devparam[tgt].sync_offset;
405 				cts->valid |=
406 				    CCB_TRANS_SYNC_RATE_VALID |
407 				    CCB_TRANS_SYNC_OFFSET_VALID;
408 			}
409 			splx(s);
410 		}
411 		ccb->ccb_h.status = CAM_REQ_CMP;
412 		xpt_done(ccb);
413 		break;
414 
415 	case XPT_CALC_GEOMETRY:
416 	{
417 		struct ccb_calc_geometry *ccg;
418 		u_int32_t secs_per_cylinder;
419 		u_int32_t size_mb;
420 
421 		ccg = &ccb->ccg;
422 		if (ccg->block_size == 0) {
423 			printf("%s: %d.%d XPT_CALC_GEOMETRY block size 0?\n",
424 				isp->isp_name, ccg->ccb_h.target_id,
425 				ccg->ccb_h.target_lun);
426 			ccb->ccb_h.status = CAM_REQ_INVALID;
427 			xpt_done(ccb);
428 			break;
429 		}
430 		size_mb = ccg->volume_size /((1024L * 1024L) / ccg->block_size);
431 		if (size_mb > 1024) {
432 			ccg->heads = 255;
433 			ccg->secs_per_track = 63;
434 		} else {
435 			ccg->heads = 64;
436 			ccg->secs_per_track = 32;
437 		}
438 		secs_per_cylinder = ccg->heads * ccg->secs_per_track;
439 		ccg->cylinders = ccg->volume_size / secs_per_cylinder;
440 		ccb->ccb_h.status = CAM_REQ_CMP;
441 		xpt_done(ccb);
442 		break;
443 	}
444 	case XPT_RESET_BUS:		/* Reset the specified bus */
445 		if (isp->isp_type & ISP_HA_FC) {
446 			ccb->ccb_h.status = CAM_REQ_CMP;
447 			xpt_done(ccb);
448                 	break;
449 		}
450 		s = splcam();
451 		error = isp_control(isp, ISPCTL_RESET_BUS, NULL);
452 		(void) splx(s);
453 		if (error)
454 			ccb->ccb_h.status = CAM_REQ_CMP_ERR;
455 		else
456 			ccb->ccb_h.status = CAM_REQ_CMP;
457 		xpt_done(ccb);
458 		break;
459 
460 	case XPT_TERM_IO:		/* Terminate the I/O process */
461 		/* Does this need to be implemented? */
462 		ccb->ccb_h.status = CAM_REQ_INVALID;
463 		xpt_done(ccb);
464 		break;
465 
466 	case XPT_PATH_INQ:		/* Path routing inquiry */
467 	{
468 		struct ccb_pathinq *cpi = &ccb->cpi;
469 
470 		cpi->version_num = 1;
471 		cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE|PI_WIDE_16;
472 		cpi->target_sprt = 0;
473 		cpi->hba_misc = 0;
474 		cpi->hba_eng_cnt = 0;
475 		if (isp->isp_type & ISP_HA_FC) {
476 			cpi->max_target = MAX_FC_TARG-1;
477 			cpi->initiator_id =
478 			    ((fcparam *)isp->isp_param)->isp_loopid;
479 			/*
480 			 * XXX: actually, this is not right if we have
481 			 * XXX: 1.14 F/W and the second level lun addressing
482 			 * XXX: in place. It's also probably not right
483 			 * XXX: even for 1.13 f/w.
484 			 */
485 			cpi->max_lun = 15;
486 		} else {
487 			cpi->initiator_id =
488 			    ((sdparam *)isp->isp_param)->isp_initiator_id;
489 			cpi->max_target =  MAX_TARGETS-1;
490 			if (isp->isp_fwrev >= ISP_FW_REV(7, 55)) {
491 				/*
492 				 * Too much breakage.
493 				 */
494 #if	0
495 				cpi->max_lun = 31;
496 #else
497 				cpi->max_lun = 7;
498 #endif
499 			} else {
500 				cpi->max_lun = 7;
501 			}
502 		}
503 
504 		cpi->bus_id = cam_sim_bus(sim);
505 		strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
506 		strncpy(cpi->hba_vid, "Qlogic", HBA_IDLEN);
507 		strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
508 		cpi->unit_number = cam_sim_unit(sim);
509 		cpi->ccb_h.status = CAM_REQ_CMP;
510 		xpt_done(ccb);
511 		break;
512 	}
513 	default:
514 		ccb->ccb_h.status = CAM_REQ_INVALID;
515 		xpt_done(ccb);
516 		break;
517 	}
518 }
519 #else
520 
521 static void ispminphys __P((struct buf *));
522 static u_int32_t isp_adapter_info __P((int));
523 static int ispcmd __P((ISP_SCSI_XFER_T *));
524 
525 static struct scsi_adapter isp_switch = {
526 	ispcmd, ispminphys, 0, 0, isp_adapter_info, "isp", { 0, 0 }
527 };
528 static struct scsi_device isp_dev = {
529 	NULL, NULL, NULL, NULL, "isp", 0, { 0, 0 }
530 };
531 static int isp_poll __P((struct ispsoftc *, ISP_SCSI_XFER_T *, int));
532 
533 
534 /*
535  * Complete attachment of hardware, include subdevices.
536  */
537 void
538 isp_attach(isp)
539 	struct ispsoftc *isp;
540 {
541 	struct scsibus_data *scbus;
542 
543 	scbus = scsi_alloc_bus();
544 	if(!scbus) {
545 		return;
546 	}
547 	isp->isp_state = ISP_RUNSTATE;
548 
549 	isp->isp_osinfo._link.adapter_unit = isp->isp_osinfo.unit;
550 	isp->isp_osinfo._link.adapter_softc = isp;
551 	isp->isp_osinfo._link.adapter = &isp_switch;
552 	isp->isp_osinfo._link.device = &isp_dev;
553 	isp->isp_osinfo._link.flags = 0;
554 	if (isp->isp_type & ISP_HA_FC) {
555 		isp->isp_osinfo._link.adapter_targ =
556 			((fcparam *)isp->isp_param)->isp_loopid;
557 		scbus->maxtarg = MAX_FC_TARG-1;
558 	} else {
559 		isp->isp_osinfo._link.adapter_targ =
560 			((sdparam *)isp->isp_param)->isp_initiator_id;
561 		scbus->maxtarg = MAX_TARGETS-1;
562 	}
563 	/*
564 	 * Prepare the scsibus_data area for the upperlevel scsi code.
565 	 */
566 	scbus->adapter_link = &isp->isp_osinfo._link;
567 
568 	/*
569 	 * ask the adapter what subunits are present
570 	 */
571 	scsi_attachdevs(scbus);
572 }
573 
574 
575 /*
576  * minphys our xfers
577  *
578  * Unfortunately, the buffer pointer describes the target device- not the
579  * adapter device, so we can't use the pointer to find out what kind of
580  * adapter we are and adjust accordingly.
581  */
582 
583 static void
584 ispminphys(bp)
585 	struct buf *bp;
586 {
587 	/*
588 	 * Only the 10X0 has a 24 bit limit.
589 	 */
590 	if (bp->b_bcount >= (1 << 24)) {
591 		bp->b_bcount = (1 << 24);
592 	}
593 }
594 
595 static u_int32_t
596 isp_adapter_info(unit)
597 	int unit;
598 {
599 	/*
600  	 * XXX: FIND ISP BASED UPON UNIT AND GET REAL QUEUE LIMIT FROM THAT
601 	 */
602 	return (2);
603 }
604 
605 static int
606 ispcmd(xs)
607 	ISP_SCSI_XFER_T *xs;
608 {
609 	struct ispsoftc *isp;
610 	int r;
611 	ISP_LOCKVAL_DECL;
612 
613 	isp = XS_ISP(xs);
614 	ISP_LOCK;
615 	r = ispscsicmd(xs);
616 	if (r != CMD_QUEUED || (xs->flags & SCSI_NOMASK) == 0) {
617 		ISP_UNLOCK;
618 		return (r);
619 	}
620 
621 	/*
622 	 * If we can't use interrupts, poll on completion.
623 	 */
624 	if (isp_poll(isp, xs, XS_TIME(xs))) {
625 		/*
626 		 * If no other error occurred but we didn't finish,
627 		 * something bad happened.
628 		 */
629 		if (XS_IS_CMD_DONE(xs) == 0) {
630 			isp->isp_nactive--;
631 			if (isp->isp_nactive < 0)
632 				isp->isp_nactive = 0;
633 			if (XS_NOERR(xs)) {
634 				isp_lostcmd(isp, xs);
635 				XS_SETERR(xs, HBA_BOTCH);
636 			}
637 		}
638 	}
639 	ISP_UNLOCK;
640 	return (CMD_COMPLETE);
641 }
642 
643 static int
644 isp_poll(isp, xs, mswait)
645 	struct ispsoftc *isp;
646 	ISP_SCSI_XFER_T *xs;
647 	int mswait;
648 {
649 
650 	while (mswait) {
651 		/* Try the interrupt handling routine */
652 		(void)isp_intr((void *)isp);
653 
654 		/* See if the xs is now done */
655 		if (XS_IS_CMD_DONE(xs))
656 			return (0);
657 		SYS_DELAY(1000);	/* wait one millisecond */
658 		mswait--;
659 	}
660 	return (1);
661 }
662 #endif
663