xref: /freebsd/sys/dev/isp/isp_freebsd.c (revision cc8df88b)
1c3aac50fSPeter Wemm /* $FreeBSD$ */
26054c3f6SMatt Jacob /*
36054c3f6SMatt Jacob  * Platform (FreeBSD) dependent common attachment code for Qlogic adapters.
46054c3f6SMatt Jacob  *
56054c3f6SMatt Jacob  *---------------------------------------
602ab3379SMatt Jacob  * Copyright (c) 1997, 1998, 1999 by Matthew Jacob
76054c3f6SMatt Jacob  * NASA/Ames Research Center
86054c3f6SMatt Jacob  * All rights reserved.
96054c3f6SMatt Jacob  *---------------------------------------
106054c3f6SMatt Jacob  *
116054c3f6SMatt Jacob  * Redistribution and use in source and binary forms, with or without
126054c3f6SMatt Jacob  * modification, are permitted provided that the following conditions
136054c3f6SMatt Jacob  * are met:
146054c3f6SMatt Jacob  * 1. Redistributions of source code must retain the above copyright
156054c3f6SMatt Jacob  *    notice immediately at the beginning of the file, without modification,
166054c3f6SMatt Jacob  *    this list of conditions, and the following disclaimer.
176054c3f6SMatt Jacob  * 2. Redistributions in binary form must reproduce the above copyright
186054c3f6SMatt Jacob  *    notice, this list of conditions and the following disclaimer in the
196054c3f6SMatt Jacob  *    documentation and/or other materials provided with the distribution.
206054c3f6SMatt Jacob  * 3. The name of the author may not be used to endorse or promote products
216054c3f6SMatt Jacob  *    derived from this software without specific prior written permission.
226054c3f6SMatt Jacob  *
236054c3f6SMatt Jacob  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
246054c3f6SMatt Jacob  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
256054c3f6SMatt Jacob  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
266054c3f6SMatt Jacob  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
276054c3f6SMatt Jacob  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
286054c3f6SMatt Jacob  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
296054c3f6SMatt Jacob  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
306054c3f6SMatt Jacob  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
316054c3f6SMatt Jacob  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
326054c3f6SMatt Jacob  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
336054c3f6SMatt Jacob  * SUCH DAMAGE.
346054c3f6SMatt Jacob  */
356054c3f6SMatt Jacob #include <dev/isp/isp_freebsd.h>
366054c3f6SMatt Jacob 
370470d791SMatt Jacob static void isp_cam_async(void *, u_int32_t, struct cam_path *, void *);
380470d791SMatt Jacob static void isp_poll(struct cam_sim *);
390470d791SMatt Jacob static void isp_relsim(void *);
40cc8df88bSMatt Jacob static timeout_t isp_timeout;
41d81ba9d5SMatt Jacob static void isp_action(struct cam_sim *, union ccb *);
420470d791SMatt Jacob 
43cc8df88bSMatt Jacob 
44d81ba9d5SMatt Jacob static struct ispsoftc *isplist = NULL;
450470d791SMatt Jacob /* #define	ISP_LUN0_ONLY	1 */
4622e1dc85SMatt Jacob #ifdef	DEBUG
4722e1dc85SMatt Jacob int isp_debug = 2;
4822e1dc85SMatt Jacob #elif defined(CAMDEBUG) || defined(DIAGNOSTIC)
49ab6c4b31SMatt Jacob int isp_debug = 1;
50ab6c4b31SMatt Jacob #else
51ab6c4b31SMatt Jacob int isp_debug = 0;
520470d791SMatt Jacob #endif
53478f8a96SJustin T. Gibbs 
54478f8a96SJustin T. Gibbs void
55c3055363SMatt Jacob isp_attach(struct ispsoftc *isp)
56478f8a96SJustin T. Gibbs {
57ea6f23cdSMatt Jacob 	int primary, secondary;
58478f8a96SJustin T. Gibbs 	struct ccb_setasync csa;
59478f8a96SJustin T. Gibbs 	struct cam_devq *devq;
60ea6f23cdSMatt Jacob 	struct cam_sim *sim;
61ea6f23cdSMatt Jacob 	struct cam_path *path;
62478f8a96SJustin T. Gibbs 
63478f8a96SJustin T. Gibbs 	/*
64ea6f23cdSMatt Jacob 	 * Establish (in case of 12X0) which bus is the primary.
65ea6f23cdSMatt Jacob 	 */
66ea6f23cdSMatt Jacob 
67ea6f23cdSMatt Jacob 	primary = 0;
68ea6f23cdSMatt Jacob 	secondary = 1;
69ea6f23cdSMatt Jacob 
70ea6f23cdSMatt Jacob 	/*
71ea6f23cdSMatt Jacob 	 * Create the device queue for our SIM(s).
72478f8a96SJustin T. Gibbs 	 */
73ab6c4b31SMatt Jacob 	devq = cam_simq_alloc(isp->isp_maxcmds);
74478f8a96SJustin T. Gibbs 	if (devq == NULL) {
75478f8a96SJustin T. Gibbs 		return;
76478f8a96SJustin T. Gibbs 	}
77478f8a96SJustin T. Gibbs 
78478f8a96SJustin T. Gibbs 	/*
79ea6f23cdSMatt Jacob 	 * Construct our SIM entry.
80478f8a96SJustin T. Gibbs 	 */
81ea6f23cdSMatt Jacob 	sim = cam_sim_alloc(isp_action, isp_poll, "isp", isp,
82ab6c4b31SMatt Jacob 	    isp->isp_unit, 1, isp->isp_maxcmds, devq);
83ea6f23cdSMatt Jacob 	if (sim == NULL) {
84478f8a96SJustin T. Gibbs 		cam_simq_free(devq);
85478f8a96SJustin T. Gibbs 		return;
86478f8a96SJustin T. Gibbs 	}
87ea6f23cdSMatt Jacob 	if (xpt_bus_register(sim, primary) != CAM_SUCCESS) {
88ea6f23cdSMatt Jacob 		cam_sim_free(sim, TRUE);
89478f8a96SJustin T. Gibbs 		return;
90478f8a96SJustin T. Gibbs 	}
91478f8a96SJustin T. Gibbs 
92ea6f23cdSMatt Jacob 	if (xpt_create_path(&path, NULL, cam_sim_path(sim),
93478f8a96SJustin T. Gibbs 	    CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
94ea6f23cdSMatt Jacob 		xpt_bus_deregister(cam_sim_path(sim));
95ea6f23cdSMatt Jacob 		cam_sim_free(sim, TRUE);
96478f8a96SJustin T. Gibbs 		return;
97478f8a96SJustin T. Gibbs 	}
98478f8a96SJustin T. Gibbs 
99ea6f23cdSMatt Jacob 	xpt_setup_ccb(&csa.ccb_h, path, 5);
100478f8a96SJustin T. Gibbs 	csa.ccb_h.func_code = XPT_SASYNC_CB;
101478f8a96SJustin T. Gibbs 	csa.event_enable = AC_LOST_DEVICE;
102cbf57b47SMatt Jacob 	csa.callback = isp_cam_async;
103ea6f23cdSMatt Jacob 	csa.callback_arg = sim;
104478f8a96SJustin T. Gibbs 	xpt_action((union ccb *)&csa);
105ea6f23cdSMatt Jacob 	isp->isp_sim = sim;
106ea6f23cdSMatt Jacob 	isp->isp_path = path;
107478f8a96SJustin T. Gibbs 
108ea6f23cdSMatt Jacob 	/*
109ea6f23cdSMatt Jacob 	 * If we have a second channel, construct SIM entry for that.
110ea6f23cdSMatt Jacob 	 */
11122e1dc85SMatt Jacob 	if (IS_DUALBUS(isp)) {
112ea6f23cdSMatt Jacob 		sim = cam_sim_alloc(isp_action, isp_poll, "isp", isp,
113ab6c4b31SMatt Jacob 		    isp->isp_unit, 1, isp->isp_maxcmds, devq);
114ea6f23cdSMatt Jacob 		if (sim == NULL) {
115ea6f23cdSMatt Jacob 			xpt_bus_deregister(cam_sim_path(isp->isp_sim));
116ea6f23cdSMatt Jacob 			xpt_free_path(isp->isp_path);
117ea6f23cdSMatt Jacob 			cam_simq_free(devq);
118ea6f23cdSMatt Jacob 			return;
119ea6f23cdSMatt Jacob 		}
120ea6f23cdSMatt Jacob 		if (xpt_bus_register(sim, secondary) != CAM_SUCCESS) {
121ea6f23cdSMatt Jacob 			xpt_bus_deregister(cam_sim_path(isp->isp_sim));
122ea6f23cdSMatt Jacob 			xpt_free_path(isp->isp_path);
123ea6f23cdSMatt Jacob 			cam_sim_free(sim, TRUE);
124ea6f23cdSMatt Jacob 			return;
125ea6f23cdSMatt Jacob 		}
126ea6f23cdSMatt Jacob 
127ea6f23cdSMatt Jacob 		if (xpt_create_path(&path, NULL, cam_sim_path(sim),
128ea6f23cdSMatt Jacob 		    CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
129ea6f23cdSMatt Jacob 			xpt_bus_deregister(cam_sim_path(isp->isp_sim));
130ea6f23cdSMatt Jacob 			xpt_free_path(isp->isp_path);
131ea6f23cdSMatt Jacob 			xpt_bus_deregister(cam_sim_path(sim));
132ea6f23cdSMatt Jacob 			cam_sim_free(sim, TRUE);
133ea6f23cdSMatt Jacob 			return;
134ea6f23cdSMatt Jacob 		}
135ea6f23cdSMatt Jacob 
136ea6f23cdSMatt Jacob 		xpt_setup_ccb(&csa.ccb_h, path, 5);
137ea6f23cdSMatt Jacob 		csa.ccb_h.func_code = XPT_SASYNC_CB;
138ea6f23cdSMatt Jacob 		csa.event_enable = AC_LOST_DEVICE;
139ea6f23cdSMatt Jacob 		csa.callback = isp_cam_async;
140ea6f23cdSMatt Jacob 		csa.callback_arg = sim;
141ea6f23cdSMatt Jacob 		xpt_action((union ccb *)&csa);
142ea6f23cdSMatt Jacob 		isp->isp_sim2 = sim;
143ea6f23cdSMatt Jacob 		isp->isp_path2 = path;
144ea6f23cdSMatt Jacob 	}
145478f8a96SJustin T. Gibbs 	isp->isp_state = ISP_RUNSTATE;
146d81ba9d5SMatt Jacob 	if (isplist == NULL) {
147d81ba9d5SMatt Jacob 		isplist = isp;
148d81ba9d5SMatt Jacob 	} else {
149d81ba9d5SMatt Jacob 		struct ispsoftc *tmp = isplist;
150d81ba9d5SMatt Jacob 		while (tmp->isp_osinfo.next) {
151d81ba9d5SMatt Jacob 			tmp = tmp->isp_osinfo.next;
152d81ba9d5SMatt Jacob 		}
153d81ba9d5SMatt Jacob 		tmp->isp_osinfo.next = isp;
154478f8a96SJustin T. Gibbs 	}
1550470d791SMatt Jacob }
156478f8a96SJustin T. Gibbs 
157d81ba9d5SMatt Jacob 
158d81ba9d5SMatt Jacob /*
159d81ba9d5SMatt Jacob  * Put the target mode functions here, because some are inlines
160d81ba9d5SMatt Jacob  */
161d81ba9d5SMatt Jacob 
162d81ba9d5SMatt Jacob #ifdef	ISP_TARGET_MODE
163d81ba9d5SMatt Jacob #include "targbh.h"
164d81ba9d5SMatt Jacob 
165d81ba9d5SMatt Jacob static __inline int is_lun_enabled(struct ispsoftc *, lun_id_t);
166d81ba9d5SMatt Jacob static __inline int are_any_luns_enabled(struct ispsoftc *);
167d81ba9d5SMatt Jacob static __inline tstate_t *get_lun_statep(struct ispsoftc *, lun_id_t);
168d81ba9d5SMatt Jacob static __inline void rls_lun_statep(struct ispsoftc *, tstate_t *);
169d81ba9d5SMatt Jacob static __inline int isp_psema_sig_rqe(struct ispsoftc *);
170d81ba9d5SMatt Jacob static __inline int isp_cv_wait_timed_rqe(struct ispsoftc *, int);
171d81ba9d5SMatt Jacob static __inline void isp_cv_signal_rqe(struct ispsoftc *, int);
172d81ba9d5SMatt Jacob static __inline void isp_vsema_rqe(struct ispsoftc *);
173d81ba9d5SMatt Jacob static cam_status
174d81ba9d5SMatt Jacob create_lun_state(struct ispsoftc *, struct cam_path *, tstate_t **);
175d81ba9d5SMatt Jacob static void destroy_lun_state(struct ispsoftc *, tstate_t *);
176d81ba9d5SMatt Jacob static void isp_en_lun(struct ispsoftc *, union ccb *);
177d81ba9d5SMatt Jacob static cam_status isp_abort_tgt_ccb(struct ispsoftc *, union ccb *);
178d81ba9d5SMatt Jacob static cam_status isp_target_start_ctio(struct ispsoftc *, union ccb *);
179d81ba9d5SMatt Jacob 
180d81ba9d5SMatt Jacob 
181d81ba9d5SMatt Jacob static int isp_handle_platform_atio(struct ispsoftc *, at_entry_t *);
182d81ba9d5SMatt Jacob static int isp_handle_platform_atio2(struct ispsoftc *, at2_entry_t *);
183d81ba9d5SMatt Jacob static int isp_handle_platform_ctio(struct ispsoftc *, void *);
184d81ba9d5SMatt Jacob 
185d81ba9d5SMatt Jacob static __inline int
186d81ba9d5SMatt Jacob is_lun_enabled(struct ispsoftc *isp, lun_id_t lun)
187d81ba9d5SMatt Jacob {
188d81ba9d5SMatt Jacob 	tstate_t *tptr;
189d81ba9d5SMatt Jacob 	int s = splsoftcam();
190d81ba9d5SMatt Jacob 	if ((tptr = isp->isp_osinfo.lun_hash[LUN_HASH_FUNC(lun)]) == NULL) {
191d81ba9d5SMatt Jacob 		splx(s);
192d81ba9d5SMatt Jacob 		return (0);
193d81ba9d5SMatt Jacob 	}
194d81ba9d5SMatt Jacob 	do {
195d81ba9d5SMatt Jacob 		if (tptr->lun == (lun_id_t) lun) {
196d81ba9d5SMatt Jacob 			splx(s);
197d81ba9d5SMatt Jacob 			return (1);
198d81ba9d5SMatt Jacob 		}
199d81ba9d5SMatt Jacob 	} while ((tptr = tptr->next) != NULL);
200d81ba9d5SMatt Jacob 	splx(s);
201d81ba9d5SMatt Jacob 	return (0);
202d81ba9d5SMatt Jacob }
203d81ba9d5SMatt Jacob 
204d81ba9d5SMatt Jacob static __inline int
205d81ba9d5SMatt Jacob are_any_luns_enabled(struct ispsoftc *isp)
206d81ba9d5SMatt Jacob {
207d81ba9d5SMatt Jacob 	int i;
208d81ba9d5SMatt Jacob 	for (i = 0; i < LUN_HASH_SIZE; i++) {
209d81ba9d5SMatt Jacob 		if (isp->isp_osinfo.lun_hash[i]) {
210d81ba9d5SMatt Jacob 			return (1);
211d81ba9d5SMatt Jacob 		}
212d81ba9d5SMatt Jacob 	}
213d81ba9d5SMatt Jacob 	return (0);
214d81ba9d5SMatt Jacob }
215d81ba9d5SMatt Jacob 
216d81ba9d5SMatt Jacob static __inline tstate_t *
217d81ba9d5SMatt Jacob get_lun_statep(struct ispsoftc *isp, lun_id_t lun)
218d81ba9d5SMatt Jacob {
219d81ba9d5SMatt Jacob 	tstate_t *tptr;
220d81ba9d5SMatt Jacob 	int s;
221d81ba9d5SMatt Jacob 
222d81ba9d5SMatt Jacob 	s = splsoftcam();
223d81ba9d5SMatt Jacob 	if (lun == CAM_LUN_WILDCARD) {
224d81ba9d5SMatt Jacob 		tptr = &isp->isp_osinfo.tsdflt;
225d81ba9d5SMatt Jacob 		tptr->hold++;
226d81ba9d5SMatt Jacob 		splx(s);
227d81ba9d5SMatt Jacob 		return (tptr);
228d81ba9d5SMatt Jacob 	} else {
229d81ba9d5SMatt Jacob 		tptr = isp->isp_osinfo.lun_hash[LUN_HASH_FUNC(lun)];
230d81ba9d5SMatt Jacob 	}
231d81ba9d5SMatt Jacob 	if (tptr == NULL) {
232d81ba9d5SMatt Jacob 		splx(s);
233d81ba9d5SMatt Jacob 		return (NULL);
234d81ba9d5SMatt Jacob 	}
235d81ba9d5SMatt Jacob 
236d81ba9d5SMatt Jacob 	do {
237d81ba9d5SMatt Jacob 		if (tptr->lun == lun) {
238d81ba9d5SMatt Jacob 			tptr->hold++;
239d81ba9d5SMatt Jacob 			splx(s);
240d81ba9d5SMatt Jacob 			return (tptr);
241d81ba9d5SMatt Jacob 		}
242d81ba9d5SMatt Jacob 	} while ((tptr = tptr->next) != NULL);
243d81ba9d5SMatt Jacob 	splx(s);
244d81ba9d5SMatt Jacob 	return (tptr);
245d81ba9d5SMatt Jacob }
246d81ba9d5SMatt Jacob 
247d81ba9d5SMatt Jacob static __inline void
248d81ba9d5SMatt Jacob rls_lun_statep(struct ispsoftc *isp, tstate_t *tptr)
249d81ba9d5SMatt Jacob {
250d81ba9d5SMatt Jacob 	if (tptr->hold)
251d81ba9d5SMatt Jacob 		tptr->hold--;
252d81ba9d5SMatt Jacob }
253d81ba9d5SMatt Jacob 
254d81ba9d5SMatt Jacob static __inline int
255d81ba9d5SMatt Jacob isp_psema_sig_rqe(struct ispsoftc *isp)
256d81ba9d5SMatt Jacob {
257d81ba9d5SMatt Jacob 	int s = splcam();
258d81ba9d5SMatt Jacob 	while (isp->isp_osinfo.tmflags & TM_BUSY) {
259d81ba9d5SMatt Jacob 		isp->isp_osinfo.tmflags |= TM_WANTED;
260d81ba9d5SMatt Jacob 		if (tsleep(&isp->isp_osinfo.tmflags, PRIBIO|PCATCH, "i0", 0)) {
261d81ba9d5SMatt Jacob 			splx(s);
262d81ba9d5SMatt Jacob 			return (-1);
263d81ba9d5SMatt Jacob 		}
264d81ba9d5SMatt Jacob 		isp->isp_osinfo.tmflags |= TM_BUSY;
265d81ba9d5SMatt Jacob 	}
266d81ba9d5SMatt Jacob 	splx(s);
267d81ba9d5SMatt Jacob 	return (0);
268d81ba9d5SMatt Jacob }
269d81ba9d5SMatt Jacob 
270d81ba9d5SMatt Jacob static __inline int
271d81ba9d5SMatt Jacob isp_cv_wait_timed_rqe(struct ispsoftc *isp, int timo)
272d81ba9d5SMatt Jacob {
273d81ba9d5SMatt Jacob 	int s = splcam();
274d81ba9d5SMatt Jacob 	if (tsleep(&isp->isp_osinfo.rstatus, PRIBIO, "qt1", timo)) {
275d81ba9d5SMatt Jacob 		splx(s);
276d81ba9d5SMatt Jacob 		return (-1);
277d81ba9d5SMatt Jacob 	}
278d81ba9d5SMatt Jacob 	splx(s);
279d81ba9d5SMatt Jacob 	return (0);
280d81ba9d5SMatt Jacob }
281d81ba9d5SMatt Jacob 
282d81ba9d5SMatt Jacob static __inline void
283d81ba9d5SMatt Jacob isp_cv_signal_rqe(struct ispsoftc *isp, int status)
284d81ba9d5SMatt Jacob {
285d81ba9d5SMatt Jacob 	isp->isp_osinfo.rstatus = status;
286d81ba9d5SMatt Jacob 	wakeup(&isp->isp_osinfo.rstatus);
287d81ba9d5SMatt Jacob }
288d81ba9d5SMatt Jacob 
289d81ba9d5SMatt Jacob static __inline void
290d81ba9d5SMatt Jacob isp_vsema_rqe(struct ispsoftc *isp)
291d81ba9d5SMatt Jacob {
292d81ba9d5SMatt Jacob 	int s = splcam();
293d81ba9d5SMatt Jacob 	if (isp->isp_osinfo.tmflags & TM_WANTED) {
294d81ba9d5SMatt Jacob 		isp->isp_osinfo.tmflags &= ~TM_WANTED;
295d81ba9d5SMatt Jacob 		wakeup(&isp->isp_osinfo.tmflags);
296d81ba9d5SMatt Jacob 	}
297d81ba9d5SMatt Jacob 	isp->isp_osinfo.tmflags &= ~TM_BUSY;
298d81ba9d5SMatt Jacob 	splx(s);
299d81ba9d5SMatt Jacob }
300d81ba9d5SMatt Jacob 
301d81ba9d5SMatt Jacob static cam_status
302d81ba9d5SMatt Jacob create_lun_state(struct ispsoftc *isp, struct cam_path *path, tstate_t **rslt)
303d81ba9d5SMatt Jacob {
304d81ba9d5SMatt Jacob 	int s;
305d81ba9d5SMatt Jacob 	cam_status status;
306d81ba9d5SMatt Jacob 	lun_id_t lun;
307d81ba9d5SMatt Jacob 	tstate_t *tptr, *new;
308d81ba9d5SMatt Jacob 
309d81ba9d5SMatt Jacob 	lun = xpt_path_lun_id(path);
310d81ba9d5SMatt Jacob 	if (lun < 0) {
311d81ba9d5SMatt Jacob 		return (CAM_LUN_INVALID);
312d81ba9d5SMatt Jacob 	}
313d81ba9d5SMatt Jacob 	if (is_lun_enabled(isp, lun)) {
314d81ba9d5SMatt Jacob 		return (CAM_LUN_ALRDY_ENA);
315d81ba9d5SMatt Jacob 	}
316d81ba9d5SMatt Jacob 	new = (tstate_t *) malloc(sizeof (tstate_t), M_DEVBUF, M_NOWAIT);
317d81ba9d5SMatt Jacob 	if (new == NULL) {
318d81ba9d5SMatt Jacob 		return (CAM_RESRC_UNAVAIL);
319d81ba9d5SMatt Jacob 	}
320d81ba9d5SMatt Jacob 	bzero(new, sizeof (tstate_t));
321d81ba9d5SMatt Jacob 
322d81ba9d5SMatt Jacob 	status = xpt_create_path(&new->owner, NULL, xpt_path_path_id(path),
323d81ba9d5SMatt Jacob 	    xpt_path_target_id(path), xpt_path_lun_id(path));
324d81ba9d5SMatt Jacob 	if (status != CAM_REQ_CMP) {
325d81ba9d5SMatt Jacob 		free(new, M_DEVBUF);
326d81ba9d5SMatt Jacob 		return (status);
327d81ba9d5SMatt Jacob 	}
328d81ba9d5SMatt Jacob 	new->lun = lun;
329d81ba9d5SMatt Jacob 	SLIST_INIT(&new->atios);
330d81ba9d5SMatt Jacob 	SLIST_INIT(&new->inots);
331d81ba9d5SMatt Jacob 	new->hold = 1;
332d81ba9d5SMatt Jacob 
333d81ba9d5SMatt Jacob 	s = splsoftcam();
334d81ba9d5SMatt Jacob 	if ((tptr = isp->isp_osinfo.lun_hash[LUN_HASH_FUNC(lun)]) == NULL) {
335d81ba9d5SMatt Jacob 		isp->isp_osinfo.lun_hash[LUN_HASH_FUNC(lun)] = new;
336d81ba9d5SMatt Jacob 	} else {
337d81ba9d5SMatt Jacob 		while (tptr->next)
338d81ba9d5SMatt Jacob 			tptr = tptr->next;
339d81ba9d5SMatt Jacob 		tptr->next = new;
340d81ba9d5SMatt Jacob 	}
341d81ba9d5SMatt Jacob 	splx(s);
342d81ba9d5SMatt Jacob 	*rslt = new;
343d81ba9d5SMatt Jacob 	return (CAM_REQ_CMP);
344d81ba9d5SMatt Jacob }
345d81ba9d5SMatt Jacob 
346d81ba9d5SMatt Jacob static __inline void
347d81ba9d5SMatt Jacob destroy_lun_state(struct ispsoftc *isp, tstate_t *tptr)
348d81ba9d5SMatt Jacob {
349d81ba9d5SMatt Jacob 	tstate_t *lw, *pw;
350d81ba9d5SMatt Jacob 	int s;
351d81ba9d5SMatt Jacob 
352d81ba9d5SMatt Jacob 	s = splsoftcam();
353d81ba9d5SMatt Jacob 	if (tptr->hold) {
354d81ba9d5SMatt Jacob 		splx(s);
355d81ba9d5SMatt Jacob 		return;
356d81ba9d5SMatt Jacob 	}
357d81ba9d5SMatt Jacob 	pw = isp->isp_osinfo.lun_hash[LUN_HASH_FUNC(tptr->lun)];
358d81ba9d5SMatt Jacob 	if (pw == NULL) {
359d81ba9d5SMatt Jacob 		splx(s);
360d81ba9d5SMatt Jacob 		return;
361d81ba9d5SMatt Jacob 	} else if (pw->lun == tptr->lun) {
362d81ba9d5SMatt Jacob 		isp->isp_osinfo.lun_hash[LUN_HASH_FUNC(tptr->lun)] = pw->next;
363d81ba9d5SMatt Jacob 	} else {
364d81ba9d5SMatt Jacob 		lw = pw;
365d81ba9d5SMatt Jacob 		pw = lw->next;
366d81ba9d5SMatt Jacob 		while (pw) {
367d81ba9d5SMatt Jacob 			if (pw->lun == tptr->lun) {
368d81ba9d5SMatt Jacob 				lw->next = pw->next;
369d81ba9d5SMatt Jacob 				break;
370d81ba9d5SMatt Jacob 			}
371d81ba9d5SMatt Jacob 			lw = pw;
372d81ba9d5SMatt Jacob 			pw = pw->next;
373d81ba9d5SMatt Jacob 		}
374d81ba9d5SMatt Jacob 		if (pw == NULL) {
375d81ba9d5SMatt Jacob 			splx(s);
376d81ba9d5SMatt Jacob 			return;
377d81ba9d5SMatt Jacob 		}
378d81ba9d5SMatt Jacob 	}
379d81ba9d5SMatt Jacob 	free(tptr, M_DEVBUF);
380d81ba9d5SMatt Jacob 	splx(s);
381d81ba9d5SMatt Jacob }
382d81ba9d5SMatt Jacob 
383d81ba9d5SMatt Jacob static void
384d81ba9d5SMatt Jacob isp_en_lun(struct ispsoftc *isp, union ccb *ccb)
385d81ba9d5SMatt Jacob {
386d81ba9d5SMatt Jacob 	const char *lfmt = "Lun now %sabled for target mode\n";
387d81ba9d5SMatt Jacob 	struct ccb_en_lun *cel = &ccb->cel;
388d81ba9d5SMatt Jacob 	tstate_t *tptr;
389d81ba9d5SMatt Jacob 	u_int16_t rstat;
390d81ba9d5SMatt Jacob 	int bus, s;
391d81ba9d5SMatt Jacob 	lun_id_t lun;
392d81ba9d5SMatt Jacob 	target_id_t tgt;
393d81ba9d5SMatt Jacob 
394d81ba9d5SMatt Jacob 
395d81ba9d5SMatt Jacob 	bus = XS_CHANNEL(ccb);
396d81ba9d5SMatt Jacob 	tgt = ccb->ccb_h.target_id;
397d81ba9d5SMatt Jacob 	lun = ccb->ccb_h.target_lun;
398d81ba9d5SMatt Jacob 
399d81ba9d5SMatt Jacob 	/*
400d81ba9d5SMatt Jacob 	 * First, check to see if we're enabling on fibre channel
401d81ba9d5SMatt Jacob 	 * and don't yet have a notion of who the heck we are (no
402d81ba9d5SMatt Jacob 	 * loop yet). We do this by
403d81ba9d5SMatt Jacob 	 */
404d81ba9d5SMatt Jacob 	if (IS_FC(isp) && cel->enable &&
405d81ba9d5SMatt Jacob 	    (isp->isp_osinfo.tmflags & TM_TMODE_ENABLED) == 0) {
406d81ba9d5SMatt Jacob 		int rv;
407d81ba9d5SMatt Jacob 		fcparam *fcp = isp->isp_param;
408d81ba9d5SMatt Jacob 
409d81ba9d5SMatt Jacob 		s = splcam();
410d81ba9d5SMatt Jacob 		rv = isp_control(isp, ISPCTL_FCLINK_TEST, NULL);
411d81ba9d5SMatt Jacob 		(void) splx(s);
412d81ba9d5SMatt Jacob 		if (rv || fcp->isp_fwstate != FW_READY) {
413d81ba9d5SMatt Jacob 			xpt_print_path(ccb->ccb_h.path);
414d81ba9d5SMatt Jacob 			printf("link status not good yet\n");
415d81ba9d5SMatt Jacob 			ccb->ccb_h.status = CAM_REQ_CMP_ERR;
416d81ba9d5SMatt Jacob 			return;
417d81ba9d5SMatt Jacob 		}
418d81ba9d5SMatt Jacob 		s = splcam();
419d81ba9d5SMatt Jacob 		rv = isp_control(isp, ISPCTL_PDB_SYNC, NULL);
420d81ba9d5SMatt Jacob 		(void) splx(s);
421d81ba9d5SMatt Jacob 		if (rv || fcp->isp_loopstate != LOOP_READY) {
422d81ba9d5SMatt Jacob 			xpt_print_path(ccb->ccb_h.path);
423d81ba9d5SMatt Jacob 			printf("could not get a good port database\n");
424d81ba9d5SMatt Jacob 			ccb->ccb_h.status = CAM_REQ_CMP_ERR;
425d81ba9d5SMatt Jacob 			return;
426d81ba9d5SMatt Jacob 		}
427d81ba9d5SMatt Jacob 	}
428d81ba9d5SMatt Jacob 
429d81ba9d5SMatt Jacob 
430d81ba9d5SMatt Jacob 	/*
431d81ba9d5SMatt Jacob 	 * Next check to see whether this is a target/lun wildcard action.
432d81ba9d5SMatt Jacob 	 *
433d81ba9d5SMatt Jacob 	 * If so, we enable/disable target mode but don't do any lun enabling.
434d81ba9d5SMatt Jacob 	 */
435d81ba9d5SMatt Jacob 	if (lun == CAM_LUN_WILDCARD && tgt == CAM_TARGET_WILDCARD) {
436d81ba9d5SMatt Jacob 		int av;
437d81ba9d5SMatt Jacob 		tptr = &isp->isp_osinfo.tsdflt;
438d81ba9d5SMatt Jacob 		if (cel->enable) {
439d81ba9d5SMatt Jacob 			if (isp->isp_osinfo.tmflags & TM_TMODE_ENABLED) {
440d81ba9d5SMatt Jacob 				ccb->ccb_h.status = CAM_LUN_ALRDY_ENA;
441d81ba9d5SMatt Jacob 				return;
442d81ba9d5SMatt Jacob 			}
443d81ba9d5SMatt Jacob 			ccb->ccb_h.status =
444d81ba9d5SMatt Jacob 			    xpt_create_path(&tptr->owner, NULL,
445d81ba9d5SMatt Jacob 			    xpt_path_path_id(ccb->ccb_h.path),
446d81ba9d5SMatt Jacob 			    xpt_path_target_id(ccb->ccb_h.path),
447d81ba9d5SMatt Jacob 			    xpt_path_lun_id(ccb->ccb_h.path));
448d81ba9d5SMatt Jacob 			if (ccb->ccb_h.status != CAM_REQ_CMP) {
449d81ba9d5SMatt Jacob 				return;
450d81ba9d5SMatt Jacob 			}
451d81ba9d5SMatt Jacob 			SLIST_INIT(&tptr->atios);
452d81ba9d5SMatt Jacob 			SLIST_INIT(&tptr->inots);
453d81ba9d5SMatt Jacob 			av = 1;
454d81ba9d5SMatt Jacob 			s = splcam();
455d81ba9d5SMatt Jacob 			av = isp_control(isp, ISPCTL_TOGGLE_TMODE, &av);
456d81ba9d5SMatt Jacob 			if (av) {
457d81ba9d5SMatt Jacob 				ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
458d81ba9d5SMatt Jacob 				xpt_free_path(tptr->owner);
459d81ba9d5SMatt Jacob 				splx(s);
460d81ba9d5SMatt Jacob 				return;
461d81ba9d5SMatt Jacob 			}
462d81ba9d5SMatt Jacob 			isp->isp_osinfo.tmflags |= TM_TMODE_ENABLED;
463d81ba9d5SMatt Jacob 			splx(s);
464d81ba9d5SMatt Jacob 		} else {
465d81ba9d5SMatt Jacob 			if ((isp->isp_osinfo.tmflags & TM_TMODE_ENABLED) == 0) {
466d81ba9d5SMatt Jacob 				ccb->ccb_h.status = CAM_LUN_INVALID;
467d81ba9d5SMatt Jacob 				return;
468d81ba9d5SMatt Jacob 			}
469d81ba9d5SMatt Jacob 			if (are_any_luns_enabled(isp)) {
470d81ba9d5SMatt Jacob 				ccb->ccb_h.status = CAM_SCSI_BUSY;
471d81ba9d5SMatt Jacob 				return;
472d81ba9d5SMatt Jacob 			}
473d81ba9d5SMatt Jacob 			av = 0;
474d81ba9d5SMatt Jacob 			s = splcam();
475d81ba9d5SMatt Jacob 			av = isp_control(isp, ISPCTL_TOGGLE_TMODE, &av);
476d81ba9d5SMatt Jacob 			if (av) {
477d81ba9d5SMatt Jacob 				ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
478d81ba9d5SMatt Jacob 				splx(s);
479d81ba9d5SMatt Jacob 				return;
480d81ba9d5SMatt Jacob 			}
481d81ba9d5SMatt Jacob 			isp->isp_osinfo.tmflags &= ~TM_TMODE_ENABLED;
482d81ba9d5SMatt Jacob 			splx(s);
483d81ba9d5SMatt Jacob 			ccb->ccb_h.status = CAM_REQ_CMP;
484d81ba9d5SMatt Jacob 		}
485d81ba9d5SMatt Jacob 		xpt_print_path(ccb->ccb_h.path);
486d81ba9d5SMatt Jacob 		printf(lfmt, (cel->enable) ? "en" : "dis");
487d81ba9d5SMatt Jacob 		return;
488d81ba9d5SMatt Jacob 	}
489d81ba9d5SMatt Jacob 
490d81ba9d5SMatt Jacob 	/*
491d81ba9d5SMatt Jacob 	 * Do some sanity checking first.
492d81ba9d5SMatt Jacob 	 */
493d81ba9d5SMatt Jacob 
494d81ba9d5SMatt Jacob 	if (IS_SCSI(isp)) {
495d81ba9d5SMatt Jacob 		if (lun < 0 || lun >= 32) {
496d81ba9d5SMatt Jacob 			ccb->ccb_h.status = CAM_LUN_INVALID;
497d81ba9d5SMatt Jacob 			return;
498d81ba9d5SMatt Jacob 		}
499d81ba9d5SMatt Jacob 		if (tgt != CAM_TARGET_WILDCARD &&
500d81ba9d5SMatt Jacob 		    tgt != ((sdparam *) isp->isp_param)->isp_initiator_id) {
501d81ba9d5SMatt Jacob 			ccb->ccb_h.status = CAM_TID_INVALID;
502d81ba9d5SMatt Jacob 			return;
503d81ba9d5SMatt Jacob 		}
504d81ba9d5SMatt Jacob 	} else {
505d81ba9d5SMatt Jacob #ifdef	ISP2100_SCCLUN
506d81ba9d5SMatt Jacob 		if (lun < 0 || lun >= 65536) {
507d81ba9d5SMatt Jacob 			ccb->ccb_h.status = CAM_LUN_INVALID;
508d81ba9d5SMatt Jacob 			return;
50992a1e549SMatt Jacob 		}
510d81ba9d5SMatt Jacob #else
511d81ba9d5SMatt Jacob 		if (lun < 0 || lun >= 16) {
512d81ba9d5SMatt Jacob 			ccb->ccb_h.status = CAM_LUN_INVALID;
513d81ba9d5SMatt Jacob 			return;
514d81ba9d5SMatt Jacob 		}
515d81ba9d5SMatt Jacob #endif
516d81ba9d5SMatt Jacob 		if (tgt != CAM_TARGET_WILDCARD &&
517d81ba9d5SMatt Jacob 		    tgt != ((fcparam *) isp->isp_param)->isp_loopid) {
518d81ba9d5SMatt Jacob 			ccb->ccb_h.status = CAM_TID_INVALID;
519d81ba9d5SMatt Jacob 			return;
520d81ba9d5SMatt Jacob 		}
521d81ba9d5SMatt Jacob 	}
522d81ba9d5SMatt Jacob 
523d81ba9d5SMatt Jacob 
524d81ba9d5SMatt Jacob 	if (cel->enable) {
525d81ba9d5SMatt Jacob 		ccb->ccb_h.status =
526d81ba9d5SMatt Jacob 		    create_lun_state(isp, ccb->ccb_h.path, &tptr);
527d81ba9d5SMatt Jacob 		if (ccb->ccb_h.status != CAM_REQ_CMP) {
528d81ba9d5SMatt Jacob 			return;
529d81ba9d5SMatt Jacob 		}
530d81ba9d5SMatt Jacob 	} else {
531d81ba9d5SMatt Jacob 		tptr = get_lun_statep(isp, lun);
532d81ba9d5SMatt Jacob 		if (tptr == NULL) {
533d81ba9d5SMatt Jacob 			ccb->ccb_h.status = CAM_LUN_INVALID;
534d81ba9d5SMatt Jacob 			return;
535d81ba9d5SMatt Jacob 		}
536d81ba9d5SMatt Jacob 	}
537d81ba9d5SMatt Jacob 
538d81ba9d5SMatt Jacob 	if (isp_psema_sig_rqe(isp)) {
539d81ba9d5SMatt Jacob 		rls_lun_statep(isp, tptr);
540d81ba9d5SMatt Jacob 		if (cel->enable)
541d81ba9d5SMatt Jacob 			destroy_lun_state(isp, tptr);
542d81ba9d5SMatt Jacob 		ccb->ccb_h.status = CAM_REQ_CMP_ERR;
543d81ba9d5SMatt Jacob 		return;
544d81ba9d5SMatt Jacob 	}
545d81ba9d5SMatt Jacob 
546d81ba9d5SMatt Jacob 	s = splcam();
547d81ba9d5SMatt Jacob 	if (cel->enable) {
548d81ba9d5SMatt Jacob 		u_int32_t seq = isp->isp_osinfo.rollinfo++;
549d81ba9d5SMatt Jacob 		rstat = LUN_ERR;
550d81ba9d5SMatt Jacob 		if (isp_lun_cmd(isp, RQSTYPE_ENABLE_LUN, bus, tgt, lun, seq)) {
551d81ba9d5SMatt Jacob 			xpt_print_path(ccb->ccb_h.path);
552d81ba9d5SMatt Jacob 			printf("isp_lun_cmd failed\n");
553d81ba9d5SMatt Jacob 			goto out;
554d81ba9d5SMatt Jacob 		}
555d81ba9d5SMatt Jacob 		if (isp_cv_wait_timed_rqe(isp, 30 * hz)) {
556d81ba9d5SMatt Jacob 			xpt_print_path(ccb->ccb_h.path);
557d81ba9d5SMatt Jacob 			printf("wait for ENABLE LUN timed out\n");
558d81ba9d5SMatt Jacob 			goto out;
559d81ba9d5SMatt Jacob 		}
560d81ba9d5SMatt Jacob 		rstat = isp->isp_osinfo.rstatus;
561d81ba9d5SMatt Jacob 		if (rstat != LUN_OK) {
562d81ba9d5SMatt Jacob 			xpt_print_path(ccb->ccb_h.path);
563d81ba9d5SMatt Jacob 			printf("ENABLE LUN returned 0x%x\n", rstat);
564d81ba9d5SMatt Jacob 			goto out;
565d81ba9d5SMatt Jacob 		}
566d81ba9d5SMatt Jacob 	} else {
567d81ba9d5SMatt Jacob 		u_int32_t seq;
568d81ba9d5SMatt Jacob 
569d81ba9d5SMatt Jacob 		seq = isp->isp_osinfo.rollinfo++;
570d81ba9d5SMatt Jacob 		rstat = LUN_ERR;
571d81ba9d5SMatt Jacob 
572d81ba9d5SMatt Jacob 		if (isp_lun_cmd(isp, -RQSTYPE_MODIFY_LUN, bus, tgt, lun, seq)) {
573d81ba9d5SMatt Jacob 			xpt_print_path(ccb->ccb_h.path);
574d81ba9d5SMatt Jacob 			printf("isp_lun_cmd failed\n");
575d81ba9d5SMatt Jacob 			goto out;
576d81ba9d5SMatt Jacob 		}
577d81ba9d5SMatt Jacob 		if (isp_cv_wait_timed_rqe(isp, 30 * hz)) {
578d81ba9d5SMatt Jacob 			xpt_print_path(ccb->ccb_h.path);
579d81ba9d5SMatt Jacob 			printf("wait for MODIFY LUN timed out\n");
580d81ba9d5SMatt Jacob 			goto out;
581d81ba9d5SMatt Jacob 		}
582d81ba9d5SMatt Jacob 		rstat = isp->isp_osinfo.rstatus;
583d81ba9d5SMatt Jacob 		if (rstat != LUN_OK) {
584d81ba9d5SMatt Jacob 			xpt_print_path(ccb->ccb_h.path);
585d81ba9d5SMatt Jacob 			printf("MODIFY LUN returned 0x%x\n", rstat);
586d81ba9d5SMatt Jacob 			goto out;
587d81ba9d5SMatt Jacob 		}
588d81ba9d5SMatt Jacob 		rstat = LUN_ERR;
589d81ba9d5SMatt Jacob 		seq = isp->isp_osinfo.rollinfo++;
590d81ba9d5SMatt Jacob 
591d81ba9d5SMatt Jacob 		if (isp_lun_cmd(isp, -RQSTYPE_ENABLE_LUN, bus, tgt, lun, seq)) {
592d81ba9d5SMatt Jacob 			xpt_print_path(ccb->ccb_h.path);
593d81ba9d5SMatt Jacob 			printf("isp_lun_cmd failed\n");
594d81ba9d5SMatt Jacob 			goto out;
595d81ba9d5SMatt Jacob 		}
596d81ba9d5SMatt Jacob 		if (isp_cv_wait_timed_rqe(isp, 30 * hz)) {
597d81ba9d5SMatt Jacob 			xpt_print_path(ccb->ccb_h.path);
598d81ba9d5SMatt Jacob 			printf("wait for ENABLE LUN timed out\n");
599d81ba9d5SMatt Jacob 			goto out;
600d81ba9d5SMatt Jacob 		}
601d81ba9d5SMatt Jacob 		rstat = isp->isp_osinfo.rstatus;
602d81ba9d5SMatt Jacob 		if (rstat != LUN_OK) {
603d81ba9d5SMatt Jacob 			xpt_print_path(ccb->ccb_h.path);
604d81ba9d5SMatt Jacob 			printf("ENABLE LUN returned 0x%x\n", rstat);
605d81ba9d5SMatt Jacob 			goto out;
606d81ba9d5SMatt Jacob 		}
607d81ba9d5SMatt Jacob 	}
608d81ba9d5SMatt Jacob out:
609d81ba9d5SMatt Jacob 	isp_vsema_rqe(isp);
610d81ba9d5SMatt Jacob 	splx(s);
611d81ba9d5SMatt Jacob 
612d81ba9d5SMatt Jacob 	if (rstat != LUN_OK) {
613d81ba9d5SMatt Jacob 		xpt_print_path(ccb->ccb_h.path);
614d81ba9d5SMatt Jacob 		printf("lun %sable failed\n", (cel->enable) ? "en" : "dis");
615d81ba9d5SMatt Jacob 		ccb->ccb_h.status = CAM_REQ_CMP_ERR;
616d81ba9d5SMatt Jacob 		rls_lun_statep(isp, tptr);
617d81ba9d5SMatt Jacob 		if (cel->enable)
618d81ba9d5SMatt Jacob 			destroy_lun_state(isp, tptr);
619d81ba9d5SMatt Jacob 	} else {
620d81ba9d5SMatt Jacob 		xpt_print_path(ccb->ccb_h.path);
621d81ba9d5SMatt Jacob 		printf(lfmt, (cel->enable) ? "en" : "dis");
622d81ba9d5SMatt Jacob 		rls_lun_statep(isp, tptr);
623d81ba9d5SMatt Jacob 		if (cel->enable == 0) {
624d81ba9d5SMatt Jacob 			destroy_lun_state(isp, tptr);
625d81ba9d5SMatt Jacob 		}
626d81ba9d5SMatt Jacob 		ccb->ccb_h.status = CAM_REQ_CMP;
627d81ba9d5SMatt Jacob 	}
628d81ba9d5SMatt Jacob }
629d81ba9d5SMatt Jacob 
630d81ba9d5SMatt Jacob static cam_status
631d81ba9d5SMatt Jacob isp_abort_tgt_ccb(struct ispsoftc *isp, union ccb *ccb)
632d81ba9d5SMatt Jacob {
633d81ba9d5SMatt Jacob 	tstate_t *tptr;
634d81ba9d5SMatt Jacob 	struct ccb_hdr_slist *lp;
635d81ba9d5SMatt Jacob 	struct ccb_hdr *curelm;
636d81ba9d5SMatt Jacob 	int found;
637d81ba9d5SMatt Jacob 	union ccb *accb = ccb->cab.abort_ccb;
638d81ba9d5SMatt Jacob 
639d81ba9d5SMatt Jacob 	if (accb->ccb_h.target_id != CAM_TARGET_WILDCARD) {
640d81ba9d5SMatt Jacob 		if (IS_FC(isp) && (accb->ccb_h.target_id !=
641d81ba9d5SMatt Jacob 		    ((fcparam *) isp->isp_param)->isp_loopid)) {
642d81ba9d5SMatt Jacob 			return (CAM_PATH_INVALID);
643d81ba9d5SMatt Jacob 		} else if (IS_SCSI(isp) && (accb->ccb_h.target_id !=
644d81ba9d5SMatt Jacob 		    ((sdparam *) isp->isp_param)->isp_initiator_id)) {
645d81ba9d5SMatt Jacob 			return (CAM_PATH_INVALID);
646d81ba9d5SMatt Jacob 		}
647d81ba9d5SMatt Jacob 	}
648d81ba9d5SMatt Jacob 	tptr = get_lun_statep(isp, accb->ccb_h.target_lun);
649d81ba9d5SMatt Jacob 	if (tptr == NULL) {
650d81ba9d5SMatt Jacob 		return (CAM_PATH_INVALID);
651d81ba9d5SMatt Jacob 	}
652d81ba9d5SMatt Jacob 	if (accb->ccb_h.func_code == XPT_ACCEPT_TARGET_IO) {
653d81ba9d5SMatt Jacob 		lp = &tptr->atios;
654d81ba9d5SMatt Jacob 	} else if (accb->ccb_h.func_code == XPT_IMMED_NOTIFY) {
655d81ba9d5SMatt Jacob 		lp = &tptr->inots;
656d81ba9d5SMatt Jacob 	} else {
657d81ba9d5SMatt Jacob 		rls_lun_statep(isp, tptr);
658d81ba9d5SMatt Jacob 		return (CAM_UA_ABORT);
659d81ba9d5SMatt Jacob 	}
660d81ba9d5SMatt Jacob 	curelm = SLIST_FIRST(lp);
661d81ba9d5SMatt Jacob 	found = 0;
662d81ba9d5SMatt Jacob 	if (curelm == &accb->ccb_h) {
663d81ba9d5SMatt Jacob 		found = 1;
664d81ba9d5SMatt Jacob 		SLIST_REMOVE_HEAD(lp, sim_links.sle);
665d81ba9d5SMatt Jacob 	} else {
666d81ba9d5SMatt Jacob 		while(curelm != NULL) {
667d81ba9d5SMatt Jacob 			struct ccb_hdr *nextelm;
668d81ba9d5SMatt Jacob 
669d81ba9d5SMatt Jacob 			nextelm = SLIST_NEXT(curelm, sim_links.sle);
670d81ba9d5SMatt Jacob 			if (nextelm == &accb->ccb_h) {
671d81ba9d5SMatt Jacob 				found = 1;
672d81ba9d5SMatt Jacob 				SLIST_NEXT(curelm, sim_links.sle) =
673d81ba9d5SMatt Jacob 				    SLIST_NEXT(nextelm, sim_links.sle);
674d81ba9d5SMatt Jacob 				break;
675d81ba9d5SMatt Jacob 			}
676d81ba9d5SMatt Jacob 			curelm = nextelm;
677d81ba9d5SMatt Jacob 		}
678d81ba9d5SMatt Jacob 	}
679d81ba9d5SMatt Jacob 	rls_lun_statep(isp, tptr);
680d81ba9d5SMatt Jacob 	if (found) {
681d81ba9d5SMatt Jacob 		accb->ccb_h.status = CAM_REQ_ABORTED;
682d81ba9d5SMatt Jacob 		return (CAM_REQ_CMP);
683d81ba9d5SMatt Jacob 	}
684d81ba9d5SMatt Jacob 	return(CAM_PATH_INVALID);
685d81ba9d5SMatt Jacob }
686d81ba9d5SMatt Jacob 
687d81ba9d5SMatt Jacob static cam_status
688d81ba9d5SMatt Jacob isp_target_start_ctio(struct ispsoftc *isp, union ccb *ccb)
689d81ba9d5SMatt Jacob {
690d81ba9d5SMatt Jacob 	void *qe;
69100a8e174SMatt Jacob 	struct ccb_scsiio *cso = &ccb->csio;
692d81ba9d5SMatt Jacob 	u_int32_t *hp, save_handle;
693d81ba9d5SMatt Jacob 	u_int16_t iptr, optr;
694d81ba9d5SMatt Jacob 
695d81ba9d5SMatt Jacob 	if (isp_getrqentry(isp, &iptr, &optr, &qe)) {
69692a1e549SMatt Jacob 		xpt_print_path(ccb->ccb_h.path);
69792a1e549SMatt Jacob 		printf("Request Queue Overflow in isp_target_start_ctio\n");
698d81ba9d5SMatt Jacob 		return (CAM_RESRC_UNAVAIL);
699d81ba9d5SMatt Jacob 	}
70092a1e549SMatt Jacob 	bzero(qe, QENTRY_LEN);
701d81ba9d5SMatt Jacob 
702d81ba9d5SMatt Jacob 	/*
703d81ba9d5SMatt Jacob 	 * We're either moving data or completing a command here.
704d81ba9d5SMatt Jacob 	 */
705d81ba9d5SMatt Jacob 
706d81ba9d5SMatt Jacob 	if (IS_FC(isp)) {
707d81ba9d5SMatt Jacob 		ct2_entry_t *cto = qe;
70800a8e174SMatt Jacob 		u_int16_t *ssptr = NULL;
70900a8e174SMatt Jacob 
710d81ba9d5SMatt Jacob 		cto->ct_header.rqs_entry_type = RQSTYPE_CTIO2;
711d81ba9d5SMatt Jacob 		cto->ct_header.rqs_entry_count = 1;
71200a8e174SMatt Jacob 		cto->ct_iid = cso->init_id;
71392a1e549SMatt Jacob #ifndef	ISP2100_SCCLUN
714d81ba9d5SMatt Jacob 		cto->ct_lun = ccb->ccb_h.target_lun;
715d81ba9d5SMatt Jacob #endif
71600a8e174SMatt Jacob 		cto->ct_rxid = cso->tag_id;
71700a8e174SMatt Jacob 		cto->ct_flags = CT2_CCINCR;
71800a8e174SMatt Jacob 		if (cso->dxfer_len == 0) {
71900a8e174SMatt Jacob 			cto->ct_flags |= CT2_FLAG_MODE1 | CT2_NO_DATA;
72000a8e174SMatt Jacob 			KASSERT(ccb->ccb_h.flags & CAM_SEND_STATUS,
72100a8e174SMatt Jacob 			    ("a CTIO with no data and no status?"));
72200a8e174SMatt Jacob 			cto->ct_flags |= CT2_SENDSTATUS;
72300a8e174SMatt Jacob 			ssptr = &cto->rsp.m1.ct_scsi_status;
72400a8e174SMatt Jacob 			*ssptr = cso->scsi_status;
72500a8e174SMatt Jacob 			if ((ccb->ccb_h.flags & CAM_SEND_SENSE) != 0) {
72600a8e174SMatt Jacob 				int m = min(cso->sense_len, MAXRESPLEN);
72700a8e174SMatt Jacob 				bcopy(&cso->sense_data, cto->rsp.m1.ct_resp, m);
72800a8e174SMatt Jacob 				cto->rsp.m1.ct_senselen = m;
72900a8e174SMatt Jacob 				cto->rsp.m1.ct_scsi_status |= CT2_SNSLEN_VALID;
73000a8e174SMatt Jacob 			}
73100a8e174SMatt Jacob 		} else {
73200a8e174SMatt Jacob 			cto->ct_flags |= CT2_FLAG_MODE0;
73300a8e174SMatt Jacob 			if ((cso->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
73400a8e174SMatt Jacob 				cto->ct_flags |= CT2_DATA_IN;
73500a8e174SMatt Jacob 			} else {
73600a8e174SMatt Jacob 				cto->ct_flags |= CT2_DATA_OUT;
737d81ba9d5SMatt Jacob 			}
738d81ba9d5SMatt Jacob 			if ((ccb->ccb_h.flags & CAM_SEND_STATUS) != 0) {
73900a8e174SMatt Jacob 				ssptr = &cto->rsp.m0.ct_scsi_status;
740d81ba9d5SMatt Jacob 				cto->ct_flags |= CT2_SENDSTATUS;
74100a8e174SMatt Jacob 				cto->rsp.m0.ct_scsi_status = cso->scsi_status;
742d81ba9d5SMatt Jacob 			}
74300a8e174SMatt Jacob 			ccb->ccb_h.flags &= ~CAM_SEND_SENSE;
74400a8e174SMatt Jacob 		}
74500a8e174SMatt Jacob 		if (ssptr && cso->resid) {
74600a8e174SMatt Jacob 			cto->ct_resid = cso->resid;
74700a8e174SMatt Jacob 			if (cso->resid < 0)
74800a8e174SMatt Jacob 				*ssptr |= CT2_DATA_OVER;
74900a8e174SMatt Jacob 			else
75000a8e174SMatt Jacob 				*ssptr |= CT2_DATA_UNDER;
75100a8e174SMatt Jacob 		}
752d667c06cSMatt Jacob 		if (isp_tdebug > 1 && ssptr &&
75300a8e174SMatt Jacob 		    (cso->scsi_status != SCSI_STATUS_OK || cso->resid)) {
75492a1e549SMatt Jacob 			printf("%s:CTIO2 RX_ID 0x%x SCSI STATUS 0x%x "
75592a1e549SMatt Jacob 			    "resid %d\n", isp->isp_name, cto->ct_rxid,
75600a8e174SMatt Jacob 			    cso->scsi_status, cso->resid);
757d81ba9d5SMatt Jacob 		}
758d81ba9d5SMatt Jacob 		hp = &cto->ct_reserved;
759d81ba9d5SMatt Jacob 	} else {
760d81ba9d5SMatt Jacob 		ct_entry_t *cto = qe;
76100a8e174SMatt Jacob 
762d81ba9d5SMatt Jacob 		cto->ct_header.rqs_entry_type = RQSTYPE_CTIO;
763d81ba9d5SMatt Jacob 		cto->ct_header.rqs_entry_count = 1;
76400a8e174SMatt Jacob 		cto->ct_iid = cso->init_id;
765d81ba9d5SMatt Jacob 		cto->ct_tgt = ccb->ccb_h.target_id;
766d81ba9d5SMatt Jacob 		cto->ct_lun = ccb->ccb_h.target_lun;
76700a8e174SMatt Jacob 		cto->ct_tag_type = cso->tag_action;
76800a8e174SMatt Jacob 		cto->ct_tag_val = cso->tag_id;
769d81ba9d5SMatt Jacob 		cto->ct_flags = CT_CCINCR;
77000a8e174SMatt Jacob 		if (cso->dxfer_len) {
771d81ba9d5SMatt Jacob 			cto->ct_flags |= CT_NO_DATA;
77200a8e174SMatt Jacob 		} else if ((cso->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
77300a8e174SMatt Jacob 			cto->ct_flags |= CT_DATA_IN;
77400a8e174SMatt Jacob 		} else {
77500a8e174SMatt Jacob 			cto->ct_flags |= CT_DATA_OUT;
776d81ba9d5SMatt Jacob 		}
777d81ba9d5SMatt Jacob 		if ((ccb->ccb_h.flags & CAM_SEND_STATUS) != 0) {
778d81ba9d5SMatt Jacob 			cto->ct_flags |= CT_SENDSTATUS;
77900a8e174SMatt Jacob 			cto->ct_scsi_status = cso->scsi_status;
78000a8e174SMatt Jacob 			cto->ct_resid = cso->resid;
781d81ba9d5SMatt Jacob 		}
782d667c06cSMatt Jacob 		if (isp_tdebug > 1 &&
78300a8e174SMatt Jacob 		    (cso->scsi_status != SCSI_STATUS_OK || cso->resid)) {
78492a1e549SMatt Jacob 			printf("%s:CTIO SCSI STATUS 0x%x resid %d\n",
78500a8e174SMatt Jacob 			    isp->isp_name, cso->scsi_status, cso->resid);
78692a1e549SMatt Jacob 		}
787d81ba9d5SMatt Jacob 		hp = &cto->ct_reserved;
78800a8e174SMatt Jacob 		ccb->ccb_h.flags &= ~CAM_SEND_SENSE;
789d81ba9d5SMatt Jacob 	}
790d81ba9d5SMatt Jacob 
791d81ba9d5SMatt Jacob 	if (isp_save_xs(isp, (ISP_SCSI_XFER_T *)ccb, hp)) {
79292a1e549SMatt Jacob 		xpt_print_path(ccb->ccb_h.path);
79392a1e549SMatt Jacob 		printf("No XFLIST pointers for isp_target_start_ctio\n");
794d81ba9d5SMatt Jacob 		return (CAM_RESRC_UNAVAIL);
795d81ba9d5SMatt Jacob 	}
796d81ba9d5SMatt Jacob 
797d81ba9d5SMatt Jacob 
798d81ba9d5SMatt Jacob 	/*
799d81ba9d5SMatt Jacob 	 * Call the dma setup routines for this entry (and any subsequent
800d81ba9d5SMatt Jacob 	 * CTIOs) if there's data to move, and then tell the f/w it's got
801d81ba9d5SMatt Jacob 	 * new things to play with. As with ispscsicmd's usage of DMA setup,
802d81ba9d5SMatt Jacob 	 * any swizzling is done in the machine dependent layer. Because
803d81ba9d5SMatt Jacob 	 * of this, we put the request onto the queue area first in native
804d81ba9d5SMatt Jacob 	 * format.
805d81ba9d5SMatt Jacob 	 */
806d81ba9d5SMatt Jacob 
807d81ba9d5SMatt Jacob 	save_handle = *hp;
80800a8e174SMatt Jacob 	switch (ISP_DMASETUP(isp, cso, qe, &iptr, optr)) {
809d81ba9d5SMatt Jacob 	case CMD_QUEUED:
810d81ba9d5SMatt Jacob 		MemoryBarrier();
811d81ba9d5SMatt Jacob 		ISP_ADD_REQUEST(isp, iptr);
812d81ba9d5SMatt Jacob 		return (CAM_REQ_INPROG);
813d81ba9d5SMatt Jacob 
814d81ba9d5SMatt Jacob 	case CMD_EAGAIN:
815d81ba9d5SMatt Jacob 		ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
816d81ba9d5SMatt Jacob 		isp_destroy_handle(isp, save_handle);
817d81ba9d5SMatt Jacob 		return (CAM_RESRC_UNAVAIL);
818d81ba9d5SMatt Jacob 
819d81ba9d5SMatt Jacob 	default:
820d81ba9d5SMatt Jacob 		isp_destroy_handle(isp, save_handle);
821d81ba9d5SMatt Jacob 		return (ccb->ccb_h.spriv_field0);
822d81ba9d5SMatt Jacob 	}
823d81ba9d5SMatt Jacob }
824d81ba9d5SMatt Jacob 
825d81ba9d5SMatt Jacob /*
826d81ba9d5SMatt Jacob  * Handle ATIO stuff that the generic code can't.
827d81ba9d5SMatt Jacob  * This means handling CDBs.
828d81ba9d5SMatt Jacob  */
829d81ba9d5SMatt Jacob 
830d81ba9d5SMatt Jacob static int
831d81ba9d5SMatt Jacob isp_handle_platform_atio(struct ispsoftc *isp, at_entry_t *aep)
832d81ba9d5SMatt Jacob {
833d81ba9d5SMatt Jacob 	tstate_t *tptr;
834d81ba9d5SMatt Jacob 	int status;
835d81ba9d5SMatt Jacob 	struct ccb_accept_tio *atiop;
836d81ba9d5SMatt Jacob 
837d81ba9d5SMatt Jacob 	/*
838d81ba9d5SMatt Jacob 	 * The firmware status (except for the QLTM_SVALID bit)
839d81ba9d5SMatt Jacob 	 * indicates why this ATIO was sent to us.
840d81ba9d5SMatt Jacob 	 *
841d81ba9d5SMatt Jacob 	 * If QLTM_SVALID is set, the firware has recommended Sense Data.
842d81ba9d5SMatt Jacob 	 *
843d81ba9d5SMatt Jacob 	 * If the DISCONNECTS DISABLED bit is set in the flags field,
844d81ba9d5SMatt Jacob 	 * we're still connected on the SCSI bus - i.e. the initiator
845d81ba9d5SMatt Jacob 	 * did not set DiscPriv in the identify message. We don't care
846d81ba9d5SMatt Jacob 	 * about this so it's ignored.
847d81ba9d5SMatt Jacob 	 */
848d81ba9d5SMatt Jacob 	status = aep->at_status;
849d81ba9d5SMatt Jacob 	if ((status & ~QLTM_SVALID) == AT_PHASE_ERROR) {
850d81ba9d5SMatt Jacob 		/*
851d81ba9d5SMatt Jacob 		 * Bus Phase Sequence error. We should have sense data
852d81ba9d5SMatt Jacob 		 * suggested by the f/w. I'm not sure quite yet what
853d81ba9d5SMatt Jacob 		 * to do about this for CAM.
854d81ba9d5SMatt Jacob 		 */
855d81ba9d5SMatt Jacob 		printf("%s: PHASE ERROR\n", isp->isp_name);
856d81ba9d5SMatt Jacob 		isp_endcmd(isp, aep, SCSI_STATUS_BUSY, 0);
857d81ba9d5SMatt Jacob 		return (0);
858d81ba9d5SMatt Jacob 	}
859d81ba9d5SMatt Jacob 	if ((status & ~QLTM_SVALID) != AT_CDB) {
860d81ba9d5SMatt Jacob 		printf("%s: bogus atio (0x%x) leaked to platform\n",
861d81ba9d5SMatt Jacob 		    isp->isp_name, status);
862d81ba9d5SMatt Jacob 		isp_endcmd(isp, aep, SCSI_STATUS_BUSY, 0);
863d81ba9d5SMatt Jacob 		return (0);
864d81ba9d5SMatt Jacob 	}
865d81ba9d5SMatt Jacob 
866d81ba9d5SMatt Jacob 	tptr = get_lun_statep(isp, aep->at_lun);
867d81ba9d5SMatt Jacob 	if (tptr == NULL) {
868d81ba9d5SMatt Jacob 		tptr = get_lun_statep(isp, CAM_LUN_WILDCARD);
869d81ba9d5SMatt Jacob 	}
870d81ba9d5SMatt Jacob 
871d81ba9d5SMatt Jacob 	if (tptr == NULL) {
872d81ba9d5SMatt Jacob 		/*
873d81ba9d5SMatt Jacob 		 * Because we can't autofeed sense data back with
874d81ba9d5SMatt Jacob 		 * a command for parallel SCSI, we can't give back
875d81ba9d5SMatt Jacob 		 * a CHECK CONDITION. We'll give back a BUSY status
876d81ba9d5SMatt Jacob 		 * instead. This works out okay because the only
877d81ba9d5SMatt Jacob 		 * time we should, in fact, get this, is in the
878d81ba9d5SMatt Jacob 		 * case that somebody configured us without the
879d81ba9d5SMatt Jacob 		 * blackhole driver, so they get what they deserve.
880d81ba9d5SMatt Jacob 		 */
881d81ba9d5SMatt Jacob 		isp_endcmd(isp, aep, SCSI_STATUS_BUSY, 0);
882d81ba9d5SMatt Jacob 		return (0);
883d81ba9d5SMatt Jacob 	}
884d81ba9d5SMatt Jacob 
885d81ba9d5SMatt Jacob 	atiop = (struct ccb_accept_tio *) SLIST_FIRST(&tptr->atios);
886d81ba9d5SMatt Jacob 	if (atiop == NULL) {
887d81ba9d5SMatt Jacob 		/*
888d81ba9d5SMatt Jacob 		 * Because we can't autofeed sense data back with
889d81ba9d5SMatt Jacob 		 * a command for parallel SCSI, we can't give back
890d81ba9d5SMatt Jacob 		 * a CHECK CONDITION. We'll give back a QUEUE FULL status
891d81ba9d5SMatt Jacob 		 * instead. This works out okay because the only time we
892d81ba9d5SMatt Jacob 		 * should, in fact, get this, is in the case that we've
893d81ba9d5SMatt Jacob 		 * run out of ATIOS.
894d81ba9d5SMatt Jacob 		 */
895d81ba9d5SMatt Jacob 		xpt_print_path(tptr->owner);
896d81ba9d5SMatt Jacob 		printf("no ATIOS for lun %d from initiator %d\n",
897d81ba9d5SMatt Jacob 		    aep->at_lun, aep->at_iid);
898d81ba9d5SMatt Jacob 		rls_lun_statep(isp, tptr);
899d81ba9d5SMatt Jacob 		if (aep->at_flags & AT_TQAE)
900d81ba9d5SMatt Jacob 			isp_endcmd(isp, aep, SCSI_STATUS_QUEUE_FULL, 0);
901d81ba9d5SMatt Jacob 		else
902d81ba9d5SMatt Jacob 			isp_endcmd(isp, aep, SCSI_STATUS_BUSY, 0);
903d81ba9d5SMatt Jacob 		return (0);
904d81ba9d5SMatt Jacob 	}
905d81ba9d5SMatt Jacob 	SLIST_REMOVE_HEAD(&tptr->atios, sim_links.sle);
906d81ba9d5SMatt Jacob 	if (tptr == &isp->isp_osinfo.tsdflt) {
907d81ba9d5SMatt Jacob 		atiop->ccb_h.target_id = aep->at_tgt;
908d81ba9d5SMatt Jacob 		atiop->ccb_h.target_lun = aep->at_lun;
909d81ba9d5SMatt Jacob 	}
910d81ba9d5SMatt Jacob 	if (aep->at_flags & AT_NODISC) {
911d81ba9d5SMatt Jacob 		xpt_print_path(tptr->owner);
912d81ba9d5SMatt Jacob 		printf("incoming command that cannot disconnect\n");
913d81ba9d5SMatt Jacob 	}
914d81ba9d5SMatt Jacob 
915d81ba9d5SMatt Jacob 
916d81ba9d5SMatt Jacob 	atiop->init_id = aep->at_iid;
917d81ba9d5SMatt Jacob 	atiop->cdb_len = aep->at_cdblen;
918d81ba9d5SMatt Jacob 	MEMCPY(atiop->cdb_io.cdb_bytes, aep->at_cdb, aep->at_cdblen);
919d81ba9d5SMatt Jacob 	atiop->ccb_h.status = CAM_CDB_RECVD;
920d81ba9d5SMatt Jacob 	if ((atiop->tag_action = aep->at_tag_type) != 0) {
921d81ba9d5SMatt Jacob 		atiop->tag_id = aep->at_tag_val;
922d81ba9d5SMatt Jacob 		atiop->ccb_h.status |= CAM_TAG_ACTION_VALID;
923d81ba9d5SMatt Jacob 	}
924d81ba9d5SMatt Jacob 	xpt_done((union ccb*)atiop);
925d667c06cSMatt Jacob 	if (isp_tdebug > 1) {
92692a1e549SMatt Jacob 		printf("%s:ATIO CDB=0x%x iid%d->lun%d tag 0x%x ttype 0x%x\n",
92792a1e549SMatt Jacob 		    isp->isp_name, aep->at_cdb[0] & 0xff, aep->at_iid,
92892a1e549SMatt Jacob 		    aep->at_lun, aep->at_tag_val & 0xff, aep->at_tag_type);
929d81ba9d5SMatt Jacob 	}
930d81ba9d5SMatt Jacob 	rls_lun_statep(isp, tptr);
931d81ba9d5SMatt Jacob 	return (0);
932d81ba9d5SMatt Jacob }
933d81ba9d5SMatt Jacob 
934d81ba9d5SMatt Jacob static int
935d81ba9d5SMatt Jacob isp_handle_platform_atio2(struct ispsoftc *isp, at2_entry_t *aep)
936d81ba9d5SMatt Jacob {
93792a1e549SMatt Jacob 	lun_id_t lun;
938d81ba9d5SMatt Jacob 	tstate_t *tptr;
939d81ba9d5SMatt Jacob 	struct ccb_accept_tio *atiop;
940d81ba9d5SMatt Jacob 
941d81ba9d5SMatt Jacob 	/*
942d81ba9d5SMatt Jacob 	 * The firmware status (except for the QLTM_SVALID bit)
943d81ba9d5SMatt Jacob 	 * indicates why this ATIO was sent to us.
944d81ba9d5SMatt Jacob 	 *
945d81ba9d5SMatt Jacob 	 * If QLTM_SVALID is set, the firware has recommended Sense Data.
946d81ba9d5SMatt Jacob 	 */
947d81ba9d5SMatt Jacob 	if ((aep->at_status & ~QLTM_SVALID) != AT_CDB) {
948d81ba9d5SMatt Jacob 		printf("%s: bogus atio (0x%x) leaked to platform\n",
949d81ba9d5SMatt Jacob 		    isp->isp_name, aep->at_status);
950d81ba9d5SMatt Jacob 		isp_endcmd(isp, aep, SCSI_STATUS_BUSY, 0);
951d81ba9d5SMatt Jacob 		return (0);
952d81ba9d5SMatt Jacob 	}
953d81ba9d5SMatt Jacob 
95492a1e549SMatt Jacob #ifdef	ISP2100_SCCLUN
95592a1e549SMatt Jacob 	lun = aep->at_scclun;
95692a1e549SMatt Jacob #else
95792a1e549SMatt Jacob 	lun = aep->at_lun;
95892a1e549SMatt Jacob #endif
95992a1e549SMatt Jacob 	tptr = get_lun_statep(isp, lun);
960d81ba9d5SMatt Jacob 	if (tptr == NULL) {
961d81ba9d5SMatt Jacob 		tptr = get_lun_statep(isp, CAM_LUN_WILDCARD);
962d81ba9d5SMatt Jacob 	}
963d81ba9d5SMatt Jacob 
964d81ba9d5SMatt Jacob 	if (tptr == NULL) {
965d81ba9d5SMatt Jacob #if	0
966d81ba9d5SMatt Jacob 		/* XXX WE REALLY NEED A HARDWIRED SENSE/INQ CTIO TO USE XXX */
96700a8e174SMatt Jacob 		u_int32_t ccode = SCSI_STATUS_CHECK_COND | ECMD_SVALID;
968d81ba9d5SMatt Jacob #if	NTARGBH > 0
969d81ba9d5SMatt Jacob 		/* Not Ready, Unit Not Self-Configured yet.... */
970d81ba9d5SMatt Jacob 		ccode |= (SSD_KEY_NOT_READY << 8) | (0x3E << 24);
971d81ba9d5SMatt Jacob #else
972d81ba9d5SMatt Jacob 		/* Illegal Request, Unit Not Self-Configured yet.... */
973d81ba9d5SMatt Jacob 		ccode |= (SSD_KEY_ILLEGAL_REQUEST << 8) | (0x25 << 24);
974d81ba9d5SMatt Jacob #endif
975d81ba9d5SMatt Jacob #else
976d81ba9d5SMatt Jacob 		u_int32_t ccode = SCSI_STATUS_BUSY;
977d81ba9d5SMatt Jacob #endif
978d81ba9d5SMatt Jacob 
979d81ba9d5SMatt Jacob 		/*
980d81ba9d5SMatt Jacob 		 * Because we can't autofeed sense data back with
981d81ba9d5SMatt Jacob 		 * a command for parallel SCSI, we can't give back
982d81ba9d5SMatt Jacob 		 * a CHECK CONDITION. We'll give back a BUSY status
983d81ba9d5SMatt Jacob 		 * instead. This works out okay because the only
984d81ba9d5SMatt Jacob 		 * time we should, in fact, get this, is in the
985d81ba9d5SMatt Jacob 		 * case that somebody configured us without the
986d81ba9d5SMatt Jacob 		 * blackhole driver, so they get what they deserve.
987d81ba9d5SMatt Jacob 		 */
988d81ba9d5SMatt Jacob 		isp_endcmd(isp, aep, ccode, 0);
989d81ba9d5SMatt Jacob 		return (0);
990d81ba9d5SMatt Jacob 	}
991d81ba9d5SMatt Jacob 
992d81ba9d5SMatt Jacob 	atiop = (struct ccb_accept_tio *) SLIST_FIRST(&tptr->atios);
993d81ba9d5SMatt Jacob 	if (atiop == NULL) {
994d81ba9d5SMatt Jacob 		/*
995d81ba9d5SMatt Jacob 		 * Because we can't autofeed sense data back with
996d81ba9d5SMatt Jacob 		 * a command for parallel SCSI, we can't give back
997d81ba9d5SMatt Jacob 		 * a CHECK CONDITION. We'll give back a QUEUE FULL status
998d81ba9d5SMatt Jacob 		 * instead. This works out okay because the only time we
999d81ba9d5SMatt Jacob 		 * should, in fact, get this, is in the case that we've
1000d81ba9d5SMatt Jacob 		 * run out of ATIOS.
1001d81ba9d5SMatt Jacob 		 */
1002d81ba9d5SMatt Jacob 		xpt_print_path(tptr->owner);
1003d81ba9d5SMatt Jacob 		printf("no ATIOS for lun %d from initiator %d\n",
100492a1e549SMatt Jacob 		    lun, aep->at_iid);
1005d81ba9d5SMatt Jacob 		rls_lun_statep(isp, tptr);
1006d81ba9d5SMatt Jacob 		if (aep->at_flags & AT_TQAE)
1007d81ba9d5SMatt Jacob 			isp_endcmd(isp, aep, SCSI_STATUS_QUEUE_FULL, 0);
1008d81ba9d5SMatt Jacob 		else
1009d81ba9d5SMatt Jacob 			isp_endcmd(isp, aep, SCSI_STATUS_BUSY, 0);
1010d81ba9d5SMatt Jacob 		return (0);
1011d81ba9d5SMatt Jacob 	}
1012d81ba9d5SMatt Jacob 	SLIST_REMOVE_HEAD(&tptr->atios, sim_links.sle);
1013d81ba9d5SMatt Jacob 	if (tptr == &isp->isp_osinfo.tsdflt) {
1014d81ba9d5SMatt Jacob 		atiop->ccb_h.target_id =
1015d81ba9d5SMatt Jacob 			((fcparam *)isp->isp_param)->isp_loopid;
101692a1e549SMatt Jacob 		atiop->ccb_h.target_lun = lun;
1017d81ba9d5SMatt Jacob 	}
1018d81ba9d5SMatt Jacob 	atiop->init_id = aep->at_iid;
1019d81ba9d5SMatt Jacob 	atiop->cdb_len = ATIO2_CDBLEN;
1020d81ba9d5SMatt Jacob 	MEMCPY(atiop->cdb_io.cdb_bytes, aep->at_cdb, ATIO2_CDBLEN);
1021d81ba9d5SMatt Jacob 	atiop->ccb_h.status = CAM_CDB_RECVD;
1022d81ba9d5SMatt Jacob 	atiop->tag_id = aep->at_rxid;
1023d81ba9d5SMatt Jacob 	switch (aep->at_taskflags & ATIO2_TC_ATTR_MASK) {
1024d81ba9d5SMatt Jacob 	case ATIO2_TC_ATTR_SIMPLEQ:
1025d81ba9d5SMatt Jacob 		atiop->tag_action = MSG_SIMPLE_Q_TAG;
1026d81ba9d5SMatt Jacob 		break;
1027d81ba9d5SMatt Jacob         case ATIO2_TC_ATTR_HEADOFQ:
1028d81ba9d5SMatt Jacob 		atiop->tag_action = MSG_HEAD_OF_Q_TAG;
1029d81ba9d5SMatt Jacob 		break;
1030d81ba9d5SMatt Jacob         case ATIO2_TC_ATTR_ORDERED:
1031d81ba9d5SMatt Jacob 		atiop->tag_action = MSG_ORDERED_Q_TAG;
1032d81ba9d5SMatt Jacob 		break;
1033d81ba9d5SMatt Jacob         case ATIO2_TC_ATTR_ACAQ:		/* ?? */
1034d81ba9d5SMatt Jacob 	case ATIO2_TC_ATTR_UNTAGGED:
1035d81ba9d5SMatt Jacob 	default:
1036d81ba9d5SMatt Jacob 		atiop->tag_action = 0;
1037d81ba9d5SMatt Jacob 		break;
1038d81ba9d5SMatt Jacob 	}
1039d81ba9d5SMatt Jacob 	if (atiop->tag_action != 0) {
1040d81ba9d5SMatt Jacob 		atiop->ccb_h.status |= CAM_TAG_ACTION_VALID;
1041d81ba9d5SMatt Jacob 	}
1042d81ba9d5SMatt Jacob 	xpt_done((union ccb*)atiop);
1043d667c06cSMatt Jacob 	if (isp_tdebug > 1) {
104492a1e549SMatt Jacob 		printf("%s:ATIO2 RX_ID 0x%x CDB=0x%x iid%d->lun%d tattr 0x%x\n",
104592a1e549SMatt Jacob 		    isp->isp_name, aep->at_rxid & 0xffff, aep->at_cdb[0] & 0xff,
104692a1e549SMatt Jacob 		    aep->at_iid, lun, aep->at_taskflags);
1047d81ba9d5SMatt Jacob 	}
1048d81ba9d5SMatt Jacob 	rls_lun_statep(isp, tptr);
1049d81ba9d5SMatt Jacob 	return (0);
1050d81ba9d5SMatt Jacob }
1051d81ba9d5SMatt Jacob 
1052d81ba9d5SMatt Jacob static int
1053d81ba9d5SMatt Jacob isp_handle_platform_ctio(struct ispsoftc *isp, void * arg)
1054d81ba9d5SMatt Jacob {
1055d81ba9d5SMatt Jacob 	union ccb *ccb;
1056d81ba9d5SMatt Jacob 	int sentstatus, ok;
1057d81ba9d5SMatt Jacob 
1058d81ba9d5SMatt Jacob 	/*
1059d81ba9d5SMatt Jacob 	 * CTIO and CTIO2 are close enough....
1060d81ba9d5SMatt Jacob 	 */
1061d81ba9d5SMatt Jacob 
1062d81ba9d5SMatt Jacob 	ccb = (union ccb *) isp_find_xs(isp, ((ct_entry_t *)arg)->ct_reserved);
1063d81ba9d5SMatt Jacob 	KASSERT((ccb != NULL), ("null ccb in isp_handle_platform_ctio"));
1064d81ba9d5SMatt Jacob 	isp_destroy_handle(isp, ((ct_entry_t *)arg)->ct_reserved);
1065d81ba9d5SMatt Jacob 
1066d81ba9d5SMatt Jacob 	if (IS_FC(isp)) {
1067d81ba9d5SMatt Jacob 		ct2_entry_t *ct = arg;
1068d81ba9d5SMatt Jacob 		sentstatus = ct->ct_flags & CT2_SENDSTATUS;
1069d81ba9d5SMatt Jacob 		ok = (ct->ct_status & ~QLTM_SVALID) == CT_OK;
107000a8e174SMatt Jacob 		if (ok && ccb->ccb_h.flags & CAM_SEND_SENSE) {
107100a8e174SMatt Jacob 			ccb->ccb_h.status |= CAM_SENT_SENSE;
107200a8e174SMatt Jacob 		}
1073d667c06cSMatt Jacob 		if (isp_tdebug > 1) {
107400a8e174SMatt Jacob 			printf("%s:CTIO2 RX_ID 0x%x sts 0x%x flg 0x%x sns "
107500a8e174SMatt Jacob 			    "%d FIN\n", isp->isp_name, ct->ct_rxid,
107600a8e174SMatt Jacob 			    ct->ct_status, ct->ct_flags,
107700a8e174SMatt Jacob 			    (ccb->ccb_h.status & CAM_SENT_SENSE) != 0);
1078d81ba9d5SMatt Jacob 		}
1079d81ba9d5SMatt Jacob 	} else {
1080d81ba9d5SMatt Jacob 		ct_entry_t *ct = arg;
1081d81ba9d5SMatt Jacob 		sentstatus = ct->ct_flags & CT_SENDSTATUS;
1082d81ba9d5SMatt Jacob 		ok = (ct->ct_status  & ~QLTM_SVALID) == CT_OK;
1083d667c06cSMatt Jacob 		if (isp_tdebug > 1) {
108400a8e174SMatt Jacob 			printf("%s:CTIO tag 0x%x sts 0x%x flg 0x%x FIN\n",
1085d81ba9d5SMatt Jacob 			    isp->isp_name, ct->ct_tag_val, ct->ct_status,
1086d81ba9d5SMatt Jacob 			    ct->ct_flags);
1087d81ba9d5SMatt Jacob 		}
1088d81ba9d5SMatt Jacob 	}
1089d81ba9d5SMatt Jacob 
1090d81ba9d5SMatt Jacob 	/*
1091d81ba9d5SMatt Jacob 	 * We're here either because data transfers are done (and
1092d81ba9d5SMatt Jacob 	 * it's time to send a final status CTIO) or because the final
1093d81ba9d5SMatt Jacob 	 * status CTIO is done. We don't get called for all intermediate
1094d81ba9d5SMatt Jacob 	 * CTIOs that happen for a large data transfer.
1095d81ba9d5SMatt Jacob 	 *
1096d81ba9d5SMatt Jacob 	 * In any case, for this platform, the upper layers figure out
1097d81ba9d5SMatt Jacob 	 * what to do next, so all we do here is collect status and
1098d81ba9d5SMatt Jacob 	 * pass information along.
1099d81ba9d5SMatt Jacob 	 */
1100d81ba9d5SMatt Jacob 
1101d81ba9d5SMatt Jacob 	if (sentstatus) {
1102d81ba9d5SMatt Jacob 		/*
1103d81ba9d5SMatt Jacob 		 * Data transfer done. See if all went okay.
1104d81ba9d5SMatt Jacob 		 */
1105d81ba9d5SMatt Jacob 		if (ok) {
1106d81ba9d5SMatt Jacob 			ccb->csio.resid = 0;
1107d81ba9d5SMatt Jacob 		} else {
1108d81ba9d5SMatt Jacob 			ccb->csio.resid = ccb->csio.dxfer_len;
1109d81ba9d5SMatt Jacob 		}
1110d81ba9d5SMatt Jacob 	}
1111d81ba9d5SMatt Jacob 
1112d81ba9d5SMatt Jacob 
1113d81ba9d5SMatt Jacob 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG) {
1114d81ba9d5SMatt Jacob 		ccb->ccb_h.status |= CAM_REQ_CMP;
1115d81ba9d5SMatt Jacob 	}
1116d81ba9d5SMatt Jacob 	ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
1117d81ba9d5SMatt Jacob 	if (isp->isp_osinfo.simqfrozen & SIMQFRZ_RESOURCE) {
1118d81ba9d5SMatt Jacob 		isp->isp_osinfo.simqfrozen &= ~SIMQFRZ_RESOURCE;
1119d81ba9d5SMatt Jacob 		if (isp->isp_osinfo.simqfrozen == 0) {
1120d81ba9d5SMatt Jacob 			if ((ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
1121d81ba9d5SMatt Jacob 				IDPRINTF(3, ("%s: isp_done -> relsimq\n",
1122d81ba9d5SMatt Jacob 				    isp->isp_name));
1123d81ba9d5SMatt Jacob 				ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
1124d81ba9d5SMatt Jacob 			} else {
1125d81ba9d5SMatt Jacob 				IDPRINTF(3, ("%s: isp_done -> devq frozen\n",
1126d81ba9d5SMatt Jacob 				    isp->isp_name));
1127d81ba9d5SMatt Jacob 			}
1128d81ba9d5SMatt Jacob 		} else {
1129d81ba9d5SMatt Jacob 			IDPRINTF(3, ("%s: isp_done -> simqfrozen = %x\n",
1130d81ba9d5SMatt Jacob 			    isp->isp_name, isp->isp_osinfo.simqfrozen));
1131d81ba9d5SMatt Jacob 		}
1132d81ba9d5SMatt Jacob 	}
1133d81ba9d5SMatt Jacob 	xpt_done(ccb);
1134d81ba9d5SMatt Jacob 	return (0);
1135d81ba9d5SMatt Jacob }
1136d81ba9d5SMatt Jacob #endif
1137d81ba9d5SMatt Jacob 
1138478f8a96SJustin T. Gibbs static void
1139cbf57b47SMatt Jacob isp_cam_async(void *cbarg, u_int32_t code, struct cam_path *path, void *arg)
1140478f8a96SJustin T. Gibbs {
1141478f8a96SJustin T. Gibbs 	struct cam_sim *sim;
1142478f8a96SJustin T. Gibbs 	struct ispsoftc *isp;
1143478f8a96SJustin T. Gibbs 
1144478f8a96SJustin T. Gibbs 	sim = (struct cam_sim *)cbarg;
1145478f8a96SJustin T. Gibbs 	isp = (struct ispsoftc *) cam_sim_softc(sim);
1146478f8a96SJustin T. Gibbs 	switch (code) {
1147478f8a96SJustin T. Gibbs 	case AC_LOST_DEVICE:
1148ab6c4b31SMatt Jacob 		if (IS_SCSI(isp)) {
1149478f8a96SJustin T. Gibbs 			u_int16_t oflags, nflags;
1150478f8a96SJustin T. Gibbs 			sdparam *sdp = isp->isp_param;
1151f9e908dcSMatt Jacob 			int s, rvf, tgt;
1152478f8a96SJustin T. Gibbs 
1153f9e908dcSMatt Jacob 			tgt = xpt_path_target_id(path);
1154f9e908dcSMatt Jacob 			rvf = ISP_FW_REVX(isp->isp_fwrev);
1155ea6f23cdSMatt Jacob 			s = splcam();
1156ea6f23cdSMatt Jacob 			sdp += cam_sim_bus(sim);
1157ea6f23cdSMatt Jacob 			isp->isp_update |= (1 << cam_sim_bus(sim));
1158478f8a96SJustin T. Gibbs 			nflags = DPARM_SAFE_DFLT;
1159f9e908dcSMatt Jacob 			if (rvf >= ISP_FW_REV(7, 55, 0) ||
1160f9e908dcSMatt Jacob 			   (ISP_FW_REV(4, 55, 0) <= rvf &&
1161f9e908dcSMatt Jacob 			   (rvf < ISP_FW_REV(5, 0, 0)))) {
1162478f8a96SJustin T. Gibbs 				nflags |= DPARM_NARROW | DPARM_ASYNC;
1163478f8a96SJustin T. Gibbs 			}
1164478f8a96SJustin T. Gibbs 			oflags = sdp->isp_devparam[tgt].dev_flags;
1165478f8a96SJustin T. Gibbs 			sdp->isp_devparam[tgt].dev_flags = nflags;
1166478f8a96SJustin T. Gibbs 			sdp->isp_devparam[tgt].dev_update = 1;
1167478f8a96SJustin T. Gibbs 			(void) isp_control(isp, ISPCTL_UPDATE_PARAMS, NULL);
1168478f8a96SJustin T. Gibbs 			sdp->isp_devparam[tgt].dev_flags = oflags;
1169ea6f23cdSMatt Jacob 			(void) splx(s);
1170478f8a96SJustin T. Gibbs 		}
1171478f8a96SJustin T. Gibbs 		break;
1172478f8a96SJustin T. Gibbs 	default:
11730470d791SMatt Jacob 		printf("%s: isp_attach Async Code 0x%x\n", isp->isp_name, code);
1174478f8a96SJustin T. Gibbs 		break;
1175478f8a96SJustin T. Gibbs 	}
1176478f8a96SJustin T. Gibbs }
1177478f8a96SJustin T. Gibbs 
1178478f8a96SJustin T. Gibbs static void
1179c3055363SMatt Jacob isp_poll(struct cam_sim *sim)
1180478f8a96SJustin T. Gibbs {
1181478f8a96SJustin T. Gibbs 	isp_intr((struct ispsoftc *) cam_sim_softc(sim));
1182478f8a96SJustin T. Gibbs }
1183478f8a96SJustin T. Gibbs 
11840470d791SMatt Jacob static void
11850470d791SMatt Jacob isp_relsim(void *arg)
11860470d791SMatt Jacob {
11870470d791SMatt Jacob 	struct ispsoftc *isp = arg;
11880470d791SMatt Jacob 	int s = splcam();
11890470d791SMatt Jacob 	if (isp->isp_osinfo.simqfrozen & SIMQFRZ_TIMED) {
11900470d791SMatt Jacob 		int wasfrozen = isp->isp_osinfo.simqfrozen & SIMQFRZ_TIMED;
11910470d791SMatt Jacob 		isp->isp_osinfo.simqfrozen &= ~SIMQFRZ_TIMED;
11920470d791SMatt Jacob 		if (wasfrozen && isp->isp_osinfo.simqfrozen == 0) {
11930470d791SMatt Jacob 			xpt_release_simq(isp->isp_sim, 1);
11940470d791SMatt Jacob 			IDPRINTF(3, ("%s: timed relsimq\n", isp->isp_name));
11950470d791SMatt Jacob 		}
11960470d791SMatt Jacob 	}
11970470d791SMatt Jacob 	splx(s);
11980470d791SMatt Jacob }
1199ab6c4b31SMatt Jacob 
1200478f8a96SJustin T. Gibbs static void
1201cc8df88bSMatt Jacob isp_timeout(void *arg)
1202cc8df88bSMatt Jacob {
1203cc8df88bSMatt Jacob 	ISP_SCSI_XFER_T *xs = arg;
1204cc8df88bSMatt Jacob 	struct ispsoftc *isp = XS_ISP(xs);
1205cc8df88bSMatt Jacob 	u_int32_t handle;
1206cc8df88bSMatt Jacob 	int s = splcam();
1207cc8df88bSMatt Jacob 	/*
1208cc8df88bSMatt Jacob 	 * We've decide this command is dead. Make sure we're not trying
1209cc8df88bSMatt Jacob 	 * to kill a command that's already dead by getting it's handle.
1210cc8df88bSMatt Jacob 	 */
1211cc8df88bSMatt Jacob 	handle = isp_find_handle(isp, xs);
1212cc8df88bSMatt Jacob 	if (handle) {
1213cc8df88bSMatt Jacob 		isp_destroy_handle(isp, handle);
1214cc8df88bSMatt Jacob 		xpt_print_path(xs->ccb_h.path);
1215cc8df88bSMatt Jacob 		printf("watchdog timeout (handle 0x%x)\n", handle);
1216cc8df88bSMatt Jacob 		XS_SETERR(xs, CAM_CMD_TIMEOUT);
1217cc8df88bSMatt Jacob 		isp_done(xs);
1218cc8df88bSMatt Jacob 	}
1219cc8df88bSMatt Jacob 	(void) splx(s);
1220cc8df88bSMatt Jacob }
1221cc8df88bSMatt Jacob 
1222cc8df88bSMatt Jacob static void
1223c3055363SMatt Jacob isp_action(struct cam_sim *sim, union ccb *ccb)
1224478f8a96SJustin T. Gibbs {
1225ab6c4b31SMatt Jacob 	int s, bus, tgt, error;
1226478f8a96SJustin T. Gibbs 	struct ispsoftc *isp;
12274663e367SJustin T. Gibbs 	struct ccb_trans_settings *cts;
1228478f8a96SJustin T. Gibbs 
1229478f8a96SJustin T. Gibbs 	CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("isp_action\n"));
1230478f8a96SJustin T. Gibbs 
1231478f8a96SJustin T. Gibbs 	isp = (struct ispsoftc *)cam_sim_softc(sim);
1232478f8a96SJustin T. Gibbs 	ccb->ccb_h.sim_priv.entries[0].field = 0;
1233478f8a96SJustin T. Gibbs 	ccb->ccb_h.sim_priv.entries[1].ptr = isp;
12340470d791SMatt Jacob 	if (isp->isp_state != ISP_RUNSTATE &&
12350470d791SMatt Jacob 	    ccb->ccb_h.func_code == XPT_SCSI_IO) {
123657c801f5SMatt Jacob 		s = splcam();
123757c801f5SMatt Jacob 		DISABLE_INTS(isp);
123857c801f5SMatt Jacob 		isp_init(isp);
123957c801f5SMatt Jacob 		if (isp->isp_state != ISP_INITSTATE) {
124057c801f5SMatt Jacob 			(void) splx(s);
124157c801f5SMatt Jacob 			/*
124257c801f5SMatt Jacob 			 * Lie. Say it was a selection timeout.
124357c801f5SMatt Jacob 			 */
124457c801f5SMatt Jacob 			ccb->ccb_h.status = CAM_SEL_TIMEOUT;
12450470d791SMatt Jacob 			ccb->ccb_h.status |= CAM_DEV_QFRZN;
12460470d791SMatt Jacob 			xpt_freeze_devq(ccb->ccb_h.path, 1);
124757c801f5SMatt Jacob 			xpt_done(ccb);
124857c801f5SMatt Jacob 			return;
124957c801f5SMatt Jacob 		}
125057c801f5SMatt Jacob 		isp->isp_state = ISP_RUNSTATE;
125157c801f5SMatt Jacob 		ENABLE_INTS(isp);
125257c801f5SMatt Jacob 		(void) splx(s);
125357c801f5SMatt Jacob 	}
1254478f8a96SJustin T. Gibbs 	IDPRINTF(4, ("%s: isp_action code %x\n", isp->isp_name,
1255478f8a96SJustin T. Gibbs 	    ccb->ccb_h.func_code));
1256478f8a96SJustin T. Gibbs 
1257478f8a96SJustin T. Gibbs 	switch (ccb->ccb_h.func_code) {
1258478f8a96SJustin T. Gibbs 	case XPT_SCSI_IO:	/* Execute the requested I/O operation */
1259478f8a96SJustin T. Gibbs 		/*
1260478f8a96SJustin T. Gibbs 		 * Do a couple of preliminary checks...
1261478f8a96SJustin T. Gibbs 		 */
1262478f8a96SJustin T. Gibbs 		if ((ccb->ccb_h.flags & CAM_CDB_POINTER) != 0) {
1263478f8a96SJustin T. Gibbs 			if ((ccb->ccb_h.flags & CAM_CDB_PHYS) != 0) {
1264478f8a96SJustin T. Gibbs 				ccb->ccb_h.status = CAM_REQ_INVALID;
1265478f8a96SJustin T. Gibbs 				xpt_done(ccb);
1266478f8a96SJustin T. Gibbs 				break;
1267478f8a96SJustin T. Gibbs 			}
1268478f8a96SJustin T. Gibbs 		}
12690470d791SMatt Jacob #ifdef	DIAGNOSTIC
12700470d791SMatt Jacob 		if (ccb->ccb_h.target_id > (ISP_MAX_TARGETS(isp) - 1)) {
1271478f8a96SJustin T. Gibbs 			ccb->ccb_h.status = CAM_PATH_INVALID;
12720470d791SMatt Jacob 		} else if (ccb->ccb_h.target_lun > (ISP_MAX_LUNS(isp) - 1)) {
1273478f8a96SJustin T. Gibbs 			ccb->ccb_h.status = CAM_PATH_INVALID;
1274478f8a96SJustin T. Gibbs 		}
1275478f8a96SJustin T. Gibbs 		if (ccb->ccb_h.status == CAM_PATH_INVALID) {
1276478f8a96SJustin T. Gibbs 			printf("%s: invalid tgt/lun (%d.%d) in XPT_SCSI_IO\n",
1277478f8a96SJustin T. Gibbs 			    isp->isp_name, ccb->ccb_h.target_id,
1278478f8a96SJustin T. Gibbs 			    ccb->ccb_h.target_lun);
1279478f8a96SJustin T. Gibbs 			xpt_done(ccb);
1280478f8a96SJustin T. Gibbs 			break;
1281478f8a96SJustin T. Gibbs 		}
12820470d791SMatt Jacob #endif
12830470d791SMatt Jacob 		((struct ccb_scsiio *) ccb)->scsi_status = SCSI_STATUS_OK;
1284478f8a96SJustin T. Gibbs 		s = splcam();
1285c3055363SMatt Jacob 		DISABLE_INTS(isp);
12860470d791SMatt Jacob 		error = ispscsicmd((ISP_SCSI_XFER_T *) ccb);
12870470d791SMatt Jacob 		ENABLE_INTS(isp);
12880470d791SMatt Jacob 		splx(s);
12890470d791SMatt Jacob 		switch (error) {
1290478f8a96SJustin T. Gibbs 		case CMD_QUEUED:
1291478f8a96SJustin T. Gibbs 			ccb->ccb_h.status |= CAM_SIM_QUEUED;
1292cc8df88bSMatt Jacob 			if (ccb->ccb_h.timeout != CAM_TIME_INFINITY) {
1293cc8df88bSMatt Jacob 				if (ccb->ccb_h.timeout == CAM_TIME_DEFAULT)
1294cc8df88bSMatt Jacob 					ccb->ccb_h.timeout = 5 * 1000;
1295cc8df88bSMatt Jacob 				ccb->ccb_h.timeout_ch =
1296cc8df88bSMatt Jacob 				    timeout(isp_timeout, (caddr_t)ccb,
1297cc8df88bSMatt Jacob 				    (ccb->ccb_h.timeout * hz) / 1000);
1298cc8df88bSMatt Jacob 			}
1299478f8a96SJustin T. Gibbs 			break;
13000470d791SMatt Jacob 		case CMD_RQLATER:
13010470d791SMatt Jacob 			if (isp->isp_osinfo.simqfrozen == 0) {
13020470d791SMatt Jacob 				IDPRINTF(3, ("%s: RQLATER freeze simq\n",
13030470d791SMatt Jacob 				    isp->isp_name));
13040470d791SMatt Jacob 				isp->isp_osinfo.simqfrozen |= SIMQFRZ_TIMED;
13050470d791SMatt Jacob 				timeout(isp_relsim, isp, 500);
1306478f8a96SJustin T. Gibbs 				xpt_freeze_simq(sim, 1);
130700f50ce8SMatt Jacob 			}
1308478f8a96SJustin T. Gibbs 			ccb->ccb_h.status &= ~CAM_STATUS_MASK;
1309478f8a96SJustin T. Gibbs                         ccb->ccb_h.status |= CAM_REQUEUE_REQ;
1310478f8a96SJustin T. Gibbs 			xpt_done(ccb);
1311478f8a96SJustin T. Gibbs 			break;
13120470d791SMatt Jacob 		case CMD_EAGAIN:
13130470d791SMatt Jacob 			if (isp->isp_osinfo.simqfrozen == 0) {
13140470d791SMatt Jacob 				xpt_freeze_simq(sim, 1);
13150470d791SMatt Jacob 				IDPRINTF(3, ("%s: EAGAIN freeze simq\n",
13160470d791SMatt Jacob 				    isp->isp_name));
1317478f8a96SJustin T. Gibbs 			}
13180470d791SMatt Jacob 			isp->isp_osinfo.simqfrozen |= SIMQFRZ_RESOURCE;
13190470d791SMatt Jacob 			ccb->ccb_h.status &= ~CAM_STATUS_MASK;
13200470d791SMatt Jacob                         ccb->ccb_h.status |= CAM_REQUEUE_REQ;
1321478f8a96SJustin T. Gibbs 			xpt_done(ccb);
1322478f8a96SJustin T. Gibbs 			break;
13230470d791SMatt Jacob 		case CMD_COMPLETE:
13240470d791SMatt Jacob 			isp_done((struct ccb_scsiio *) ccb);
13250470d791SMatt Jacob 			break;
13260470d791SMatt Jacob 		default:
13270470d791SMatt Jacob 			printf("%s: What's this? 0x%x at %d in file %s\n",
13280470d791SMatt Jacob 			    isp->isp_name, error, __LINE__, __FILE__);
13290470d791SMatt Jacob 			ccb->ccb_h.status &= ~CAM_STATUS_MASK;
13300470d791SMatt Jacob 			ccb->ccb_h.status |= CAM_REQ_CMP_ERR;
13310470d791SMatt Jacob 			xpt_done(ccb);
1332478f8a96SJustin T. Gibbs 		}
1333478f8a96SJustin T. Gibbs 		break;
1334478f8a96SJustin T. Gibbs 
1335d81ba9d5SMatt Jacob #ifdef	ISP_TARGET_MODE
1336478f8a96SJustin T. Gibbs 	case XPT_EN_LUN:		/* Enable LUN as a target */
1337d81ba9d5SMatt Jacob 		isp_en_lun(isp, ccb);
1338478f8a96SJustin T. Gibbs 		xpt_done(ccb);
1339478f8a96SJustin T. Gibbs 		break;
1340478f8a96SJustin T. Gibbs 
1341d81ba9d5SMatt Jacob 	case XPT_NOTIFY_ACK:		/* recycle notify ack */
1342d81ba9d5SMatt Jacob 	case XPT_IMMED_NOTIFY:		/* Add Immediate Notify Resource */
1343d81ba9d5SMatt Jacob 	case XPT_ACCEPT_TARGET_IO:	/* Add Accept Target IO Resource */
1344d81ba9d5SMatt Jacob 	{
1345d81ba9d5SMatt Jacob 		tstate_t *tptr = get_lun_statep(isp, ccb->ccb_h.target_lun);
1346d81ba9d5SMatt Jacob 		if (tptr == NULL) {
1347d81ba9d5SMatt Jacob 			ccb->ccb_h.status = CAM_LUN_INVALID;
1348d81ba9d5SMatt Jacob 			xpt_done(ccb);
1349d81ba9d5SMatt Jacob 			break;
1350d81ba9d5SMatt Jacob 		}
1351d81ba9d5SMatt Jacob 		s = splsoftcam();
1352d81ba9d5SMatt Jacob 		if (ccb->ccb_h.func_code == XPT_ACCEPT_TARGET_IO) {
1353d81ba9d5SMatt Jacob 			SLIST_INSERT_HEAD(&tptr->atios,
1354d81ba9d5SMatt Jacob 			    &ccb->ccb_h, sim_links.sle);
1355d81ba9d5SMatt Jacob 		} else {
1356d81ba9d5SMatt Jacob 			SLIST_INSERT_HEAD(&tptr->inots, &ccb->ccb_h,
1357d81ba9d5SMatt Jacob 			    sim_links.sle);
1358d81ba9d5SMatt Jacob 		}
1359d81ba9d5SMatt Jacob 		splx(s);
1360d81ba9d5SMatt Jacob 		rls_lun_statep(isp, tptr);
1361d81ba9d5SMatt Jacob 		ccb->ccb_h.status = CAM_REQ_INPROG;
1362d81ba9d5SMatt Jacob 		break;
1363d81ba9d5SMatt Jacob 	}
1364d81ba9d5SMatt Jacob 	case XPT_CONT_TARGET_IO:
1365d81ba9d5SMatt Jacob 	{
1366d81ba9d5SMatt Jacob 		s = splcam();
1367d81ba9d5SMatt Jacob 		ccb->ccb_h.status = isp_target_start_ctio(isp, ccb);
1368d81ba9d5SMatt Jacob 		if (ccb->ccb_h.status != CAM_REQ_INPROG) {
1369d81ba9d5SMatt Jacob 			if (isp->isp_osinfo.simqfrozen == 0) {
1370d81ba9d5SMatt Jacob 				xpt_freeze_simq(sim, 1);
1371d81ba9d5SMatt Jacob 				xpt_print_path(ccb->ccb_h.path);
1372d81ba9d5SMatt Jacob 				printf("XPT_CONT_TARGET_IO freeze simq\n");
1373d81ba9d5SMatt Jacob 			}
1374d81ba9d5SMatt Jacob 			isp->isp_osinfo.simqfrozen |= SIMQFRZ_RESOURCE;
1375d81ba9d5SMatt Jacob 			ccb->ccb_h.status &= ~CAM_STATUS_MASK;
1376d81ba9d5SMatt Jacob                         ccb->ccb_h.status |= CAM_REQUEUE_REQ;
1377d81ba9d5SMatt Jacob 			xpt_done(ccb);
1378d81ba9d5SMatt Jacob 		} else {
1379d81ba9d5SMatt Jacob 			ccb->ccb_h.status |= CAM_SIM_QUEUED;
1380d81ba9d5SMatt Jacob 		}
1381d81ba9d5SMatt Jacob 		splx(s);
1382d81ba9d5SMatt Jacob 		break;
1383d81ba9d5SMatt Jacob 	}
1384d81ba9d5SMatt Jacob #endif
1385478f8a96SJustin T. Gibbs 	case XPT_RESET_DEV:		/* BDR the specified SCSI device */
1386d81ba9d5SMatt Jacob 
1387d81ba9d5SMatt Jacob 		bus = cam_sim_bus(xpt_path_sim(ccb->ccb_h.path));
1388d81ba9d5SMatt Jacob 		tgt = ccb->ccb_h.target_id;
1389d81ba9d5SMatt Jacob 		tgt |= (bus << 16);
1390d81ba9d5SMatt Jacob 
1391478f8a96SJustin T. Gibbs 		s = splcam();
1392ea6f23cdSMatt Jacob 		error = isp_control(isp, ISPCTL_RESET_DEV, &tgt);
1393478f8a96SJustin T. Gibbs 		(void) splx(s);
1394478f8a96SJustin T. Gibbs 		if (error) {
1395478f8a96SJustin T. Gibbs 			ccb->ccb_h.status = CAM_REQ_CMP_ERR;
1396478f8a96SJustin T. Gibbs 		} else {
1397478f8a96SJustin T. Gibbs 			ccb->ccb_h.status = CAM_REQ_CMP;
1398478f8a96SJustin T. Gibbs 		}
1399478f8a96SJustin T. Gibbs 		xpt_done(ccb);
1400478f8a96SJustin T. Gibbs 		break;
1401478f8a96SJustin T. Gibbs 	case XPT_ABORT:			/* Abort the specified CCB */
1402d81ba9d5SMatt Jacob 	{
1403d81ba9d5SMatt Jacob 		union ccb *accb = ccb->cab.abort_ccb;
1404d81ba9d5SMatt Jacob 		switch (accb->ccb_h.func_code) {
1405d81ba9d5SMatt Jacob #ifdef	ISP_TARGET_MODE
1406d81ba9d5SMatt Jacob 		case XPT_ACCEPT_TARGET_IO:
1407d81ba9d5SMatt Jacob 		case XPT_IMMED_NOTIFY:
1408d81ba9d5SMatt Jacob         		ccb->ccb_h.status = isp_abort_tgt_ccb(isp, ccb);
1409d81ba9d5SMatt Jacob 			break;
1410d81ba9d5SMatt Jacob 		case XPT_CONT_TARGET_IO:
1411d81ba9d5SMatt Jacob 			PRINTF("%s: cannot abort CTIOs yet\n", isp->isp_name);
1412d81ba9d5SMatt Jacob 			ccb->ccb_h.status = CAM_UA_ABORT;
1413d81ba9d5SMatt Jacob 			break;
1414d81ba9d5SMatt Jacob #endif
1415d81ba9d5SMatt Jacob 		case XPT_SCSI_IO:
1416478f8a96SJustin T. Gibbs 			s = splcam();
1417478f8a96SJustin T. Gibbs 			error = isp_control(isp, ISPCTL_ABORT_CMD, ccb);
1418478f8a96SJustin T. Gibbs 			(void) splx(s);
1419478f8a96SJustin T. Gibbs 			if (error) {
1420d81ba9d5SMatt Jacob 				ccb->ccb_h.status = CAM_UA_ABORT;
1421478f8a96SJustin T. Gibbs 			} else {
1422478f8a96SJustin T. Gibbs 				ccb->ccb_h.status = CAM_REQ_CMP;
1423478f8a96SJustin T. Gibbs 			}
1424d81ba9d5SMatt Jacob 			break;
1425d81ba9d5SMatt Jacob 		default:
1426d81ba9d5SMatt Jacob 			ccb->ccb_h.status = CAM_REQ_INVALID;
1427d81ba9d5SMatt Jacob 			break;
1428d81ba9d5SMatt Jacob 		}
1429478f8a96SJustin T. Gibbs 		xpt_done(ccb);
1430478f8a96SJustin T. Gibbs 		break;
1431d81ba9d5SMatt Jacob 	}
1432478f8a96SJustin T. Gibbs 	case XPT_SET_TRAN_SETTINGS:	/* Nexus Settings */
1433478f8a96SJustin T. Gibbs 
1434478f8a96SJustin T. Gibbs 		cts = &ccb->cts;
1435478f8a96SJustin T. Gibbs 		tgt = cts->ccb_h.target_id;
1436478f8a96SJustin T. Gibbs 		s = splcam();
1437ab6c4b31SMatt Jacob 		if (IS_SCSI(isp)) {
1438478f8a96SJustin T. Gibbs 			sdparam *sdp = isp->isp_param;
1439478f8a96SJustin T. Gibbs 			u_int16_t *dptr;
1440d81ba9d5SMatt Jacob 
1441d81ba9d5SMatt Jacob 			bus = cam_sim_bus(xpt_path_sim(cts->ccb_h.path));
1442478f8a96SJustin T. Gibbs 
1443ea6f23cdSMatt Jacob 			sdp += bus;
1444478f8a96SJustin T. Gibbs #if	0
1445478f8a96SJustin T. Gibbs 			if (cts->flags & CCB_TRANS_CURRENT_SETTINGS)
1446478f8a96SJustin T. Gibbs 				dptr = &sdp->isp_devparam[tgt].cur_dflags;
1447478f8a96SJustin T. Gibbs 			else
1448478f8a96SJustin T. Gibbs 				dptr = &sdp->isp_devparam[tgt].dev_flags;
1449478f8a96SJustin T. Gibbs #else
1450478f8a96SJustin T. Gibbs 			/*
1451478f8a96SJustin T. Gibbs 			 * We always update (internally) from dev_flags
1452478f8a96SJustin T. Gibbs 			 * so any request to change settings just gets
1453478f8a96SJustin T. Gibbs 			 * vectored to that location.
1454478f8a96SJustin T. Gibbs 			 */
1455478f8a96SJustin T. Gibbs 			dptr = &sdp->isp_devparam[tgt].dev_flags;
1456478f8a96SJustin T. Gibbs #endif
1457478f8a96SJustin T. Gibbs 
1458478f8a96SJustin T. Gibbs 			/*
1459478f8a96SJustin T. Gibbs 			 * Note that these operations affect the
14604394c92fSMatt Jacob 			 * the goal flags (dev_flags)- not
1461478f8a96SJustin T. Gibbs 			 * the current state flags. Then we mark
1462478f8a96SJustin T. Gibbs 			 * things so that the next operation to
1463478f8a96SJustin T. Gibbs 			 * this HBA will cause the update to occur.
1464478f8a96SJustin T. Gibbs 			 */
1465478f8a96SJustin T. Gibbs 			if (cts->valid & CCB_TRANS_DISC_VALID) {
1466478f8a96SJustin T. Gibbs 				if ((cts->flags & CCB_TRANS_DISC_ENB) != 0) {
1467478f8a96SJustin T. Gibbs 					*dptr |= DPARM_DISC;
1468478f8a96SJustin T. Gibbs 				} else {
1469478f8a96SJustin T. Gibbs 					*dptr &= ~DPARM_DISC;
1470478f8a96SJustin T. Gibbs 				}
1471478f8a96SJustin T. Gibbs 			}
1472478f8a96SJustin T. Gibbs 			if (cts->valid & CCB_TRANS_TQ_VALID) {
1473478f8a96SJustin T. Gibbs 				if ((cts->flags & CCB_TRANS_TAG_ENB) != 0) {
1474478f8a96SJustin T. Gibbs 					*dptr |= DPARM_TQING;
1475478f8a96SJustin T. Gibbs 				} else {
1476478f8a96SJustin T. Gibbs 					*dptr &= ~DPARM_TQING;
1477478f8a96SJustin T. Gibbs 				}
1478478f8a96SJustin T. Gibbs 			}
1479478f8a96SJustin T. Gibbs 			if (cts->valid & CCB_TRANS_BUS_WIDTH_VALID) {
1480478f8a96SJustin T. Gibbs 				switch (cts->bus_width) {
1481478f8a96SJustin T. Gibbs 				case MSG_EXT_WDTR_BUS_16_BIT:
1482478f8a96SJustin T. Gibbs 					*dptr |= DPARM_WIDE;
1483478f8a96SJustin T. Gibbs 					break;
1484478f8a96SJustin T. Gibbs 				default:
1485478f8a96SJustin T. Gibbs 					*dptr &= ~DPARM_WIDE;
1486478f8a96SJustin T. Gibbs 				}
1487478f8a96SJustin T. Gibbs 			}
1488478f8a96SJustin T. Gibbs 			/*
1489478f8a96SJustin T. Gibbs 			 * Any SYNC RATE of nonzero and SYNC_OFFSET
1490478f8a96SJustin T. Gibbs 			 * of nonzero will cause us to go to the
1491478f8a96SJustin T. Gibbs 			 * selected (from NVRAM) maximum value for
1492478f8a96SJustin T. Gibbs 			 * this device. At a later point, we'll
1493478f8a96SJustin T. Gibbs 			 * allow finer control.
1494478f8a96SJustin T. Gibbs 			 */
1495478f8a96SJustin T. Gibbs 			if ((cts->valid & CCB_TRANS_SYNC_RATE_VALID) &&
1496478f8a96SJustin T. Gibbs 			    (cts->valid & CCB_TRANS_SYNC_OFFSET_VALID) &&
1497478f8a96SJustin T. Gibbs 			    (cts->sync_offset > 0)) {
1498478f8a96SJustin T. Gibbs 				*dptr |= DPARM_SYNC;
1499478f8a96SJustin T. Gibbs 			} else {
1500478f8a96SJustin T. Gibbs 				*dptr &= ~DPARM_SYNC;
1501478f8a96SJustin T. Gibbs 			}
1502ab6c4b31SMatt Jacob 			*dptr |= DPARM_SAFE_DFLT;
150383ae4407SMatt Jacob 			if (bootverbose || isp->isp_dblev >= 3)
150483ae4407SMatt Jacob 				printf("%s: %d.%d set %s period 0x%x offset "
150583ae4407SMatt Jacob 				    "0x%x flags 0x%x\n", isp->isp_name, bus,
150683ae4407SMatt Jacob 				    tgt,
15074394c92fSMatt Jacob 				    (cts->flags & CCB_TRANS_CURRENT_SETTINGS)?
15084394c92fSMatt Jacob 				    "current" : "user",
15092b052931SMatt Jacob 				    sdp->isp_devparam[tgt].sync_period,
15102b052931SMatt Jacob 				    sdp->isp_devparam[tgt].sync_offset,
151183ae4407SMatt Jacob 				    sdp->isp_devparam[tgt].dev_flags);
1512478f8a96SJustin T. Gibbs 			sdp->isp_devparam[tgt].dev_update = 1;
1513ea6f23cdSMatt Jacob 			isp->isp_update |= (1 << bus);
1514478f8a96SJustin T. Gibbs 		}
1515478f8a96SJustin T. Gibbs 		(void) splx(s);
1516478f8a96SJustin T. Gibbs 		ccb->ccb_h.status = CAM_REQ_CMP;
1517478f8a96SJustin T. Gibbs 		xpt_done(ccb);
1518478f8a96SJustin T. Gibbs 		break;
1519478f8a96SJustin T. Gibbs 
1520478f8a96SJustin T. Gibbs 	case XPT_GET_TRAN_SETTINGS:
1521478f8a96SJustin T. Gibbs 
1522478f8a96SJustin T. Gibbs 		cts = &ccb->cts;
1523478f8a96SJustin T. Gibbs 		tgt = cts->ccb_h.target_id;
1524ab6c4b31SMatt Jacob 		if (IS_FC(isp)) {
1525478f8a96SJustin T. Gibbs 			/*
1526478f8a96SJustin T. Gibbs 			 * a lot of normal SCSI things don't make sense.
1527478f8a96SJustin T. Gibbs 			 */
1528478f8a96SJustin T. Gibbs 			cts->flags = CCB_TRANS_TAG_ENB | CCB_TRANS_DISC_ENB;
1529478f8a96SJustin T. Gibbs 			cts->valid = CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID;
1530478f8a96SJustin T. Gibbs 			/*
1531478f8a96SJustin T. Gibbs 			 * How do you measure the width of a high
1532478f8a96SJustin T. Gibbs 			 * speed serial bus? Well, in bytes.
1533478f8a96SJustin T. Gibbs 			 *
1534478f8a96SJustin T. Gibbs 			 * Offset and period make no sense, though, so we set
1535478f8a96SJustin T. Gibbs 			 * (above) a 'base' transfer speed to be gigabit.
1536478f8a96SJustin T. Gibbs 			 */
1537478f8a96SJustin T. Gibbs 			cts->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
1538478f8a96SJustin T. Gibbs 		} else {
1539478f8a96SJustin T. Gibbs 			sdparam *sdp = isp->isp_param;
15404394c92fSMatt Jacob 			u_int16_t dval, pval, oval;
1541ea6f23cdSMatt Jacob 			int bus = cam_sim_bus(xpt_path_sim(cts->ccb_h.path));
1542478f8a96SJustin T. Gibbs 
1543ea6f23cdSMatt Jacob 			sdp += bus;
15444394c92fSMatt Jacob 			if (cts->flags & CCB_TRANS_CURRENT_SETTINGS) {
154583ae4407SMatt Jacob 				s = splcam();
154683ae4407SMatt Jacob 				sdp->isp_devparam[tgt].dev_refresh = 1;
154783ae4407SMatt Jacob 				isp->isp_update |= (1 << bus);
154883ae4407SMatt Jacob 				(void) isp_control(isp, ISPCTL_UPDATE_PARAMS,
154983ae4407SMatt Jacob 				    NULL);
155083ae4407SMatt Jacob 				(void) splx(s);
1551478f8a96SJustin T. Gibbs 				dval = sdp->isp_devparam[tgt].cur_dflags;
15524394c92fSMatt Jacob 				oval = sdp->isp_devparam[tgt].cur_offset;
15534394c92fSMatt Jacob 				pval = sdp->isp_devparam[tgt].cur_period;
15544394c92fSMatt Jacob 			} else {
1555478f8a96SJustin T. Gibbs 				dval = sdp->isp_devparam[tgt].dev_flags;
15564394c92fSMatt Jacob 				oval = sdp->isp_devparam[tgt].sync_offset;
15574394c92fSMatt Jacob 				pval = sdp->isp_devparam[tgt].sync_period;
15584394c92fSMatt Jacob 			}
1559478f8a96SJustin T. Gibbs 
1560478f8a96SJustin T. Gibbs 			s = splcam();
1561478f8a96SJustin T. Gibbs 			cts->flags &= ~(CCB_TRANS_DISC_ENB|CCB_TRANS_TAG_ENB);
1562478f8a96SJustin T. Gibbs 
1563478f8a96SJustin T. Gibbs 			if (dval & DPARM_DISC) {
1564478f8a96SJustin T. Gibbs 				cts->flags |= CCB_TRANS_DISC_ENB;
1565478f8a96SJustin T. Gibbs 			}
1566478f8a96SJustin T. Gibbs 			if (dval & DPARM_TQING) {
1567478f8a96SJustin T. Gibbs 				cts->flags |= CCB_TRANS_TAG_ENB;
1568478f8a96SJustin T. Gibbs 			}
1569478f8a96SJustin T. Gibbs 			if (dval & DPARM_WIDE) {
1570478f8a96SJustin T. Gibbs 				cts->bus_width = MSG_EXT_WDTR_BUS_16_BIT;
1571478f8a96SJustin T. Gibbs 			} else {
1572478f8a96SJustin T. Gibbs 				cts->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
1573478f8a96SJustin T. Gibbs 			}
1574478f8a96SJustin T. Gibbs 			cts->valid = CCB_TRANS_BUS_WIDTH_VALID |
1575478f8a96SJustin T. Gibbs 			    CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID;
1576478f8a96SJustin T. Gibbs 
15774394c92fSMatt Jacob 			if ((dval & DPARM_SYNC) && oval != 0) {
15784394c92fSMatt Jacob 				cts->sync_period = pval;
15794394c92fSMatt Jacob 				cts->sync_offset = oval;
1580478f8a96SJustin T. Gibbs 				cts->valid |=
1581478f8a96SJustin T. Gibbs 				    CCB_TRANS_SYNC_RATE_VALID |
1582478f8a96SJustin T. Gibbs 				    CCB_TRANS_SYNC_OFFSET_VALID;
1583478f8a96SJustin T. Gibbs 			}
1584478f8a96SJustin T. Gibbs 			splx(s);
158583ae4407SMatt Jacob 			if (bootverbose || isp->isp_dblev >= 3)
158683ae4407SMatt Jacob 				printf("%s: %d.%d get %s period 0x%x offset "
158783ae4407SMatt Jacob 				    "0x%x flags 0x%x\n", isp->isp_name, bus,
158883ae4407SMatt Jacob 				    tgt,
15894394c92fSMatt Jacob 			    	    (cts->flags & CCB_TRANS_CURRENT_SETTINGS)?
159083ae4407SMatt Jacob 				    "current" : "user", pval, oval, dval);
1591478f8a96SJustin T. Gibbs 		}
1592478f8a96SJustin T. Gibbs 		ccb->ccb_h.status = CAM_REQ_CMP;
1593478f8a96SJustin T. Gibbs 		xpt_done(ccb);
1594478f8a96SJustin T. Gibbs 		break;
1595478f8a96SJustin T. Gibbs 
1596478f8a96SJustin T. Gibbs 	case XPT_CALC_GEOMETRY:
1597478f8a96SJustin T. Gibbs 	{
1598478f8a96SJustin T. Gibbs 		struct ccb_calc_geometry *ccg;
1599478f8a96SJustin T. Gibbs 		u_int32_t secs_per_cylinder;
1600478f8a96SJustin T. Gibbs 		u_int32_t size_mb;
1601478f8a96SJustin T. Gibbs 
1602478f8a96SJustin T. Gibbs 		ccg = &ccb->ccg;
1603478f8a96SJustin T. Gibbs 		if (ccg->block_size == 0) {
1604478f8a96SJustin T. Gibbs 			printf("%s: %d.%d XPT_CALC_GEOMETRY block size 0?\n",
1605478f8a96SJustin T. Gibbs 				isp->isp_name, ccg->ccb_h.target_id,
1606478f8a96SJustin T. Gibbs 				ccg->ccb_h.target_lun);
1607478f8a96SJustin T. Gibbs 			ccb->ccb_h.status = CAM_REQ_INVALID;
1608478f8a96SJustin T. Gibbs 			xpt_done(ccb);
1609478f8a96SJustin T. Gibbs 			break;
1610478f8a96SJustin T. Gibbs 		}
1611478f8a96SJustin T. Gibbs 		size_mb = ccg->volume_size /((1024L * 1024L) / ccg->block_size);
1612478f8a96SJustin T. Gibbs 		if (size_mb > 1024) {
1613478f8a96SJustin T. Gibbs 			ccg->heads = 255;
1614478f8a96SJustin T. Gibbs 			ccg->secs_per_track = 63;
1615478f8a96SJustin T. Gibbs 		} else {
1616478f8a96SJustin T. Gibbs 			ccg->heads = 64;
1617478f8a96SJustin T. Gibbs 			ccg->secs_per_track = 32;
1618478f8a96SJustin T. Gibbs 		}
1619478f8a96SJustin T. Gibbs 		secs_per_cylinder = ccg->heads * ccg->secs_per_track;
1620478f8a96SJustin T. Gibbs 		ccg->cylinders = ccg->volume_size / secs_per_cylinder;
1621478f8a96SJustin T. Gibbs 		ccb->ccb_h.status = CAM_REQ_CMP;
1622478f8a96SJustin T. Gibbs 		xpt_done(ccb);
1623478f8a96SJustin T. Gibbs 		break;
1624478f8a96SJustin T. Gibbs 	}
1625478f8a96SJustin T. Gibbs 	case XPT_RESET_BUS:		/* Reset the specified bus */
1626ab6c4b31SMatt Jacob 		bus = cam_sim_bus(sim);
1627478f8a96SJustin T. Gibbs 		s = splcam();
1628ab6c4b31SMatt Jacob 		error = isp_control(isp, ISPCTL_RESET_BUS, &bus);
1629478f8a96SJustin T. Gibbs 		(void) splx(s);
1630478f8a96SJustin T. Gibbs 		if (error)
1631478f8a96SJustin T. Gibbs 			ccb->ccb_h.status = CAM_REQ_CMP_ERR;
16322b052931SMatt Jacob 		else {
1633ea6f23cdSMatt Jacob 			if (cam_sim_bus(sim) && isp->isp_path2 != NULL)
1634ea6f23cdSMatt Jacob 				xpt_async(AC_BUS_RESET, isp->isp_path2, NULL);
1635ea6f23cdSMatt Jacob 			else if (isp->isp_path != NULL)
16362b052931SMatt Jacob 				xpt_async(AC_BUS_RESET, isp->isp_path, NULL);
1637478f8a96SJustin T. Gibbs 			ccb->ccb_h.status = CAM_REQ_CMP;
16382b052931SMatt Jacob 		}
1639478f8a96SJustin T. Gibbs 		xpt_done(ccb);
1640478f8a96SJustin T. Gibbs 		break;
1641478f8a96SJustin T. Gibbs 
1642478f8a96SJustin T. Gibbs 	case XPT_TERM_IO:		/* Terminate the I/O process */
1643478f8a96SJustin T. Gibbs 		/* Does this need to be implemented? */
1644478f8a96SJustin T. Gibbs 		ccb->ccb_h.status = CAM_REQ_INVALID;
1645478f8a96SJustin T. Gibbs 		xpt_done(ccb);
1646478f8a96SJustin T. Gibbs 		break;
1647478f8a96SJustin T. Gibbs 
1648478f8a96SJustin T. Gibbs 	case XPT_PATH_INQ:		/* Path routing inquiry */
1649478f8a96SJustin T. Gibbs 	{
1650478f8a96SJustin T. Gibbs 		struct ccb_pathinq *cpi = &ccb->cpi;
1651478f8a96SJustin T. Gibbs 
1652478f8a96SJustin T. Gibbs 		cpi->version_num = 1;
1653d81ba9d5SMatt Jacob #ifdef	ISP_TARGET_MODE
1654d81ba9d5SMatt Jacob 		cpi->target_sprt = PIT_PROCESSOR | PIT_DISCONNECT | PIT_TERM_IO;
1655d81ba9d5SMatt Jacob #else
1656478f8a96SJustin T. Gibbs 		cpi->target_sprt = 0;
1657d81ba9d5SMatt Jacob #endif
1658478f8a96SJustin T. Gibbs 		cpi->hba_eng_cnt = 0;
16590470d791SMatt Jacob 		cpi->max_target = ISP_MAX_TARGETS(isp) - 1;
16600470d791SMatt Jacob 		cpi->max_lun = ISP_MAX_LUNS(isp) - 1;
16610470d791SMatt Jacob 		cpi->bus_id = cam_sim_bus(sim);
16624394c92fSMatt Jacob 		if (IS_FC(isp)) {
16634394c92fSMatt Jacob 			cpi->hba_misc = PIM_NOBUSRESET;
16640470d791SMatt Jacob 			/*
16650470d791SMatt Jacob 			 * Because our loop ID can shift from time to time,
16660470d791SMatt Jacob 			 * make our initiator ID out of range of our bus.
16670470d791SMatt Jacob 			 */
16680470d791SMatt Jacob 			cpi->initiator_id = cpi->max_target + 1;
16690470d791SMatt Jacob 
16709deea857SKenneth D. Merry 			/*
16719deea857SKenneth D. Merry 			 * Set base transfer capabilities for Fibre Channel.
16729deea857SKenneth D. Merry 			 * Technically not correct because we don't know
16739deea857SKenneth D. Merry 			 * what media we're running on top of- but we'll
16749deea857SKenneth D. Merry 			 * look good if we always say 100MB/s.
16759deea857SKenneth D. Merry 			 */
16769deea857SKenneth D. Merry 			cpi->base_transfer_speed = 100000;
16770470d791SMatt Jacob 			cpi->hba_inquiry = PI_TAG_ABLE;
1678478f8a96SJustin T. Gibbs 		} else {
1679ea6f23cdSMatt Jacob 			sdparam *sdp = isp->isp_param;
1680ea6f23cdSMatt Jacob 			sdp += cam_sim_bus(xpt_path_sim(cpi->ccb_h.path));
16810470d791SMatt Jacob 			cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE|PI_WIDE_16;
16824394c92fSMatt Jacob 			cpi->hba_misc = 0;
1683ea6f23cdSMatt Jacob 			cpi->initiator_id = sdp->isp_initiator_id;
16849deea857SKenneth D. Merry 			cpi->base_transfer_speed = 3300;
1685478f8a96SJustin T. Gibbs 		}
1686478f8a96SJustin T. Gibbs 		strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
1687478f8a96SJustin T. Gibbs 		strncpy(cpi->hba_vid, "Qlogic", HBA_IDLEN);
1688478f8a96SJustin T. Gibbs 		strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
1689478f8a96SJustin T. Gibbs 		cpi->unit_number = cam_sim_unit(sim);
1690478f8a96SJustin T. Gibbs 		cpi->ccb_h.status = CAM_REQ_CMP;
1691478f8a96SJustin T. Gibbs 		xpt_done(ccb);
1692478f8a96SJustin T. Gibbs 		break;
1693478f8a96SJustin T. Gibbs 	}
1694478f8a96SJustin T. Gibbs 	default:
1695478f8a96SJustin T. Gibbs 		ccb->ccb_h.status = CAM_REQ_INVALID;
1696478f8a96SJustin T. Gibbs 		xpt_done(ccb);
1697478f8a96SJustin T. Gibbs 		break;
1698478f8a96SJustin T. Gibbs 	}
1699478f8a96SJustin T. Gibbs }
1700d3a9eb2eSMatt Jacob 
1701d3a9eb2eSMatt Jacob #define	ISPDDB	(CAM_DEBUG_INFO|CAM_DEBUG_TRACE|CAM_DEBUG_CDB)
1702d3a9eb2eSMatt Jacob void
1703c3055363SMatt Jacob isp_done(struct ccb_scsiio *sccb)
1704d3a9eb2eSMatt Jacob {
1705d3a9eb2eSMatt Jacob 	struct ispsoftc *isp = XS_ISP(sccb);
1706d3a9eb2eSMatt Jacob 
1707d3a9eb2eSMatt Jacob 	if (XS_NOERR(sccb))
1708d3a9eb2eSMatt Jacob 		XS_SETERR(sccb, CAM_REQ_CMP);
1709d3a9eb2eSMatt Jacob 	sccb->ccb_h.status &= ~CAM_STATUS_MASK;
1710d3a9eb2eSMatt Jacob 	sccb->ccb_h.status |= sccb->ccb_h.spriv_field0;
1711d3a9eb2eSMatt Jacob 	if ((sccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP &&
1712d3a9eb2eSMatt Jacob 	    (sccb->scsi_status != SCSI_STATUS_OK)) {
1713d3a9eb2eSMatt Jacob 		sccb->ccb_h.status &= ~CAM_STATUS_MASK;
171492a1e549SMatt Jacob 		if ((sccb->scsi_status == SCSI_STATUS_CHECK_COND) &&
171592a1e549SMatt Jacob 		    (sccb->ccb_h.status & CAM_AUTOSNS_VALID) == 0) {
171692a1e549SMatt Jacob 			sccb->ccb_h.status |= CAM_AUTOSENSE_FAIL;
171792a1e549SMatt Jacob 		} else {
1718d3a9eb2eSMatt Jacob 			sccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR;
1719d3a9eb2eSMatt Jacob 		}
172092a1e549SMatt Jacob 	}
17210470d791SMatt Jacob 	sccb->ccb_h.status &= ~CAM_SIM_QUEUED;
1722d3a9eb2eSMatt Jacob 	if ((sccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1723d3a9eb2eSMatt Jacob 		if ((sccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
1724d3a9eb2eSMatt Jacob 			sccb->ccb_h.status |= CAM_DEV_QFRZN;
17250470d791SMatt Jacob 			xpt_freeze_devq(sccb->ccb_h.path, 1);
17260470d791SMatt Jacob 			if (sccb->scsi_status != SCSI_STATUS_OK)
17270470d791SMatt Jacob 				IDPRINTF(3, ("%s: fdevq %d.%d %x %x\n",
17280470d791SMatt Jacob 				    isp->isp_name, sccb->ccb_h.target_id,
17290470d791SMatt Jacob 				    sccb->ccb_h.target_lun, sccb->ccb_h.status,
17300470d791SMatt Jacob 				    sccb->scsi_status));
1731d3a9eb2eSMatt Jacob 		}
1732d3a9eb2eSMatt Jacob 	}
17330470d791SMatt Jacob 	/*
17340470d791SMatt Jacob 	 * If we were frozen waiting resources, clear that we were frozen
17350470d791SMatt Jacob 	 * waiting for resources. If we are no longer frozen, and the devq
17360470d791SMatt Jacob 	 * isn't frozen, mark the completing CCB to have the XPT layer
17370470d791SMatt Jacob 	 * release the simq.
17380470d791SMatt Jacob 	 */
173957c801f5SMatt Jacob 	if (isp->isp_osinfo.simqfrozen & SIMQFRZ_RESOURCE) {
174057c801f5SMatt Jacob 		isp->isp_osinfo.simqfrozen &= ~SIMQFRZ_RESOURCE;
17410470d791SMatt Jacob 		if (isp->isp_osinfo.simqfrozen == 0) {
17420470d791SMatt Jacob 			if ((sccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
17430470d791SMatt Jacob 				IDPRINTF(3, ("%s: isp_done -> relsimq\n",
17440470d791SMatt Jacob 				    isp->isp_name));
1745d3a9eb2eSMatt Jacob 				sccb->ccb_h.status |= CAM_RELEASE_SIMQ;
17460470d791SMatt Jacob 			} else {
17470470d791SMatt Jacob 				IDPRINTF(3, ("%s: isp_done -> devq frozen\n",
17480470d791SMatt Jacob 				    isp->isp_name));
1749d3a9eb2eSMatt Jacob 			}
17500470d791SMatt Jacob 		} else {
17510470d791SMatt Jacob 			IDPRINTF(3, ("%s: isp_done -> simqfrozen = %x\n",
17520470d791SMatt Jacob 			    isp->isp_name, isp->isp_osinfo.simqfrozen));
17530470d791SMatt Jacob 		}
17540470d791SMatt Jacob 	}
1755d3a9eb2eSMatt Jacob 	if (CAM_DEBUGGED(sccb->ccb_h.path, ISPDDB) &&
1756d3a9eb2eSMatt Jacob 	    (sccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1757d3a9eb2eSMatt Jacob 		xpt_print_path(sccb->ccb_h.path);
1758d3a9eb2eSMatt Jacob 		printf("cam completion status 0x%x\n", sccb->ccb_h.status);
1759d3a9eb2eSMatt Jacob 	}
1760cc8df88bSMatt Jacob 	untimeout(isp_timeout, (caddr_t)sccb, sccb->ccb_h.timeout_ch);
1761d3a9eb2eSMatt Jacob 	xpt_done((union ccb *) sccb);
1762d3a9eb2eSMatt Jacob }
1763d3a9eb2eSMatt Jacob 
1764cbf57b47SMatt Jacob int
17650470d791SMatt Jacob isp_async(struct ispsoftc *isp, ispasync_t cmd, void *arg)
1766cbf57b47SMatt Jacob {
1767ea6f23cdSMatt Jacob 	int bus, rv = 0;
1768cbf57b47SMatt Jacob 	switch (cmd) {
1769cbf57b47SMatt Jacob 	case ISPASYNC_NEW_TGT_PARAMS:
17700470d791SMatt Jacob 	{
1771cbf57b47SMatt Jacob 		int flags, tgt;
1772cbf57b47SMatt Jacob 		sdparam *sdp = isp->isp_param;
1773cbf57b47SMatt Jacob 		struct ccb_trans_settings neg;
1774cbf57b47SMatt Jacob 		struct cam_path *tmppath;
1775cbf57b47SMatt Jacob 
1776cbf57b47SMatt Jacob 		tgt = *((int *)arg);
1777ea6f23cdSMatt Jacob 		bus = (tgt >> 16) & 0xffff;
1778ea6f23cdSMatt Jacob 		tgt &= 0xffff;
1779ea6f23cdSMatt Jacob 		sdp += bus;
1780cbf57b47SMatt Jacob 		if (xpt_create_path(&tmppath, NULL,
1781ea6f23cdSMatt Jacob 		    cam_sim_path(bus? isp->isp_sim2 : isp->isp_sim),
1782ea6f23cdSMatt Jacob 		    tgt, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
1783cbf57b47SMatt Jacob 			xpt_print_path(isp->isp_path);
1784cbf57b47SMatt Jacob 			printf("isp_async cannot make temp path for "
1785ea6f23cdSMatt Jacob 			    "target %d bus %d\n", tgt, bus);
1786cbf57b47SMatt Jacob 			rv = -1;
1787cbf57b47SMatt Jacob 			break;
1788cbf57b47SMatt Jacob 		}
17894394c92fSMatt Jacob 		flags = sdp->isp_devparam[tgt].cur_dflags;
1790cbf57b47SMatt Jacob 		neg.valid = CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID;
1791cbf57b47SMatt Jacob 		if (flags & DPARM_DISC) {
1792cbf57b47SMatt Jacob 			neg.flags |= CCB_TRANS_DISC_ENB;
1793cbf57b47SMatt Jacob 		}
1794cbf57b47SMatt Jacob 		if (flags & DPARM_TQING) {
1795cbf57b47SMatt Jacob 			neg.flags |= CCB_TRANS_TAG_ENB;
1796cbf57b47SMatt Jacob 		}
1797cbf57b47SMatt Jacob 		neg.valid |= CCB_TRANS_BUS_WIDTH_VALID;
1798cbf57b47SMatt Jacob 		neg.bus_width = (flags & DPARM_WIDE)?
1799cbf57b47SMatt Jacob 		    MSG_EXT_WDTR_BUS_8_BIT : MSG_EXT_WDTR_BUS_16_BIT;
18004394c92fSMatt Jacob 		neg.sync_period = sdp->isp_devparam[tgt].cur_period;
18014394c92fSMatt Jacob 		neg.sync_offset = sdp->isp_devparam[tgt].cur_offset;
1802cbf57b47SMatt Jacob 		if (flags & DPARM_SYNC) {
18034394c92fSMatt Jacob 			neg.valid |=
18044394c92fSMatt Jacob 			    CCB_TRANS_SYNC_RATE_VALID |
1805cbf57b47SMatt Jacob 			    CCB_TRANS_SYNC_OFFSET_VALID;
1806cbf57b47SMatt Jacob 		}
1807ea6f23cdSMatt Jacob 		IDPRINTF(3, ("%s: NEW_TGT_PARAMS bus %d tgt %d period "
1808ea6f23cdSMatt Jacob 		    "0x%x offset 0x%x flags 0x%x\n", isp->isp_name,
1809ea6f23cdSMatt Jacob 		    bus, tgt, neg.sync_period, neg.sync_offset, flags));
1810cbf57b47SMatt Jacob 		xpt_setup_ccb(&neg.ccb_h, tmppath, 1);
1811cbf57b47SMatt Jacob 		xpt_async(AC_TRANSFER_NEG, tmppath, &neg);
1812cbf57b47SMatt Jacob 		xpt_free_path(tmppath);
1813cbf57b47SMatt Jacob 		break;
18140470d791SMatt Jacob 	}
181557c801f5SMatt Jacob 	case ISPASYNC_BUS_RESET:
1816ea6f23cdSMatt Jacob 		bus = *((int *)arg);
1817ea6f23cdSMatt Jacob 		printf("%s: SCSI bus reset on bus %d detected\n",
1818ea6f23cdSMatt Jacob 		    isp->isp_name, bus);
1819ea6f23cdSMatt Jacob 		if (bus > 0 && isp->isp_path2) {
1820ea6f23cdSMatt Jacob 			xpt_async(AC_BUS_RESET, isp->isp_path2, NULL);
1821ea6f23cdSMatt Jacob 		} else if (isp->isp_path) {
182257c801f5SMatt Jacob 			xpt_async(AC_BUS_RESET, isp->isp_path, NULL);
182357c801f5SMatt Jacob 		}
182457c801f5SMatt Jacob 		break;
182557c801f5SMatt Jacob 	case ISPASYNC_LOOP_DOWN:
182657c801f5SMatt Jacob 		if (isp->isp_path) {
18270470d791SMatt Jacob 			if (isp->isp_osinfo.simqfrozen == 0) {
18280470d791SMatt Jacob 				IDPRINTF(3, ("%s: loop down freeze simq\n",
18290470d791SMatt Jacob 				    isp->isp_name));
183057c801f5SMatt Jacob 				xpt_freeze_simq(isp->isp_sim, 1);
18310470d791SMatt Jacob 			}
183257c801f5SMatt Jacob 			isp->isp_osinfo.simqfrozen |= SIMQFRZ_LOOPDOWN;
183357c801f5SMatt Jacob 		}
183457c801f5SMatt Jacob 		printf("%s: Loop DOWN\n", isp->isp_name);
183557c801f5SMatt Jacob 		break;
183657c801f5SMatt Jacob 	case ISPASYNC_LOOP_UP:
183757c801f5SMatt Jacob 		if (isp->isp_path) {
18380470d791SMatt Jacob 			int wasfrozen =
18390470d791SMatt Jacob 			    isp->isp_osinfo.simqfrozen & SIMQFRZ_LOOPDOWN;
184057c801f5SMatt Jacob 			isp->isp_osinfo.simqfrozen &= ~SIMQFRZ_LOOPDOWN;
18410470d791SMatt Jacob 			if (wasfrozen && isp->isp_osinfo.simqfrozen == 0) {
18420470d791SMatt Jacob 				xpt_release_simq(isp->isp_sim, 1);
18430470d791SMatt Jacob 				IDPRINTF(3, ("%s: loop up release simq\n",
18440470d791SMatt Jacob 					isp->isp_name));
184557c801f5SMatt Jacob 			}
184657c801f5SMatt Jacob 		}
184757c801f5SMatt Jacob 		printf("%s: Loop UP\n", isp->isp_name);
184857c801f5SMatt Jacob 		break;
184902ab3379SMatt Jacob 	case ISPASYNC_PDB_CHANGED:
18500470d791SMatt Jacob 	{
185102ab3379SMatt Jacob 		const char *fmt = "%s: Target %d (Loop 0x%x) Port ID 0x%x "
185202ab3379SMatt Jacob 		    "role %s %s\n Port WWN 0x%08x%08x\n Node WWN 0x%08x%08x\n";
185302ab3379SMatt Jacob 		const static char *roles[4] = {
18540470d791SMatt Jacob 		    "(none)", "Target", "Initiator", "Target/Initiator"
185557c801f5SMatt Jacob 		};
185602ab3379SMatt Jacob 		char *ptr;
185702ab3379SMatt Jacob 		fcparam *fcp = isp->isp_param;
185802ab3379SMatt Jacob 		int tgt = *((int *) arg);
185902ab3379SMatt Jacob 		struct lportdb *lp = &fcp->portdb[tgt];
186002ab3379SMatt Jacob 
186102ab3379SMatt Jacob 		if (lp->valid) {
186202ab3379SMatt Jacob 			ptr = "arrived";
186302ab3379SMatt Jacob 		} else {
186402ab3379SMatt Jacob 			ptr = "disappeared";
186502ab3379SMatt Jacob 		}
186602ab3379SMatt Jacob 		printf(fmt, isp->isp_name, tgt, lp->loopid, lp->portid,
186702ab3379SMatt Jacob 		    roles[lp->roles & 0x3], ptr,
186802ab3379SMatt Jacob 		    (u_int32_t) (lp->port_wwn >> 32),
186902ab3379SMatt Jacob 		    (u_int32_t) (lp->port_wwn & 0xffffffffLL),
187002ab3379SMatt Jacob 		    (u_int32_t) (lp->node_wwn >> 32),
187102ab3379SMatt Jacob 		    (u_int32_t) (lp->node_wwn & 0xffffffffLL));
18724394c92fSMatt Jacob 		break;
18734394c92fSMatt Jacob 	}
187457c801f5SMatt Jacob 	case ISPASYNC_CHANGE_NOTIFY:
187557c801f5SMatt Jacob 		printf("%s: Name Server Database Changed\n", isp->isp_name);
187657c801f5SMatt Jacob 		break;
18770470d791SMatt Jacob #ifdef	ISP2100_FABRIC
187802ab3379SMatt Jacob 	case ISPASYNC_FABRIC_DEV:
187902ab3379SMatt Jacob 	{
188002ab3379SMatt Jacob 		int target;
188102ab3379SMatt Jacob 		struct lportdb *lp;
188240cfc8feSMatt Jacob 		char *pt;
188340cfc8feSMatt Jacob 		sns_ganrsp_t *resp = (sns_ganrsp_t *) arg;
188402ab3379SMatt Jacob 		u_int32_t portid;
188540cfc8feSMatt Jacob 		u_int64_t wwpn, wwnn;
188602ab3379SMatt Jacob 		fcparam *fcp = isp->isp_param;
188702ab3379SMatt Jacob 
188802ab3379SMatt Jacob 		rv = -1;
188902ab3379SMatt Jacob 
189002ab3379SMatt Jacob 		portid =
189102ab3379SMatt Jacob 		    (((u_int32_t) resp->snscb_port_id[0]) << 16) |
189202ab3379SMatt Jacob 		    (((u_int32_t) resp->snscb_port_id[1]) << 8) |
189302ab3379SMatt Jacob 		    (((u_int32_t) resp->snscb_port_id[2]));
189440cfc8feSMatt Jacob 
189540cfc8feSMatt Jacob 		wwpn =
189602ab3379SMatt Jacob 		    (((u_int64_t)resp->snscb_portname[0]) << 56) |
189702ab3379SMatt Jacob 		    (((u_int64_t)resp->snscb_portname[1]) << 48) |
189802ab3379SMatt Jacob 		    (((u_int64_t)resp->snscb_portname[2]) << 40) |
189902ab3379SMatt Jacob 		    (((u_int64_t)resp->snscb_portname[3]) << 32) |
190002ab3379SMatt Jacob 		    (((u_int64_t)resp->snscb_portname[4]) << 24) |
190102ab3379SMatt Jacob 		    (((u_int64_t)resp->snscb_portname[5]) << 16) |
190202ab3379SMatt Jacob 		    (((u_int64_t)resp->snscb_portname[6]) <<  8) |
190302ab3379SMatt Jacob 		    (((u_int64_t)resp->snscb_portname[7]));
190440cfc8feSMatt Jacob 
190540cfc8feSMatt Jacob 		wwnn =
190640cfc8feSMatt Jacob 		    (((u_int64_t)resp->snscb_nodename[0]) << 56) |
190740cfc8feSMatt Jacob 		    (((u_int64_t)resp->snscb_nodename[1]) << 48) |
190840cfc8feSMatt Jacob 		    (((u_int64_t)resp->snscb_nodename[2]) << 40) |
190940cfc8feSMatt Jacob 		    (((u_int64_t)resp->snscb_nodename[3]) << 32) |
191040cfc8feSMatt Jacob 		    (((u_int64_t)resp->snscb_nodename[4]) << 24) |
191140cfc8feSMatt Jacob 		    (((u_int64_t)resp->snscb_nodename[5]) << 16) |
191240cfc8feSMatt Jacob 		    (((u_int64_t)resp->snscb_nodename[6]) <<  8) |
191340cfc8feSMatt Jacob 		    (((u_int64_t)resp->snscb_nodename[7]));
191440cfc8feSMatt Jacob 		if (portid == 0 || wwpn == 0) {
191502ab3379SMatt Jacob 			rv = 0;
191602ab3379SMatt Jacob 			break;
191702ab3379SMatt Jacob 		}
191840cfc8feSMatt Jacob 
191940cfc8feSMatt Jacob 		switch (resp->snscb_port_type) {
192040cfc8feSMatt Jacob 		case 1:
192140cfc8feSMatt Jacob 			pt = "   N_Port";
192240cfc8feSMatt Jacob 			break;
192340cfc8feSMatt Jacob 		case 2:
192440cfc8feSMatt Jacob 			pt = "  NL_Port";
192540cfc8feSMatt Jacob 			break;
192640cfc8feSMatt Jacob 		case 3:
192740cfc8feSMatt Jacob 			pt = "F/NL_Port";
192840cfc8feSMatt Jacob 			break;
192940cfc8feSMatt Jacob 		case 0x7f:
193040cfc8feSMatt Jacob 			pt = "  Nx_Port";
193140cfc8feSMatt Jacob 			break;
193240cfc8feSMatt Jacob 		case 0x81:
193340cfc8feSMatt Jacob 			pt = "  F_port";
193440cfc8feSMatt Jacob 			break;
193540cfc8feSMatt Jacob 		case 0x82:
193640cfc8feSMatt Jacob 			pt = "  FL_Port";
193740cfc8feSMatt Jacob 			break;
193840cfc8feSMatt Jacob 		case 0x84:
193940cfc8feSMatt Jacob 			pt = "   E_port";
194040cfc8feSMatt Jacob 			break;
194140cfc8feSMatt Jacob 		default:
194240cfc8feSMatt Jacob 			pt = "?";
194340cfc8feSMatt Jacob 			break;
194440cfc8feSMatt Jacob 		}
194540cfc8feSMatt Jacob 		CFGPRINTF("%s: %s @ 0x%x, Node 0x%08x%08x Port %08x%08x\n",
194640cfc8feSMatt Jacob 		    isp->isp_name, pt, portid,
194740cfc8feSMatt Jacob 		    ((u_int32_t) (wwnn >> 32)), ((u_int32_t) wwnn),
194840cfc8feSMatt Jacob 		    ((u_int32_t) (wwpn >> 32)), ((u_int32_t) wwpn));
194940cfc8feSMatt Jacob #if	0
195040cfc8feSMatt Jacob 		if ((resp->snscb_fc4_types[1] & 0x1) == 0) {
195140cfc8feSMatt Jacob 			rv = 0;
195240cfc8feSMatt Jacob 			printf("Types 0..3: 0x%x 0x%x 0x%x 0x%x\n",
195340cfc8feSMatt Jacob 			    resp->snscb_fc4_types[0], resp->snscb_fc4_types[1],
195440cfc8feSMatt Jacob 			    resp->snscb_fc4_types[3], resp->snscb_fc4_types[3]);
195540cfc8feSMatt Jacob 			break;
195640cfc8feSMatt Jacob 		}
195740cfc8feSMatt Jacob #endif
195802ab3379SMatt Jacob 		for (target = FC_SNS_ID+1; target < MAX_FC_TARG; target++) {
195902ab3379SMatt Jacob 			lp = &fcp->portdb[target];
196040cfc8feSMatt Jacob 			if (lp->port_wwn == wwpn && lp->node_wwn == wwnn)
196102ab3379SMatt Jacob 				break;
196202ab3379SMatt Jacob 		}
196302ab3379SMatt Jacob 		if (target < MAX_FC_TARG) {
196402ab3379SMatt Jacob 			rv = 0;
196502ab3379SMatt Jacob 			break;
196602ab3379SMatt Jacob 		}
196702ab3379SMatt Jacob 		for (target = FC_SNS_ID+1; target < MAX_FC_TARG; target++) {
196802ab3379SMatt Jacob 			lp = &fcp->portdb[target];
196902ab3379SMatt Jacob 			if (lp->port_wwn == 0)
197002ab3379SMatt Jacob 				break;
197102ab3379SMatt Jacob 		}
197202ab3379SMatt Jacob 		if (target == MAX_FC_TARG) {
197302ab3379SMatt Jacob 			printf("%s: no more space for fabric devices\n",
197402ab3379SMatt Jacob 			    isp->isp_name);
197502ab3379SMatt Jacob 			break;
197602ab3379SMatt Jacob 		}
197740cfc8feSMatt Jacob 		lp->node_wwn = wwnn;
197840cfc8feSMatt Jacob 		lp->port_wwn = wwpn;
197902ab3379SMatt Jacob 		lp->portid = portid;
198002ab3379SMatt Jacob 		rv = 0;
198102ab3379SMatt Jacob 		break;
198202ab3379SMatt Jacob 	}
198302ab3379SMatt Jacob #endif
1984d81ba9d5SMatt Jacob #ifdef	ISP_TARGET_MODE
1985d81ba9d5SMatt Jacob 	case ISPASYNC_TARGET_MESSAGE:
1986d81ba9d5SMatt Jacob 	{
1987d81ba9d5SMatt Jacob 		tmd_msg_t *mp = arg;
1988d667c06cSMatt Jacob 		ITDEBUG(2, ("%s: bus %d iid %d tgt %d lun %d ttype %x tval %x"
198900a8e174SMatt Jacob 		    " msg[0]=0x%x\n", isp->isp_name, mp->nt_bus,
199000a8e174SMatt Jacob 		    (int) mp->nt_iid, (int) mp->nt_tgt, (int) mp->nt_lun,
199100a8e174SMatt Jacob 		    mp->nt_tagtype, mp->nt_tagval, mp->nt_msg[0]));
1992d81ba9d5SMatt Jacob 		break;
1993d81ba9d5SMatt Jacob 	}
1994d81ba9d5SMatt Jacob 	case ISPASYNC_TARGET_EVENT:
1995d81ba9d5SMatt Jacob 	{
1996d81ba9d5SMatt Jacob 		tmd_event_t *ep = arg;
1997d667c06cSMatt Jacob 		ITDEBUG(2, ("%s: bus %d event code 0x%x\n", isp->isp_name,
1998d81ba9d5SMatt Jacob 		    ep->ev_bus, ep->ev_event));
1999d81ba9d5SMatt Jacob 		break;
2000d81ba9d5SMatt Jacob 	}
2001d81ba9d5SMatt Jacob 	case ISPASYNC_TARGET_ACTION:
2002d81ba9d5SMatt Jacob 		switch (((isphdr_t *)arg)->rqs_entry_type) {
2003cbf57b47SMatt Jacob 		default:
2004d81ba9d5SMatt Jacob 			printf("%s: event 0x%x for unhandled target action\n",
2005d81ba9d5SMatt Jacob 			    isp->isp_name, ((isphdr_t *)arg)->rqs_entry_type);
2006d81ba9d5SMatt Jacob 			break;
2007d81ba9d5SMatt Jacob 		case RQSTYPE_ATIO:
2008d81ba9d5SMatt Jacob 			rv = isp_handle_platform_atio(isp, (at_entry_t *) arg);
2009d81ba9d5SMatt Jacob 			break;
2010d81ba9d5SMatt Jacob 		case RQSTYPE_ATIO2:
2011d81ba9d5SMatt Jacob 			rv = isp_handle_platform_atio2(isp, (at2_entry_t *)arg);
2012d81ba9d5SMatt Jacob 			break;
2013d81ba9d5SMatt Jacob 		case RQSTYPE_CTIO2:
2014d81ba9d5SMatt Jacob 		case RQSTYPE_CTIO:
2015d81ba9d5SMatt Jacob 			rv = isp_handle_platform_ctio(isp, arg);
2016d81ba9d5SMatt Jacob 			break;
2017d81ba9d5SMatt Jacob 		case RQSTYPE_ENABLE_LUN:
2018d81ba9d5SMatt Jacob 		case RQSTYPE_MODIFY_LUN:
2019d81ba9d5SMatt Jacob 			isp_cv_signal_rqe(isp, ((lun_entry_t *)arg)->le_status);
2020d81ba9d5SMatt Jacob 			break;
2021d81ba9d5SMatt Jacob 		}
2022d81ba9d5SMatt Jacob 		break;
2023d81ba9d5SMatt Jacob #endif
2024d81ba9d5SMatt Jacob 	default:
2025d81ba9d5SMatt Jacob 		PRINTF("%s: unknown isp_async event %d\n", isp->isp_name, cmd);
202602ab3379SMatt Jacob 		rv = -1;
2027cbf57b47SMatt Jacob 		break;
2028cbf57b47SMatt Jacob 	}
2029cbf57b47SMatt Jacob 	return (rv);
2030cbf57b47SMatt Jacob }
2031cbf57b47SMatt Jacob 
203292718a7fSMatt Jacob 
203392718a7fSMatt Jacob /*
203492718a7fSMatt Jacob  * Locks are held before coming here.
203592718a7fSMatt Jacob  */
203692718a7fSMatt Jacob void
203792718a7fSMatt Jacob isp_uninit(struct ispsoftc *isp)
203892718a7fSMatt Jacob {
2039ea6f23cdSMatt Jacob 	ISP_WRITE(isp, HCCR, HCCR_CMD_RESET);
204092718a7fSMatt Jacob 	DISABLE_INTS(isp);
204192718a7fSMatt Jacob }
2042