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