1195534Sscottl/*-
2195534Sscottl * Implementation of the SCSI Transport
3195534Sscottl *
4195534Sscottl * Copyright (c) 1997, 1998, 1999 Justin T. Gibbs.
5195534Sscottl * Copyright (c) 1997, 1998, 1999 Kenneth D. Merry.
6195534Sscottl * All rights reserved.
7195534Sscottl *
8195534Sscottl * Redistribution and use in source and binary forms, with or without
9195534Sscottl * modification, are permitted provided that the following conditions
10195534Sscottl * are met:
11195534Sscottl * 1. Redistributions of source code must retain the above copyright
12195534Sscottl *    notice, this list of conditions, and the following disclaimer,
13195534Sscottl *    without modification, immediately at the beginning of the file.
14195534Sscottl * 2. The name of the author may not be used to endorse or promote products
15195534Sscottl *    derived from this software without specific prior written permission.
16195534Sscottl *
17195534Sscottl * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18195534Sscottl * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19195534Sscottl * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20195534Sscottl * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
21195534Sscottl * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22195534Sscottl * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23195534Sscottl * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24195534Sscottl * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25195534Sscottl * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26195534Sscottl * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27195534Sscottl * SUCH DAMAGE.
28195534Sscottl */
29195534Sscottl
30195534Sscottl#include <sys/cdefs.h>
31195534Sscottl__FBSDID("$FreeBSD: stable/11/sys/cam/scsi/scsi_xpt.c 351754 2019-09-03 16:24:44Z mav $");
32195534Sscottl
33195534Sscottl#include <sys/param.h>
34195534Sscottl#include <sys/bus.h>
35195534Sscottl#include <sys/systm.h>
36195534Sscottl#include <sys/types.h>
37195534Sscottl#include <sys/malloc.h>
38195534Sscottl#include <sys/kernel.h>
39195534Sscottl#include <sys/time.h>
40195534Sscottl#include <sys/conf.h>
41195534Sscottl#include <sys/fcntl.h>
42195534Sscottl#include <sys/md5.h>
43195534Sscottl#include <sys/sbuf.h>
44195534Sscottl
45195534Sscottl#include <sys/lock.h>
46195534Sscottl#include <sys/mutex.h>
47195534Sscottl#include <sys/sysctl.h>
48195534Sscottl
49195534Sscottl#include <cam/cam.h>
50195534Sscottl#include <cam/cam_ccb.h>
51195534Sscottl#include <cam/cam_queue.h>
52195534Sscottl#include <cam/cam_periph.h>
53195534Sscottl#include <cam/cam_sim.h>
54195534Sscottl#include <cam/cam_xpt.h>
55195534Sscottl#include <cam/cam_xpt_sim.h>
56195534Sscottl#include <cam/cam_xpt_periph.h>
57195534Sscottl#include <cam/cam_xpt_internal.h>
58195534Sscottl#include <cam/cam_debug.h>
59195534Sscottl
60195534Sscottl#include <cam/scsi/scsi_all.h>
61195534Sscottl#include <cam/scsi/scsi_message.h>
62195534Sscottl#include <cam/scsi/scsi_pass.h>
63195534Sscottl#include <machine/stdarg.h>	/* for xpt_print below */
64195534Sscottl#include "opt_cam.h"
65195534Sscottl
66195534Sscottlstruct scsi_quirk_entry {
67195534Sscottl	struct scsi_inquiry_pattern inq_pat;
68195534Sscottl	u_int8_t quirks;
69195534Sscottl#define	CAM_QUIRK_NOLUNS	0x01
70216088Sken#define	CAM_QUIRK_NOVPDS	0x02
71195534Sscottl#define	CAM_QUIRK_HILUNS	0x04
72195534Sscottl#define	CAM_QUIRK_NOHILUNS	0x08
73208911Smjacob#define	CAM_QUIRK_NORPTLUNS	0x10
74195534Sscottl	u_int mintags;
75195534Sscottl	u_int maxtags;
76195534Sscottl};
77195534Sscottl#define SCSI_QUIRK(dev)	((struct scsi_quirk_entry *)((dev)->quirk))
78195534Sscottl
79195534Sscottlstatic int cam_srch_hi = 0;
80195534Sscottlstatic int sysctl_cam_search_luns(SYSCTL_HANDLER_ARGS);
81267992ShselaskySYSCTL_PROC(_kern_cam, OID_AUTO, cam_srch_hi, CTLTYPE_INT | CTLFLAG_RWTUN, 0, 0,
82195534Sscottl    sysctl_cam_search_luns, "I",
83195534Sscottl    "allow search above LUN 7 for SCSI3 and greater devices");
84195534Sscottl
85195534Sscottl#define	CAM_SCSI2_MAXLUN	8
86208911Smjacob#define	CAM_CAN_GET_SIMPLE_LUN(x, i)				\
87208911Smjacob	((((x)->luns[i].lundata[0] & RPL_LUNDATA_ATYP_MASK) ==	\
88208911Smjacob	RPL_LUNDATA_ATYP_PERIPH) ||				\
89208911Smjacob	(((x)->luns[i].lundata[0] & RPL_LUNDATA_ATYP_MASK) ==	\
90208911Smjacob	RPL_LUNDATA_ATYP_FLAT))
91208911Smjacob#define	CAM_GET_SIMPLE_LUN(lp, i, lval)					\
92208911Smjacob	if (((lp)->luns[(i)].lundata[0] & RPL_LUNDATA_ATYP_MASK) == 	\
93208911Smjacob	    RPL_LUNDATA_ATYP_PERIPH) {					\
94208911Smjacob		(lval) = (lp)->luns[(i)].lundata[1];			\
95208911Smjacob	} else {							\
96208911Smjacob		(lval) = (lp)->luns[(i)].lundata[0];			\
97208911Smjacob		(lval) &= RPL_LUNDATA_FLAT_LUN_MASK;			\
98208911Smjacob		(lval) <<= 8;						\
99208911Smjacob		(lval) |=  (lp)->luns[(i)].lundata[1];			\
100208911Smjacob	}
101257345Snwhitehorn#define	CAM_GET_LUN(lp, i, lval)					\
102259397Snwhitehorn	(lval) = scsi_8btou64((lp)->luns[(i)].lundata);			\
103259397Snwhitehorn	(lval) = CAM_EXTLUN_BYTE_SWIZZLE(lval);
104257345Snwhitehorn
105195534Sscottl/*
106195534Sscottl * If we're not quirked to search <= the first 8 luns
107195534Sscottl * and we are either quirked to search above lun 8,
108195534Sscottl * or we're > SCSI-2 and we've enabled hilun searching,
109195534Sscottl * or we're > SCSI-2 and the last lun was a success,
110195534Sscottl * we can look for luns above lun 8.
111195534Sscottl */
112195534Sscottl#define	CAN_SRCH_HI_SPARSE(dv)					\
113195534Sscottl  (((SCSI_QUIRK(dv)->quirks & CAM_QUIRK_NOHILUNS) == 0) 	\
114195534Sscottl  && ((SCSI_QUIRK(dv)->quirks & CAM_QUIRK_HILUNS)		\
115195534Sscottl  || (SID_ANSI_REV(&dv->inq_data) > SCSI_REV_2 && cam_srch_hi)))
116195534Sscottl
117195534Sscottl#define	CAN_SRCH_HI_DENSE(dv)					\
118195534Sscottl  (((SCSI_QUIRK(dv)->quirks & CAM_QUIRK_NOHILUNS) == 0) 	\
119195534Sscottl  && ((SCSI_QUIRK(dv)->quirks & CAM_QUIRK_HILUNS)		\
120195534Sscottl  || (SID_ANSI_REV(&dv->inq_data) > SCSI_REV_2)))
121195534Sscottl
122195534Sscottlstatic periph_init_t probe_periph_init;
123195534Sscottl
124195534Sscottlstatic struct periph_driver probe_driver =
125195534Sscottl{
126195534Sscottl	probe_periph_init, "probe",
127198708Smav	TAILQ_HEAD_INITIALIZER(probe_driver.units), /* generation */ 0,
128198708Smav	CAM_PERIPH_DRV_EARLY
129195534Sscottl};
130195534Sscottl
131195534SscottlPERIPHDRIVER_DECLARE(probe, probe_driver);
132195534Sscottl
133195534Sscottltypedef enum {
134195534Sscottl	PROBE_TUR,
135195534Sscottl	PROBE_INQUIRY,	/* this counts as DV0 for Basic Domain Validation */
136195534Sscottl	PROBE_FULL_INQUIRY,
137208911Smjacob	PROBE_REPORT_LUNS,
138195534Sscottl	PROBE_MODE_SENSE,
139216088Sken	PROBE_SUPPORTED_VPD_LIST,
140216088Sken	PROBE_DEVICE_ID,
141278228Sken	PROBE_EXTENDED_INQUIRY,
142216088Sken	PROBE_SERIAL_NUM,
143195534Sscottl	PROBE_TUR_FOR_NEGOTIATION,
144195534Sscottl	PROBE_INQUIRY_BASIC_DV1,
145195534Sscottl	PROBE_INQUIRY_BASIC_DV2,
146195534Sscottl	PROBE_DV_EXIT,
147236613Smav	PROBE_DONE,
148195534Sscottl	PROBE_INVALID
149195534Sscottl} probe_action;
150195534Sscottl
151195534Sscottlstatic char *probe_action_text[] = {
152195534Sscottl	"PROBE_TUR",
153195534Sscottl	"PROBE_INQUIRY",
154195534Sscottl	"PROBE_FULL_INQUIRY",
155208911Smjacob	"PROBE_REPORT_LUNS",
156195534Sscottl	"PROBE_MODE_SENSE",
157216088Sken	"PROBE_SUPPORTED_VPD_LIST",
158216088Sken	"PROBE_DEVICE_ID",
159278228Sken	"PROBE_EXTENDED_INQUIRY",
160216088Sken	"PROBE_SERIAL_NUM",
161195534Sscottl	"PROBE_TUR_FOR_NEGOTIATION",
162195534Sscottl	"PROBE_INQUIRY_BASIC_DV1",
163195534Sscottl	"PROBE_INQUIRY_BASIC_DV2",
164195534Sscottl	"PROBE_DV_EXIT",
165236613Smav	"PROBE_DONE",
166195534Sscottl	"PROBE_INVALID"
167195534Sscottl};
168195534Sscottl
169195534Sscottl#define PROBE_SET_ACTION(softc, newaction)	\
170195534Sscottldo {									\
171195534Sscottl	char **text;							\
172195534Sscottl	text = probe_action_text;					\
173236613Smav	CAM_DEBUG((softc)->periph->path, CAM_DEBUG_PROBE,		\
174195534Sscottl	    ("Probe %s to %s\n", text[(softc)->action],			\
175195534Sscottl	    text[(newaction)]));					\
176195534Sscottl	(softc)->action = (newaction);					\
177195534Sscottl} while(0)
178195534Sscottl
179195534Sscottltypedef enum {
180195534Sscottl	PROBE_INQUIRY_CKSUM	= 0x01,
181195534Sscottl	PROBE_SERIAL_CKSUM	= 0x02,
182257345Snwhitehorn	PROBE_NO_ANNOUNCE	= 0x04,
183257345Snwhitehorn	PROBE_EXTLUN		= 0x08
184195534Sscottl} probe_flags;
185195534Sscottl
186195534Sscottltypedef struct {
187195534Sscottl	TAILQ_HEAD(, ccb_hdr) request_ccbs;
188195534Sscottl	probe_action	action;
189195534Sscottl	union ccb	saved_ccb;
190195534Sscottl	probe_flags	flags;
191195534Sscottl	MD5_CTX		context;
192195534Sscottl	u_int8_t	digest[16];
193195534Sscottl	struct cam_periph *periph;
194195534Sscottl} probe_softc;
195195534Sscottl
196195534Sscottlstatic const char quantum[] = "QUANTUM";
197195534Sscottlstatic const char sony[] = "SONY";
198195534Sscottlstatic const char west_digital[] = "WDIGTL";
199195534Sscottlstatic const char samsung[] = "SAMSUNG";
200195534Sscottlstatic const char seagate[] = "SEAGATE";
201195534Sscottlstatic const char microp[] = "MICROP";
202195534Sscottl
203195534Sscottlstatic struct scsi_quirk_entry scsi_quirk_table[] =
204195534Sscottl{
205195534Sscottl	{
206195534Sscottl		/* Reports QUEUE FULL for temporary resource shortages */
207195534Sscottl		{ T_DIRECT, SIP_MEDIA_FIXED, quantum, "XP39100*", "*" },
208195534Sscottl		/*quirks*/0, /*mintags*/24, /*maxtags*/32
209195534Sscottl	},
210195534Sscottl	{
211195534Sscottl		/* Reports QUEUE FULL for temporary resource shortages */
212195534Sscottl		{ T_DIRECT, SIP_MEDIA_FIXED, quantum, "XP34550*", "*" },
213195534Sscottl		/*quirks*/0, /*mintags*/24, /*maxtags*/32
214195534Sscottl	},
215195534Sscottl	{
216195534Sscottl		/* Reports QUEUE FULL for temporary resource shortages */
217195534Sscottl		{ T_DIRECT, SIP_MEDIA_FIXED, quantum, "XP32275*", "*" },
218195534Sscottl		/*quirks*/0, /*mintags*/24, /*maxtags*/32
219195534Sscottl	},
220195534Sscottl	{
221195534Sscottl		/* Broken tagged queuing drive */
222195534Sscottl		{ T_DIRECT, SIP_MEDIA_FIXED, microp, "4421-07*", "*" },
223195534Sscottl		/*quirks*/0, /*mintags*/0, /*maxtags*/0
224195534Sscottl	},
225195534Sscottl	{
226195534Sscottl		/* Broken tagged queuing drive */
227195534Sscottl		{ T_DIRECT, SIP_MEDIA_FIXED, "HP", "C372*", "*" },
228195534Sscottl		/*quirks*/0, /*mintags*/0, /*maxtags*/0
229195534Sscottl	},
230195534Sscottl	{
231195534Sscottl		/* Broken tagged queuing drive */
232195534Sscottl		{ T_DIRECT, SIP_MEDIA_FIXED, microp, "3391*", "x43h" },
233195534Sscottl		/*quirks*/0, /*mintags*/0, /*maxtags*/0
234195534Sscottl	},
235195534Sscottl	{
236195534Sscottl		/*
237195534Sscottl		 * Unfortunately, the Quantum Atlas III has the same
238195534Sscottl		 * problem as the Atlas II drives above.
239195534Sscottl		 * Reported by: "Johan Granlund" <johan@granlund.nu>
240195534Sscottl		 *
241195534Sscottl		 * For future reference, the drive with the problem was:
242195534Sscottl		 * QUANTUM QM39100TD-SW N1B0
243195534Sscottl		 *
244195534Sscottl		 * It's possible that Quantum will fix the problem in later
245195534Sscottl		 * firmware revisions.  If that happens, the quirk entry
246195534Sscottl		 * will need to be made specific to the firmware revisions
247195534Sscottl		 * with the problem.
248195534Sscottl		 *
249195534Sscottl		 */
250195534Sscottl		/* Reports QUEUE FULL for temporary resource shortages */
251195534Sscottl		{ T_DIRECT, SIP_MEDIA_FIXED, quantum, "QM39100*", "*" },
252195534Sscottl		/*quirks*/0, /*mintags*/24, /*maxtags*/32
253195534Sscottl	},
254195534Sscottl	{
255195534Sscottl		/*
256195534Sscottl		 * 18 Gig Atlas III, same problem as the 9G version.
257195534Sscottl		 * Reported by: Andre Albsmeier
258195534Sscottl		 *		<andre.albsmeier@mchp.siemens.de>
259195534Sscottl		 *
260195534Sscottl		 * For future reference, the drive with the problem was:
261195534Sscottl		 * QUANTUM QM318000TD-S N491
262195534Sscottl		 */
263195534Sscottl		/* Reports QUEUE FULL for temporary resource shortages */
264195534Sscottl		{ T_DIRECT, SIP_MEDIA_FIXED, quantum, "QM318000*", "*" },
265195534Sscottl		/*quirks*/0, /*mintags*/24, /*maxtags*/32
266195534Sscottl	},
267195534Sscottl	{
268195534Sscottl		/*
269195534Sscottl		 * Broken tagged queuing drive
270195534Sscottl		 * Reported by: Bret Ford <bford@uop.cs.uop.edu>
271195534Sscottl		 *         and: Martin Renters <martin@tdc.on.ca>
272195534Sscottl		 */
273195534Sscottl		{ T_DIRECT, SIP_MEDIA_FIXED, seagate, "ST410800*", "71*" },
274195534Sscottl		/*quirks*/0, /*mintags*/0, /*maxtags*/0
275195534Sscottl	},
276195534Sscottl		/*
277195534Sscottl		 * The Seagate Medalist Pro drives have very poor write
278195534Sscottl		 * performance with anything more than 2 tags.
279195534Sscottl		 *
280195534Sscottl		 * Reported by:  Paul van der Zwan <paulz@trantor.xs4all.nl>
281195534Sscottl		 * Drive:  <SEAGATE ST36530N 1444>
282195534Sscottl		 *
283195534Sscottl		 * Reported by:  Jeremy Lea <reg@shale.csir.co.za>
284195534Sscottl		 * Drive:  <SEAGATE ST34520W 1281>
285195534Sscottl		 *
286195534Sscottl		 * No one has actually reported that the 9G version
287195534Sscottl		 * (ST39140*) of the Medalist Pro has the same problem, but
288195534Sscottl		 * we're assuming that it does because the 4G and 6.5G
289195534Sscottl		 * versions of the drive are broken.
290195534Sscottl		 */
291195534Sscottl	{
292195534Sscottl		{ T_DIRECT, SIP_MEDIA_FIXED, seagate, "ST34520*", "*"},
293195534Sscottl		/*quirks*/0, /*mintags*/2, /*maxtags*/2
294195534Sscottl	},
295195534Sscottl	{
296195534Sscottl		{ T_DIRECT, SIP_MEDIA_FIXED, seagate, "ST36530*", "*"},
297195534Sscottl		/*quirks*/0, /*mintags*/2, /*maxtags*/2
298195534Sscottl	},
299195534Sscottl	{
300195534Sscottl		{ T_DIRECT, SIP_MEDIA_FIXED, seagate, "ST39140*", "*"},
301195534Sscottl		/*quirks*/0, /*mintags*/2, /*maxtags*/2
302195534Sscottl	},
303195534Sscottl	{
304195534Sscottl		/*
305231745Sgibbs		 * Experiences command timeouts under load with a
306231745Sgibbs		 * tag count higher than 55.
307231745Sgibbs		 */
308231745Sgibbs		{ T_DIRECT, SIP_MEDIA_FIXED, seagate, "ST3146855LW", "*"},
309231745Sgibbs		/*quirks*/0, /*mintags*/2, /*maxtags*/55
310231745Sgibbs	},
311231745Sgibbs	{
312231745Sgibbs		/*
313195534Sscottl		 * Slow when tagged queueing is enabled.  Write performance
314195534Sscottl		 * steadily drops off with more and more concurrent
315195534Sscottl		 * transactions.  Best sequential write performance with
316195534Sscottl		 * tagged queueing turned off and write caching turned on.
317195534Sscottl		 *
318195534Sscottl		 * PR:  kern/10398
319195534Sscottl		 * Submitted by:  Hideaki Okada <hokada@isl.melco.co.jp>
320195534Sscottl		 * Drive:  DCAS-34330 w/ "S65A" firmware.
321195534Sscottl		 *
322195534Sscottl		 * The drive with the problem had the "S65A" firmware
323195534Sscottl		 * revision, and has also been reported (by Stephen J.
324195534Sscottl		 * Roznowski <sjr@home.net>) for a drive with the "S61A"
325195534Sscottl		 * firmware revision.
326195534Sscottl		 *
327195534Sscottl		 * Although no one has reported problems with the 2 gig
328195534Sscottl		 * version of the DCAS drive, the assumption is that it
329195534Sscottl		 * has the same problems as the 4 gig version.  Therefore
330195534Sscottl		 * this quirk entries disables tagged queueing for all
331195534Sscottl		 * DCAS drives.
332195534Sscottl		 */
333195534Sscottl		{ T_DIRECT, SIP_MEDIA_FIXED, "IBM", "DCAS*", "*" },
334195534Sscottl		/*quirks*/0, /*mintags*/0, /*maxtags*/0
335195534Sscottl	},
336195534Sscottl	{
337195534Sscottl		/* Broken tagged queuing drive */
338195534Sscottl		{ T_DIRECT, SIP_MEDIA_REMOVABLE, "iomega", "jaz*", "*" },
339195534Sscottl		/*quirks*/0, /*mintags*/0, /*maxtags*/0
340195534Sscottl	},
341195534Sscottl	{
342195534Sscottl		/* Broken tagged queuing drive */
343195534Sscottl		{ T_DIRECT, SIP_MEDIA_FIXED, "CONNER", "CFP2107*", "*" },
344195534Sscottl		/*quirks*/0, /*mintags*/0, /*maxtags*/0
345195534Sscottl	},
346195534Sscottl	{
347195534Sscottl		/* This does not support other than LUN 0 */
348195534Sscottl		{ T_DIRECT, SIP_MEDIA_FIXED, "VMware*", "*", "*" },
349195534Sscottl		CAM_QUIRK_NOLUNS, /*mintags*/2, /*maxtags*/255
350195534Sscottl	},
351195534Sscottl	{
352195534Sscottl		/*
353195534Sscottl		 * Broken tagged queuing drive.
354195534Sscottl		 * Submitted by:
355195534Sscottl		 * NAKAJI Hiroyuki <nakaji@zeisei.dpri.kyoto-u.ac.jp>
356195534Sscottl		 * in PR kern/9535
357195534Sscottl		 */
358195534Sscottl		{ T_DIRECT, SIP_MEDIA_FIXED, samsung, "WN34324U*", "*" },
359195534Sscottl		/*quirks*/0, /*mintags*/0, /*maxtags*/0
360195534Sscottl	},
361195534Sscottl        {
362195534Sscottl		/*
363195534Sscottl		 * Slow when tagged queueing is enabled. (1.5MB/sec versus
364195534Sscottl		 * 8MB/sec.)
365195534Sscottl		 * Submitted by: Andrew Gallatin <gallatin@cs.duke.edu>
366195534Sscottl		 * Best performance with these drives is achieved with
367195534Sscottl		 * tagged queueing turned off, and write caching turned on.
368195534Sscottl		 */
369195534Sscottl		{ T_DIRECT, SIP_MEDIA_FIXED, west_digital, "WDE*", "*" },
370195534Sscottl		/*quirks*/0, /*mintags*/0, /*maxtags*/0
371195534Sscottl        },
372195534Sscottl        {
373195534Sscottl		/*
374195534Sscottl		 * Slow when tagged queueing is enabled. (1.5MB/sec versus
375195534Sscottl		 * 8MB/sec.)
376195534Sscottl		 * Submitted by: Andrew Gallatin <gallatin@cs.duke.edu>
377195534Sscottl		 * Best performance with these drives is achieved with
378195534Sscottl		 * tagged queueing turned off, and write caching turned on.
379195534Sscottl		 */
380195534Sscottl		{ T_DIRECT, SIP_MEDIA_FIXED, west_digital, "ENTERPRISE", "*" },
381195534Sscottl		/*quirks*/0, /*mintags*/0, /*maxtags*/0
382195534Sscottl        },
383195534Sscottl	{
384195534Sscottl		/*
385195534Sscottl		 * Doesn't handle queue full condition correctly,
386195534Sscottl		 * so we need to limit maxtags to what the device
387195534Sscottl		 * can handle instead of determining this automatically.
388195534Sscottl		 */
389195534Sscottl		{ T_DIRECT, SIP_MEDIA_FIXED, samsung, "WN321010S*", "*" },
390195534Sscottl		/*quirks*/0, /*mintags*/2, /*maxtags*/32
391195534Sscottl	},
392195534Sscottl	{
393195534Sscottl		/* Really only one LUN */
394195534Sscottl		{ T_ENCLOSURE, SIP_MEDIA_FIXED, "SUN", "SENA", "*" },
395195534Sscottl		CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0
396195534Sscottl	},
397195534Sscottl	{
398195534Sscottl		/* I can't believe we need a quirk for DPT volumes. */
399195534Sscottl		{ T_ANY, SIP_MEDIA_FIXED|SIP_MEDIA_REMOVABLE, "DPT", "*", "*" },
400195534Sscottl		CAM_QUIRK_NOLUNS,
401195534Sscottl		/*mintags*/0, /*maxtags*/255
402195534Sscottl	},
403195534Sscottl	{
404195534Sscottl		/*
405195534Sscottl		 * Many Sony CDROM drives don't like multi-LUN probing.
406195534Sscottl		 */
407195534Sscottl		{ T_CDROM, SIP_MEDIA_REMOVABLE, sony, "CD-ROM CDU*", "*" },
408195534Sscottl		CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0
409195534Sscottl	},
410195534Sscottl	{
411195534Sscottl		/*
412195534Sscottl		 * This drive doesn't like multiple LUN probing.
413195534Sscottl		 * Submitted by:  Parag Patel <parag@cgt.com>
414195534Sscottl		 */
415195534Sscottl		{ T_WORM, SIP_MEDIA_REMOVABLE, sony, "CD-R   CDU9*", "*" },
416195534Sscottl		CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0
417195534Sscottl	},
418195534Sscottl	{
419195534Sscottl		{ T_WORM, SIP_MEDIA_REMOVABLE, "YAMAHA", "CDR100*", "*" },
420195534Sscottl		CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0
421195534Sscottl	},
422195534Sscottl	{
423195534Sscottl		/*
424195534Sscottl		 * The 8200 doesn't like multi-lun probing, and probably
425195534Sscottl		 * don't like serial number requests either.
426195534Sscottl		 */
427195534Sscottl		{
428195534Sscottl			T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "EXABYTE",
429195534Sscottl			"EXB-8200*", "*"
430195534Sscottl		},
431195534Sscottl		CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0
432195534Sscottl	},
433195534Sscottl	{
434195534Sscottl		/*
435195534Sscottl		 * Let's try the same as above, but for a drive that says
436195534Sscottl		 * it's an IPL-6860 but is actually an EXB 8200.
437195534Sscottl		 */
438195534Sscottl		{
439195534Sscottl			T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "EXABYTE",
440195534Sscottl			"IPL-6860*", "*"
441195534Sscottl		},
442195534Sscottl		CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0
443195534Sscottl	},
444195534Sscottl	{
445195534Sscottl		/*
446195534Sscottl		 * These Hitachi drives don't like multi-lun probing.
447195534Sscottl		 * The PR submitter has a DK319H, but says that the Linux
448195534Sscottl		 * kernel has a similar work-around for the DK312 and DK314,
449195534Sscottl		 * so all DK31* drives are quirked here.
450195534Sscottl		 * PR:            misc/18793
451195534Sscottl		 * Submitted by:  Paul Haddad <paul@pth.com>
452195534Sscottl		 */
453195534Sscottl		{ T_DIRECT, SIP_MEDIA_FIXED, "HITACHI", "DK31*", "*" },
454195534Sscottl		CAM_QUIRK_NOLUNS, /*mintags*/2, /*maxtags*/255
455195534Sscottl	},
456195534Sscottl	{
457195534Sscottl		/*
458298810Spfg		 * The Hitachi CJ series with J8A8 firmware apparently has
459195534Sscottl		 * problems with tagged commands.
460195534Sscottl		 * PR: 23536
461195534Sscottl		 * Reported by: amagai@nue.org
462195534Sscottl		 */
463195534Sscottl		{ T_DIRECT, SIP_MEDIA_FIXED, "HITACHI", "DK32CJ*", "J8A8" },
464195534Sscottl		CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0
465195534Sscottl	},
466195534Sscottl	{
467195534Sscottl		/*
468195534Sscottl		 * These are the large storage arrays.
469195534Sscottl		 * Submitted by:  William Carrel <william.carrel@infospace.com>
470195534Sscottl		 */
471195534Sscottl		{ T_DIRECT, SIP_MEDIA_FIXED, "HITACHI", "OPEN*", "*" },
472195534Sscottl		CAM_QUIRK_HILUNS, 2, 1024
473195534Sscottl	},
474195534Sscottl	{
475195534Sscottl		/*
476195534Sscottl		 * This old revision of the TDC3600 is also SCSI-1, and
477195534Sscottl		 * hangs upon serial number probing.
478195534Sscottl		 */
479195534Sscottl		{
480195534Sscottl			T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "TANDBERG",
481195534Sscottl			" TDC 3600", "U07:"
482195534Sscottl		},
483216088Sken		CAM_QUIRK_NOVPDS, /*mintags*/0, /*maxtags*/0
484195534Sscottl	},
485195534Sscottl	{
486195534Sscottl		/*
487195534Sscottl		 * Would repond to all LUNs if asked for.
488195534Sscottl		 */
489195534Sscottl		{
490195534Sscottl			T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "CALIPER",
491195534Sscottl			"CP150", "*"
492195534Sscottl		},
493195534Sscottl		CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0
494195534Sscottl	},
495195534Sscottl	{
496195534Sscottl		/*
497195534Sscottl		 * Would repond to all LUNs if asked for.
498195534Sscottl		 */
499195534Sscottl		{
500195534Sscottl			T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "KENNEDY",
501195534Sscottl			"96X2*", "*"
502195534Sscottl		},
503195534Sscottl		CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0
504195534Sscottl	},
505195534Sscottl	{
506195534Sscottl		/* Submitted by: Matthew Dodd <winter@jurai.net> */
507195534Sscottl		{ T_PROCESSOR, SIP_MEDIA_FIXED, "Cabletrn", "EA41*", "*" },
508195534Sscottl		CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0
509195534Sscottl	},
510195534Sscottl	{
511195534Sscottl		/* Submitted by: Matthew Dodd <winter@jurai.net> */
512195534Sscottl		{ T_PROCESSOR, SIP_MEDIA_FIXED, "CABLETRN", "EA41*", "*" },
513195534Sscottl		CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0
514195534Sscottl	},
515195534Sscottl	{
516195534Sscottl		/* TeraSolutions special settings for TRC-22 RAID */
517195534Sscottl		{ T_DIRECT, SIP_MEDIA_FIXED, "TERASOLU", "TRC-22", "*" },
518195534Sscottl		  /*quirks*/0, /*mintags*/55, /*maxtags*/255
519195534Sscottl	},
520195534Sscottl	{
521195534Sscottl		/* Veritas Storage Appliance */
522195534Sscottl		{ T_DIRECT, SIP_MEDIA_FIXED, "VERITAS", "*", "*" },
523195534Sscottl		  CAM_QUIRK_HILUNS, /*mintags*/2, /*maxtags*/1024
524195534Sscottl	},
525195534Sscottl	{
526195534Sscottl		/*
527195534Sscottl		 * Would respond to all LUNs.  Device type and removable
528195534Sscottl		 * flag are jumper-selectable.
529195534Sscottl		 */
530195534Sscottl		{ T_ANY, SIP_MEDIA_REMOVABLE|SIP_MEDIA_FIXED, "MaxOptix",
531195534Sscottl		  "Tahiti 1", "*"
532195534Sscottl		},
533195534Sscottl		CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0
534195534Sscottl	},
535195534Sscottl	{
536195534Sscottl		/* EasyRAID E5A aka. areca ARC-6010 */
537195534Sscottl		{ T_DIRECT, SIP_MEDIA_FIXED, "easyRAID", "*", "*" },
538195534Sscottl		  CAM_QUIRK_NOHILUNS, /*mintags*/2, /*maxtags*/255
539195534Sscottl	},
540195534Sscottl	{
541195534Sscottl		{ T_ENCLOSURE, SIP_MEDIA_FIXED, "DP", "BACKPLANE", "*" },
542195534Sscottl		CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0
543195534Sscottl	},
544195534Sscottl	{
545236283Seadler		{ T_DIRECT, SIP_MEDIA_REMOVABLE, "Garmin", "*", "*" },
546236283Seadler		CAM_QUIRK_NORPTLUNS, /*mintags*/2, /*maxtags*/255
547236283Seadler	},
548236283Seadler	{
549331044Seadler		{ T_DIRECT, SIP_MEDIA_REMOVABLE, "Generic", "STORAGE DEVICE*", "120?" },
550331044Seadler		CAM_QUIRK_NORPTLUNS, /*mintags*/2, /*maxtags*/255
551331044Seadler	},
552331044Seadler	{
553331044Seadler		{ T_DIRECT, SIP_MEDIA_REMOVABLE, "Generic", "MassStorageClass", "1533" },
554331044Seadler		CAM_QUIRK_NORPTLUNS, /*mintags*/2, /*maxtags*/255
555331044Seadler	},
556331044Seadler	{
557195534Sscottl		/* Default tagged queuing parameters for all devices */
558195534Sscottl		{
559195534Sscottl		  T_ANY, SIP_MEDIA_REMOVABLE|SIP_MEDIA_FIXED,
560195534Sscottl		  /*vendor*/"*", /*product*/"*", /*revision*/"*"
561195534Sscottl		},
562195534Sscottl		/*quirks*/0, /*mintags*/2, /*maxtags*/255
563195534Sscottl	},
564195534Sscottl};
565195534Sscottl
566195534Sscottlstatic cam_status	proberegister(struct cam_periph *periph,
567195534Sscottl				      void *arg);
568195534Sscottlstatic void	 probeschedule(struct cam_periph *probe_periph);
569195534Sscottlstatic void	 probestart(struct cam_periph *periph, union ccb *start_ccb);
570195534Sscottlstatic void	 proberequestdefaultnegotiation(struct cam_periph *periph);
571195534Sscottlstatic int       proberequestbackoff(struct cam_periph *periph,
572195534Sscottl				     struct cam_ed *device);
573195534Sscottlstatic void	 probedone(struct cam_periph *periph, union ccb *done_ccb);
574208911Smjacobstatic void	 probe_purge_old(struct cam_path *path,
575257345Snwhitehorn				 struct scsi_report_luns_data *new,
576257345Snwhitehorn				 probe_flags flags);
577195534Sscottlstatic void	 probecleanup(struct cam_periph *periph);
578195534Sscottlstatic void	 scsi_find_quirk(struct cam_ed *device);
579195534Sscottlstatic void	 scsi_scan_bus(struct cam_periph *periph, union ccb *ccb);
580195534Sscottlstatic void	 scsi_scan_lun(struct cam_periph *periph,
581195534Sscottl			       struct cam_path *path, cam_flags flags,
582195534Sscottl			       union ccb *ccb);
583195534Sscottlstatic void	 xptscandone(struct cam_periph *periph, union ccb *done_ccb);
584195534Sscottlstatic struct cam_ed *
585195534Sscottl		 scsi_alloc_device(struct cam_eb *bus, struct cam_et *target,
586195534Sscottl				   lun_id_t lun_id);
587195534Sscottlstatic void	 scsi_devise_transport(struct cam_path *path);
588195534Sscottlstatic void	 scsi_set_transfer_settings(struct ccb_trans_settings *cts,
589256843Smav					    struct cam_path *path,
590195534Sscottl					    int async_update);
591195534Sscottlstatic void	 scsi_toggle_tags(struct cam_path *path);
592195534Sscottlstatic void	 scsi_dev_async(u_int32_t async_code,
593195534Sscottl				struct cam_eb *bus,
594195534Sscottl				struct cam_et *target,
595195534Sscottl				struct cam_ed *device,
596195534Sscottl				void *async_arg);
597195534Sscottlstatic void	 scsi_action(union ccb *start_ccb);
598204220Smavstatic void	 scsi_announce_periph(struct cam_periph *periph);
599328820Smavstatic void	 scsi_proto_announce(struct cam_ed *device);
600328820Smavstatic void	 scsi_proto_denounce(struct cam_ed *device);
601328820Smavstatic void	 scsi_proto_debug_out(union ccb *ccb);
602195534Sscottl
603328819Smavstatic struct xpt_xport_ops scsi_xport_ops = {
604195534Sscottl	.alloc_device = scsi_alloc_device,
605195534Sscottl	.action = scsi_action,
606195534Sscottl	.async = scsi_dev_async,
607204220Smav	.announce = scsi_announce_periph,
608195534Sscottl};
609328819Smav#define SCSI_XPT_XPORT(x, X)			\
610328819Smavstatic struct xpt_xport scsi_xport_ ## x = {	\
611328819Smav	.xport = XPORT_ ## X,			\
612328819Smav	.name = #x,				\
613328819Smav	.ops = &scsi_xport_ops,			\
614328819Smav};						\
615328819SmavCAM_XPT_XPORT(scsi_xport_ ## x);
616195534Sscottl
617328819SmavSCSI_XPT_XPORT(spi, SPI);
618328819SmavSCSI_XPT_XPORT(sas, SAS);
619328819SmavSCSI_XPT_XPORT(fc, FC);
620328819SmavSCSI_XPT_XPORT(usb, USB);
621328819SmavSCSI_XPT_XPORT(iscsi, ISCSI);
622328819SmavSCSI_XPT_XPORT(srp, SRP);
623328819SmavSCSI_XPT_XPORT(ppb, PPB);
624195534Sscottl
625328819Smav#undef SCSI_XPORT_XPORT
626328819Smav
627328820Smavstatic struct xpt_proto_ops scsi_proto_ops = {
628328820Smav	.announce = scsi_proto_announce,
629328820Smav	.denounce = scsi_proto_denounce,
630328820Smav	.debug_out = scsi_proto_debug_out,
631328820Smav};
632328820Smavstatic struct xpt_proto scsi_proto = {
633328820Smav	.proto = PROTO_SCSI,
634328820Smav	.name = "scsi",
635328820Smav	.ops = &scsi_proto_ops,
636328820Smav};
637328820SmavCAM_XPT_PROTO(scsi_proto);
638328820Smav
639195534Sscottlstatic void
640195534Sscottlprobe_periph_init()
641195534Sscottl{
642195534Sscottl}
643195534Sscottl
644195534Sscottlstatic cam_status
645195534Sscottlproberegister(struct cam_periph *periph, void *arg)
646195534Sscottl{
647195534Sscottl	union ccb *request_ccb;	/* CCB representing the probe request */
648195534Sscottl	cam_status status;
649195534Sscottl	probe_softc *softc;
650195534Sscottl
651195534Sscottl	request_ccb = (union ccb *)arg;
652195534Sscottl	if (request_ccb == NULL) {
653195534Sscottl		printf("proberegister: no probe CCB, "
654195534Sscottl		       "can't register device\n");
655195534Sscottl		return(CAM_REQ_CMP_ERR);
656195534Sscottl	}
657195534Sscottl
658195534Sscottl	softc = (probe_softc *)malloc(sizeof(*softc), M_CAMXPT, M_NOWAIT);
659195534Sscottl
660195534Sscottl	if (softc == NULL) {
661195534Sscottl		printf("proberegister: Unable to probe new device. "
662195534Sscottl		       "Unable to allocate softc\n");
663195534Sscottl		return(CAM_REQ_CMP_ERR);
664195534Sscottl	}
665195534Sscottl	TAILQ_INIT(&softc->request_ccbs);
666195534Sscottl	TAILQ_INSERT_TAIL(&softc->request_ccbs, &request_ccb->ccb_h,
667195534Sscottl			  periph_links.tqe);
668195534Sscottl	softc->flags = 0;
669195534Sscottl	periph->softc = softc;
670195534Sscottl	softc->periph = periph;
671195534Sscottl	softc->action = PROBE_INVALID;
672195534Sscottl	status = cam_periph_acquire(periph);
673195534Sscottl	if (status != CAM_REQ_CMP) {
674195534Sscottl		return (status);
675195534Sscottl	}
676236613Smav	CAM_DEBUG(periph->path, CAM_DEBUG_PROBE, ("Probe started\n"));
677256843Smav	scsi_devise_transport(periph->path);
678195534Sscottl
679195534Sscottl	/*
680195534Sscottl	 * Ensure we've waited at least a bus settle
681195534Sscottl	 * delay before attempting to probe the device.
682195534Sscottl	 * For HBAs that don't do bus resets, this won't make a difference.
683195534Sscottl	 */
684195534Sscottl	cam_periph_freeze_after_event(periph, &periph->path->bus->last_reset,
685195534Sscottl				      scsi_delay);
686195534Sscottl	probeschedule(periph);
687195534Sscottl	return(CAM_REQ_CMP);
688195534Sscottl}
689195534Sscottl
690195534Sscottlstatic void
691195534Sscottlprobeschedule(struct cam_periph *periph)
692195534Sscottl{
693195534Sscottl	struct ccb_pathinq cpi;
694195534Sscottl	union ccb *ccb;
695195534Sscottl	probe_softc *softc;
696195534Sscottl
697195534Sscottl	softc = (probe_softc *)periph->softc;
698195534Sscottl	ccb = (union ccb *)TAILQ_FIRST(&softc->request_ccbs);
699195534Sscottl
700350804Smav	xpt_path_inq(&cpi, periph->path);
701195534Sscottl
702195534Sscottl	/*
703195534Sscottl	 * If a device has gone away and another device, or the same one,
704195534Sscottl	 * is back in the same place, it should have a unit attention
705195534Sscottl	 * condition pending.  It will not report the unit attention in
706195534Sscottl	 * response to an inquiry, which may leave invalid transfer
707195534Sscottl	 * negotiations in effect.  The TUR will reveal the unit attention
708195534Sscottl	 * condition.  Only send the TUR for lun 0, since some devices
709195534Sscottl	 * will get confused by commands other than inquiry to non-existent
710195534Sscottl	 * luns.  If you think a device has gone away start your scan from
711195534Sscottl	 * lun 0.  This will insure that any bogus transfer settings are
712195534Sscottl	 * invalidated.
713195534Sscottl	 *
714195534Sscottl	 * If we haven't seen the device before and the controller supports
715195534Sscottl	 * some kind of transfer negotiation, negotiate with the first
716195534Sscottl	 * sent command if no bus reset was performed at startup.  This
717195534Sscottl	 * ensures that the device is not confused by transfer negotiation
718195534Sscottl	 * settings left over by loader or BIOS action.
719195534Sscottl	 */
720195534Sscottl	if (((ccb->ccb_h.path->device->flags & CAM_DEV_UNCONFIGURED) == 0)
721195534Sscottl	 && (ccb->ccb_h.target_lun == 0)) {
722195534Sscottl		PROBE_SET_ACTION(softc, PROBE_TUR);
723195534Sscottl	} else if ((cpi.hba_inquiry & (PI_WIDE_32|PI_WIDE_16|PI_SDTR_ABLE)) != 0
724195534Sscottl	      && (cpi.hba_misc & PIM_NOBUSRESET) != 0) {
725195534Sscottl		proberequestdefaultnegotiation(periph);
726195534Sscottl		PROBE_SET_ACTION(softc, PROBE_INQUIRY);
727195534Sscottl	} else {
728195534Sscottl		PROBE_SET_ACTION(softc, PROBE_INQUIRY);
729195534Sscottl	}
730195534Sscottl
731195534Sscottl	if (ccb->crcn.flags & CAM_EXPECT_INQ_CHANGE)
732195534Sscottl		softc->flags |= PROBE_NO_ANNOUNCE;
733195534Sscottl	else
734195534Sscottl		softc->flags &= ~PROBE_NO_ANNOUNCE;
735195534Sscottl
736257345Snwhitehorn	if (cpi.hba_misc & PIM_EXTLUNS)
737257345Snwhitehorn		softc->flags |= PROBE_EXTLUN;
738257345Snwhitehorn	else
739257345Snwhitehorn		softc->flags &= ~PROBE_EXTLUN;
740257345Snwhitehorn
741203108Smav	xpt_schedule(periph, CAM_PRIORITY_XPT);
742195534Sscottl}
743195534Sscottl
744195534Sscottlstatic void
745195534Sscottlprobestart(struct cam_periph *periph, union ccb *start_ccb)
746195534Sscottl{
747195534Sscottl	/* Probe the device that our peripheral driver points to */
748195534Sscottl	struct ccb_scsiio *csio;
749195534Sscottl	probe_softc *softc;
750195534Sscottl
751195534Sscottl	CAM_DEBUG(start_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("probestart\n"));
752195534Sscottl
753195534Sscottl	softc = (probe_softc *)periph->softc;
754195534Sscottl	csio = &start_ccb->csio;
755208911Smjacobagain:
756195534Sscottl
757195534Sscottl	switch (softc->action) {
758195534Sscottl	case PROBE_TUR:
759195534Sscottl	case PROBE_TUR_FOR_NEGOTIATION:
760195534Sscottl	case PROBE_DV_EXIT:
761195534Sscottl	{
762195534Sscottl		scsi_test_unit_ready(csio,
763236814Smav				     /*retries*/4,
764195534Sscottl				     probedone,
765195534Sscottl				     MSG_SIMPLE_Q_TAG,
766195534Sscottl				     SSD_FULL_SIZE,
767195534Sscottl				     /*timeout*/60000);
768195534Sscottl		break;
769195534Sscottl	}
770195534Sscottl	case PROBE_INQUIRY:
771195534Sscottl	case PROBE_FULL_INQUIRY:
772195534Sscottl	case PROBE_INQUIRY_BASIC_DV1:
773195534Sscottl	case PROBE_INQUIRY_BASIC_DV2:
774195534Sscottl	{
775195534Sscottl		u_int inquiry_len;
776195534Sscottl		struct scsi_inquiry_data *inq_buf;
777195534Sscottl
778195534Sscottl		inq_buf = &periph->path->device->inq_data;
779195534Sscottl
780195534Sscottl		/*
781195534Sscottl		 * If the device is currently configured, we calculate an
782195534Sscottl		 * MD5 checksum of the inquiry data, and if the serial number
783195534Sscottl		 * length is greater than 0, add the serial number data
784195534Sscottl		 * into the checksum as well.  Once the inquiry and the
785195534Sscottl		 * serial number check finish, we attempt to figure out
786195534Sscottl		 * whether we still have the same device.
787195534Sscottl		 */
788276831Sken		if (((periph->path->device->flags & CAM_DEV_UNCONFIGURED) == 0)
789276831Sken		 && ((softc->flags & PROBE_INQUIRY_CKSUM) == 0)) {
790195534Sscottl
791195534Sscottl			MD5Init(&softc->context);
792195534Sscottl			MD5Update(&softc->context, (unsigned char *)inq_buf,
793195534Sscottl				  sizeof(struct scsi_inquiry_data));
794195534Sscottl			softc->flags |= PROBE_INQUIRY_CKSUM;
795195534Sscottl			if (periph->path->device->serial_num_len > 0) {
796195534Sscottl				MD5Update(&softc->context,
797195534Sscottl					  periph->path->device->serial_num,
798195534Sscottl					  periph->path->device->serial_num_len);
799195534Sscottl				softc->flags |= PROBE_SERIAL_CKSUM;
800195534Sscottl			}
801195534Sscottl			MD5Final(softc->digest, &softc->context);
802195534Sscottl		}
803195534Sscottl
804195534Sscottl		if (softc->action == PROBE_INQUIRY)
805195534Sscottl			inquiry_len = SHORT_INQUIRY_LENGTH;
806195534Sscottl		else
807195534Sscottl			inquiry_len = SID_ADDITIONAL_LENGTH(inq_buf);
808195534Sscottl
809195534Sscottl		/*
810195534Sscottl		 * Some parallel SCSI devices fail to send an
811195534Sscottl		 * ignore wide residue message when dealing with
812195534Sscottl		 * odd length inquiry requests.  Round up to be
813195534Sscottl		 * safe.
814195534Sscottl		 */
815195534Sscottl		inquiry_len = roundup2(inquiry_len, 2);
816195534Sscottl
817195534Sscottl		if (softc->action == PROBE_INQUIRY_BASIC_DV1
818195534Sscottl		 || softc->action == PROBE_INQUIRY_BASIC_DV2) {
819195534Sscottl			inq_buf = malloc(inquiry_len, M_CAMXPT, M_NOWAIT);
820195534Sscottl		}
821195534Sscottl		if (inq_buf == NULL) {
822195534Sscottl			xpt_print(periph->path, "malloc failure- skipping Basic"
823195534Sscottl			    "Domain Validation\n");
824195534Sscottl			PROBE_SET_ACTION(softc, PROBE_DV_EXIT);
825195534Sscottl			scsi_test_unit_ready(csio,
826195534Sscottl					     /*retries*/4,
827195534Sscottl					     probedone,
828195534Sscottl					     MSG_SIMPLE_Q_TAG,
829195534Sscottl					     SSD_FULL_SIZE,
830195534Sscottl					     /*timeout*/60000);
831195534Sscottl			break;
832195534Sscottl		}
833195534Sscottl		scsi_inquiry(csio,
834195534Sscottl			     /*retries*/4,
835195534Sscottl			     probedone,
836195534Sscottl			     MSG_SIMPLE_Q_TAG,
837195534Sscottl			     (u_int8_t *)inq_buf,
838195534Sscottl			     inquiry_len,
839195534Sscottl			     /*evpd*/FALSE,
840195534Sscottl			     /*page_code*/0,
841195534Sscottl			     SSD_MIN_SIZE,
842195534Sscottl			     /*timeout*/60 * 1000);
843195534Sscottl		break;
844195534Sscottl	}
845208911Smjacob	case PROBE_REPORT_LUNS:
846208911Smjacob	{
847208911Smjacob		void *rp;
848208911Smjacob
849208911Smjacob		rp = malloc(periph->path->target->rpl_size,
850208911Smjacob		    M_CAMXPT, M_NOWAIT | M_ZERO);
851208911Smjacob		if (rp == NULL) {
852208911Smjacob			struct scsi_inquiry_data *inq_buf;
853208911Smjacob			inq_buf = &periph->path->device->inq_data;
854208911Smjacob			xpt_print(periph->path,
855208911Smjacob			    "Unable to alloc report luns storage\n");
856208911Smjacob			if (INQ_DATA_TQ_ENABLED(inq_buf))
857208911Smjacob				PROBE_SET_ACTION(softc, PROBE_MODE_SENSE);
858208911Smjacob			else
859216088Sken				PROBE_SET_ACTION(softc,
860216088Sken				    PROBE_SUPPORTED_VPD_LIST);
861208911Smjacob			goto again;
862208911Smjacob		}
863208911Smjacob		scsi_report_luns(csio, 5, probedone, MSG_SIMPLE_Q_TAG,
864208911Smjacob		    RPL_REPORT_DEFAULT, rp, periph->path->target->rpl_size,
865208911Smjacob		    SSD_FULL_SIZE, 60000); break;
866208911Smjacob		break;
867208911Smjacob	}
868195534Sscottl	case PROBE_MODE_SENSE:
869195534Sscottl	{
870195534Sscottl		void  *mode_buf;
871195534Sscottl		int    mode_buf_len;
872195534Sscottl
873195534Sscottl		mode_buf_len = sizeof(struct scsi_mode_header_6)
874195534Sscottl			     + sizeof(struct scsi_mode_blk_desc)
875195534Sscottl			     + sizeof(struct scsi_control_page);
876195534Sscottl		mode_buf = malloc(mode_buf_len, M_CAMXPT, M_NOWAIT);
877195534Sscottl		if (mode_buf != NULL) {
878195534Sscottl	                scsi_mode_sense(csio,
879195534Sscottl					/*retries*/4,
880195534Sscottl					probedone,
881195534Sscottl					MSG_SIMPLE_Q_TAG,
882195534Sscottl					/*dbd*/FALSE,
883195534Sscottl					SMS_PAGE_CTRL_CURRENT,
884195534Sscottl					SMS_CONTROL_MODE_PAGE,
885195534Sscottl					mode_buf,
886195534Sscottl					mode_buf_len,
887195534Sscottl					SSD_FULL_SIZE,
888195534Sscottl					/*timeout*/60000);
889195534Sscottl			break;
890195534Sscottl		}
891195534Sscottl		xpt_print(periph->path, "Unable to mode sense control page - "
892195534Sscottl		    "malloc failure\n");
893216088Sken		PROBE_SET_ACTION(softc, PROBE_SUPPORTED_VPD_LIST);
894195534Sscottl	}
895195534Sscottl	/* FALLTHROUGH */
896216088Sken	case PROBE_SUPPORTED_VPD_LIST:
897195534Sscottl	{
898216088Sken		struct scsi_vpd_supported_page_list *vpd_list;
899195534Sscottl		struct cam_ed *device;
900195534Sscottl
901216088Sken		vpd_list = NULL;
902195534Sscottl		device = periph->path->device;
903216088Sken
904216088Sken		if ((SCSI_QUIRK(device)->quirks & CAM_QUIRK_NOVPDS) == 0)
905195534Sscottl			vpd_list = malloc(sizeof(*vpd_list), M_CAMXPT,
906195534Sscottl			    M_NOWAIT | M_ZERO);
907195534Sscottl
908195534Sscottl		if (vpd_list != NULL) {
909195534Sscottl			scsi_inquiry(csio,
910195534Sscottl				     /*retries*/4,
911195534Sscottl				     probedone,
912195534Sscottl				     MSG_SIMPLE_Q_TAG,
913195534Sscottl				     (u_int8_t *)vpd_list,
914195534Sscottl				     sizeof(*vpd_list),
915195534Sscottl				     /*evpd*/TRUE,
916195534Sscottl				     SVPD_SUPPORTED_PAGE_LIST,
917195534Sscottl				     SSD_MIN_SIZE,
918195534Sscottl				     /*timeout*/60 * 1000);
919195534Sscottl			break;
920195534Sscottl		}
921260541Smavdone:
922195534Sscottl		/*
923195534Sscottl		 * We'll have to do without, let our probedone
924195534Sscottl		 * routine finish up for us.
925195534Sscottl		 */
926195534Sscottl		start_ccb->csio.data_ptr = NULL;
927250025Smav		cam_freeze_devq(periph->path);
928260541Smav		cam_periph_doacquire(periph);
929195534Sscottl		probedone(periph, start_ccb);
930195534Sscottl		return;
931195534Sscottl	}
932216088Sken	case PROBE_DEVICE_ID:
933195534Sscottl	{
934216088Sken		struct scsi_vpd_device_id *devid;
935216088Sken
936216088Sken		devid = NULL;
937249937Ssmh		if (scsi_vpd_supported_page(periph, SVPD_DEVICE_ID))
938216088Sken			devid = malloc(SVPD_DEVICE_ID_MAX_SIZE, M_CAMXPT,
939216088Sken			    M_NOWAIT | M_ZERO);
940216088Sken
941216088Sken		if (devid != NULL) {
942216088Sken			scsi_inquiry(csio,
943216088Sken				     /*retries*/4,
944216088Sken				     probedone,
945216088Sken				     MSG_SIMPLE_Q_TAG,
946216088Sken				     (uint8_t *)devid,
947216088Sken				     SVPD_DEVICE_ID_MAX_SIZE,
948216088Sken				     /*evpd*/TRUE,
949216088Sken				     SVPD_DEVICE_ID,
950216088Sken				     SSD_MIN_SIZE,
951216088Sken				     /*timeout*/60 * 1000);
952216088Sken			break;
953216088Sken		}
954260541Smav		goto done;
955216088Sken	}
956278228Sken	case PROBE_EXTENDED_INQUIRY:
957278228Sken	{
958278228Sken		struct scsi_vpd_extended_inquiry_data *ext_inq;
959278228Sken
960278228Sken		ext_inq = NULL;
961278228Sken		if (scsi_vpd_supported_page(periph, SVPD_EXTENDED_INQUIRY_DATA))
962278228Sken			ext_inq = malloc(sizeof(*ext_inq), M_CAMXPT,
963278228Sken			    M_NOWAIT | M_ZERO);
964278228Sken
965278228Sken		if (ext_inq != NULL) {
966278228Sken			scsi_inquiry(csio,
967278228Sken				     /*retries*/4,
968278228Sken				     probedone,
969278228Sken				     MSG_SIMPLE_Q_TAG,
970278228Sken				     (uint8_t *)ext_inq,
971278228Sken				     sizeof(*ext_inq),
972278228Sken				     /*evpd*/TRUE,
973278228Sken				     SVPD_EXTENDED_INQUIRY_DATA,
974278228Sken				     SSD_MIN_SIZE,
975278228Sken				     /*timeout*/60 * 1000);
976278228Sken			break;
977278228Sken		}
978278228Sken		/*
979278228Sken		 * We'll have to do without, let our probedone
980278228Sken		 * routine finish up for us.
981278228Sken		 */
982278228Sken		goto done;
983278228Sken	}
984216088Sken	case PROBE_SERIAL_NUM:
985216088Sken	{
986195534Sscottl		struct scsi_vpd_unit_serial_number *serial_buf;
987195534Sscottl		struct cam_ed* device;
988195534Sscottl
989195534Sscottl		serial_buf = NULL;
990195534Sscottl		device = periph->path->device;
991195685Semaste		if (device->serial_num != NULL) {
992195685Semaste			free(device->serial_num, M_CAMXPT);
993195685Semaste			device->serial_num = NULL;
994195685Semaste			device->serial_num_len = 0;
995195685Semaste		}
996195534Sscottl
997249937Ssmh		if (scsi_vpd_supported_page(periph, SVPD_UNIT_SERIAL_NUMBER))
998216088Sken			serial_buf = (struct scsi_vpd_unit_serial_number *)
999216088Sken				malloc(sizeof(*serial_buf), M_CAMXPT,
1000216088Sken				    M_NOWAIT|M_ZERO);
1001195534Sscottl
1002195534Sscottl		if (serial_buf != NULL) {
1003195534Sscottl			scsi_inquiry(csio,
1004195534Sscottl				     /*retries*/4,
1005195534Sscottl				     probedone,
1006195534Sscottl				     MSG_SIMPLE_Q_TAG,
1007195534Sscottl				     (u_int8_t *)serial_buf,
1008195534Sscottl				     sizeof(*serial_buf),
1009195534Sscottl				     /*evpd*/TRUE,
1010195534Sscottl				     SVPD_UNIT_SERIAL_NUMBER,
1011195534Sscottl				     SSD_MIN_SIZE,
1012195534Sscottl				     /*timeout*/60 * 1000);
1013195534Sscottl			break;
1014195534Sscottl		}
1015260541Smav		goto done;
1016195534Sscottl	}
1017195534Sscottl	default:
1018236613Smav		panic("probestart: invalid action state 0x%x\n", softc->action);
1019195534Sscottl	}
1020249466Smav	start_ccb->ccb_h.flags |= CAM_DEV_QFREEZE;
1021260541Smav	cam_periph_doacquire(periph);
1022195534Sscottl	xpt_action(start_ccb);
1023195534Sscottl}
1024195534Sscottl
1025195534Sscottlstatic void
1026195534Sscottlproberequestdefaultnegotiation(struct cam_periph *periph)
1027195534Sscottl{
1028195534Sscottl	struct ccb_trans_settings cts;
1029195534Sscottl
1030203108Smav	xpt_setup_ccb(&cts.ccb_h, periph->path, CAM_PRIORITY_NONE);
1031195534Sscottl	cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
1032195534Sscottl	cts.type = CTS_TYPE_USER_SETTINGS;
1033195534Sscottl	xpt_action((union ccb *)&cts);
1034252382Sscottl	if (cam_ccb_status((union ccb *)&cts) != CAM_REQ_CMP) {
1035195534Sscottl		return;
1036195534Sscottl	}
1037195534Sscottl	cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
1038195534Sscottl	cts.type = CTS_TYPE_CURRENT_SETTINGS;
1039195534Sscottl	xpt_action((union ccb *)&cts);
1040195534Sscottl}
1041195534Sscottl
1042195534Sscottl/*
1043195534Sscottl * Backoff Negotiation Code- only pertinent for SPI devices.
1044195534Sscottl */
1045195534Sscottlstatic int
1046195534Sscottlproberequestbackoff(struct cam_periph *periph, struct cam_ed *device)
1047195534Sscottl{
1048195534Sscottl	struct ccb_trans_settings cts;
1049195534Sscottl	struct ccb_trans_settings_spi *spi;
1050195534Sscottl
1051195534Sscottl	memset(&cts, 0, sizeof (cts));
1052203108Smav	xpt_setup_ccb(&cts.ccb_h, periph->path, CAM_PRIORITY_NONE);
1053195534Sscottl	cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
1054195534Sscottl	cts.type = CTS_TYPE_CURRENT_SETTINGS;
1055195534Sscottl	xpt_action((union ccb *)&cts);
1056252382Sscottl	if (cam_ccb_status((union ccb *)&cts) != CAM_REQ_CMP) {
1057195534Sscottl		if (bootverbose) {
1058195534Sscottl			xpt_print(periph->path,
1059195534Sscottl			    "failed to get current device settings\n");
1060195534Sscottl		}
1061195534Sscottl		return (0);
1062195534Sscottl	}
1063195534Sscottl	if (cts.transport != XPORT_SPI) {
1064195534Sscottl		if (bootverbose) {
1065195534Sscottl			xpt_print(periph->path, "not SPI transport\n");
1066195534Sscottl		}
1067195534Sscottl		return (0);
1068195534Sscottl	}
1069195534Sscottl	spi = &cts.xport_specific.spi;
1070195534Sscottl
1071195534Sscottl	/*
1072195534Sscottl	 * We cannot renegotiate sync rate if we don't have one.
1073195534Sscottl	 */
1074195534Sscottl	if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) == 0) {
1075195534Sscottl		if (bootverbose) {
1076195534Sscottl			xpt_print(periph->path, "no sync rate known\n");
1077195534Sscottl		}
1078195534Sscottl		return (0);
1079195534Sscottl	}
1080195534Sscottl
1081195534Sscottl	/*
1082195534Sscottl	 * We'll assert that we don't have to touch PPR options- the
1083195534Sscottl	 * SIM will see what we do with period and offset and adjust
1084195534Sscottl	 * the PPR options as appropriate.
1085195534Sscottl	 */
1086195534Sscottl
1087195534Sscottl	/*
1088195534Sscottl	 * A sync rate with unknown or zero offset is nonsensical.
1089195534Sscottl	 * A sync period of zero means Async.
1090195534Sscottl	 */
1091195534Sscottl	if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) == 0
1092195534Sscottl	 || spi->sync_offset == 0 || spi->sync_period == 0) {
1093195534Sscottl		if (bootverbose) {
1094195534Sscottl			xpt_print(periph->path, "no sync rate available\n");
1095195534Sscottl		}
1096195534Sscottl		return (0);
1097195534Sscottl	}
1098195534Sscottl
1099195534Sscottl	if (device->flags & CAM_DEV_DV_HIT_BOTTOM) {
1100236613Smav		CAM_DEBUG(periph->path, CAM_DEBUG_PROBE,
1101195534Sscottl		    ("hit async: giving up on DV\n"));
1102195534Sscottl		return (0);
1103195534Sscottl	}
1104195534Sscottl
1105195534Sscottl
1106195534Sscottl	/*
1107195534Sscottl	 * Jump sync_period up by one, but stop at 5MHz and fall back to Async.
1108195534Sscottl	 * We don't try to remember 'last' settings to see if the SIM actually
1109195534Sscottl	 * gets into the speed we want to set. We check on the SIM telling
1110195534Sscottl	 * us that a requested speed is bad, but otherwise don't try and
1111195534Sscottl	 * check the speed due to the asynchronous and handshake nature
1112195534Sscottl	 * of speed setting.
1113195534Sscottl	 */
1114195534Sscottl	spi->valid = CTS_SPI_VALID_SYNC_RATE | CTS_SPI_VALID_SYNC_OFFSET;
1115195534Sscottl	for (;;) {
1116195534Sscottl		spi->sync_period++;
1117195534Sscottl		if (spi->sync_period >= 0xf) {
1118195534Sscottl			spi->sync_period = 0;
1119195534Sscottl			spi->sync_offset = 0;
1120236613Smav			CAM_DEBUG(periph->path, CAM_DEBUG_PROBE,
1121195534Sscottl			    ("setting to async for DV\n"));
1122195534Sscottl			/*
1123195534Sscottl			 * Once we hit async, we don't want to try
1124195534Sscottl			 * any more settings.
1125195534Sscottl			 */
1126195534Sscottl			device->flags |= CAM_DEV_DV_HIT_BOTTOM;
1127195534Sscottl		} else if (bootverbose) {
1128236613Smav			CAM_DEBUG(periph->path, CAM_DEBUG_PROBE,
1129195534Sscottl			    ("DV: period 0x%x\n", spi->sync_period));
1130195534Sscottl			printf("setting period to 0x%x\n", spi->sync_period);
1131195534Sscottl		}
1132195534Sscottl		cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
1133195534Sscottl		cts.type = CTS_TYPE_CURRENT_SETTINGS;
1134195534Sscottl		xpt_action((union ccb *)&cts);
1135252382Sscottl		if (cam_ccb_status((union ccb *)&cts) != CAM_REQ_CMP) {
1136195534Sscottl			break;
1137195534Sscottl		}
1138236613Smav		CAM_DEBUG(periph->path, CAM_DEBUG_PROBE,
1139195534Sscottl		    ("DV: failed to set period 0x%x\n", spi->sync_period));
1140195534Sscottl		if (spi->sync_period == 0) {
1141195534Sscottl			return (0);
1142195534Sscottl		}
1143195534Sscottl	}
1144195534Sscottl	return (1);
1145195534Sscottl}
1146195534Sscottl
1147216088Sken#define CCB_COMPLETED_OK(ccb) (((ccb).status & CAM_STATUS_MASK) == CAM_REQ_CMP)
1148216088Sken
1149195534Sscottlstatic void
1150195534Sscottlprobedone(struct cam_periph *periph, union ccb *done_ccb)
1151195534Sscottl{
1152195534Sscottl	probe_softc *softc;
1153195534Sscottl	struct cam_path *path;
1154287289Smav	struct scsi_inquiry_data *inq_buf;
1155195534Sscottl	u_int32_t  priority;
1156195534Sscottl
1157195534Sscottl	CAM_DEBUG(done_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("probedone\n"));
1158195534Sscottl
1159195534Sscottl	softc = (probe_softc *)periph->softc;
1160195534Sscottl	path = done_ccb->ccb_h.path;
1161195534Sscottl	priority = done_ccb->ccb_h.pinfo.priority;
1162326777Sasomers	cam_periph_assert(periph, MA_OWNED);
1163195534Sscottl
1164195534Sscottl	switch (softc->action) {
1165195534Sscottl	case PROBE_TUR:
1166195534Sscottl	{
1167252382Sscottl		if (cam_ccb_status(done_ccb) != CAM_REQ_CMP) {
1168195534Sscottl
1169195534Sscottl			if (cam_periph_error(done_ccb, 0,
1170249466Smav					     SF_NO_PRINT, NULL) == ERESTART) {
1171260547Smavoutr:
1172249466Smav				/* Drop freeze taken due to CAM_DEV_QFREEZE */
1173249466Smav				cam_release_devq(path, 0, 0, 0, FALSE);
1174195534Sscottl				return;
1175249466Smav			}
1176195534Sscottl			else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
1177195534Sscottl				/* Don't wedge the queue */
1178195534Sscottl				xpt_release_devq(done_ccb->ccb_h.path,
1179195534Sscottl						 /*count*/1,
1180195534Sscottl						 /*run_queue*/TRUE);
1181195534Sscottl		}
1182195534Sscottl		PROBE_SET_ACTION(softc, PROBE_INQUIRY);
1183195534Sscottl		xpt_release_ccb(done_ccb);
1184195534Sscottl		xpt_schedule(periph, priority);
1185260547Smavout:
1186260547Smav		/* Drop freeze taken due to CAM_DEV_QFREEZE and release. */
1187260547Smav		cam_release_devq(path, 0, 0, 0, FALSE);
1188260547Smav		cam_periph_release_locked(periph);
1189260547Smav		return;
1190195534Sscottl	}
1191195534Sscottl	case PROBE_INQUIRY:
1192195534Sscottl	case PROBE_FULL_INQUIRY:
1193195534Sscottl	{
1194252382Sscottl		if (cam_ccb_status(done_ccb) == CAM_REQ_CMP) {
1195195534Sscottl			u_int8_t periph_qual;
1196195534Sscottl
1197195534Sscottl			path->device->flags |= CAM_DEV_INQUIRY_DATA_VALID;
1198272401Smav			scsi_find_quirk(path->device);
1199195534Sscottl			inq_buf = &path->device->inq_data;
1200195534Sscottl
1201195534Sscottl			periph_qual = SID_QUAL(inq_buf);
1202195534Sscottl
1203287289Smav			if (periph_qual == SID_QUAL_LU_CONNECTED ||
1204287289Smav			    periph_qual == SID_QUAL_LU_OFFLINE) {
1205195534Sscottl				u_int8_t len;
1206195534Sscottl
1207195534Sscottl				/*
1208195534Sscottl				 * We conservatively request only
1209195534Sscottl				 * SHORT_INQUIRY_LEN bytes of inquiry
1210195534Sscottl				 * information during our first try
1211195534Sscottl				 * at sending an INQUIRY. If the device
1212195534Sscottl				 * has more information to give,
1213195534Sscottl				 * perform a second request specifying
1214195534Sscottl				 * the amount of information the device
1215195534Sscottl				 * is willing to give.
1216195534Sscottl				 */
1217195534Sscottl				len = inq_buf->additional_length
1218195534Sscottl				    + offsetof(struct scsi_inquiry_data,
1219195534Sscottl                                               additional_length) + 1;
1220195534Sscottl				if (softc->action == PROBE_INQUIRY
1221195534Sscottl				    && len > SHORT_INQUIRY_LENGTH) {
1222195534Sscottl					PROBE_SET_ACTION(softc, PROBE_FULL_INQUIRY);
1223195534Sscottl					xpt_release_ccb(done_ccb);
1224195534Sscottl					xpt_schedule(periph, priority);
1225249466Smav					goto out;
1226195534Sscottl				}
1227195534Sscottl
1228195534Sscottl				scsi_devise_transport(path);
1229208911Smjacob
1230208911Smjacob				if (path->device->lun_id == 0 &&
1231208911Smjacob				    SID_ANSI_REV(inq_buf) > SCSI_REV_SPC2 &&
1232208911Smjacob				    (SCSI_QUIRK(path->device)->quirks &
1233208911Smjacob				     CAM_QUIRK_NORPTLUNS) == 0) {
1234208911Smjacob					PROBE_SET_ACTION(softc,
1235208911Smjacob					    PROBE_REPORT_LUNS);
1236208911Smjacob					/*
1237208911Smjacob					 * Start with room for *one* lun.
1238208911Smjacob					 */
1239208911Smjacob					periph->path->target->rpl_size = 16;
1240208911Smjacob				} else if (INQ_DATA_TQ_ENABLED(inq_buf))
1241208911Smjacob					PROBE_SET_ACTION(softc,
1242208911Smjacob					    PROBE_MODE_SENSE);
1243195534Sscottl				else
1244208911Smjacob					PROBE_SET_ACTION(softc,
1245216088Sken					    PROBE_SUPPORTED_VPD_LIST);
1246195534Sscottl
1247198748Smav				if (path->device->flags & CAM_DEV_UNCONFIGURED) {
1248198748Smav					path->device->flags &= ~CAM_DEV_UNCONFIGURED;
1249198748Smav					xpt_acquire_device(path->device);
1250198748Smav				}
1251195534Sscottl				xpt_release_ccb(done_ccb);
1252195534Sscottl				xpt_schedule(periph, priority);
1253249466Smav				goto out;
1254208911Smjacob			} else if (path->device->lun_id == 0 &&
1255272409Smav			    SID_ANSI_REV(inq_buf) >= SCSI_REV_SPC2 &&
1256208911Smjacob			    (SCSI_QUIRK(path->device)->quirks &
1257208911Smjacob			     CAM_QUIRK_NORPTLUNS) == 0) {
1258208911Smjacob				PROBE_SET_ACTION(softc, PROBE_REPORT_LUNS);
1259208911Smjacob				periph->path->target->rpl_size = 16;
1260208911Smjacob				xpt_release_ccb(done_ccb);
1261208911Smjacob				xpt_schedule(periph, priority);
1262249466Smav				goto out;
1263195534Sscottl			}
1264195534Sscottl		} else if (cam_periph_error(done_ccb, 0,
1265195534Sscottl					    done_ccb->ccb_h.target_lun > 0
1266195534Sscottl					    ? SF_RETRY_UA|SF_QUIET_IR
1267195534Sscottl					    : SF_RETRY_UA,
1268195534Sscottl					    &softc->saved_ccb) == ERESTART) {
1269260547Smav			goto outr;
1270272401Smav		} else {
1271272401Smav			if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
1272272401Smav				/* Don't wedge the queue */
1273272401Smav				xpt_release_devq(done_ccb->ccb_h.path,
1274272401Smav				    /*count*/1, /*run_queue*/TRUE);
1275272401Smav			}
1276272401Smav			path->device->flags &= ~CAM_DEV_INQUIRY_DATA_VALID;
1277195534Sscottl		}
1278195534Sscottl		/*
1279195534Sscottl		 * If we get to this point, we got an error status back
1280195534Sscottl		 * from the inquiry and the error status doesn't require
1281195534Sscottl		 * automatically retrying the command.  Therefore, the
1282195534Sscottl		 * inquiry failed.  If we had inquiry information before
1283195534Sscottl		 * for this device, but this latest inquiry command failed,
1284195534Sscottl		 * the device has probably gone away.  If this device isn't
1285195534Sscottl		 * already marked unconfigured, notify the peripheral
1286195534Sscottl		 * drivers that this device is no more.
1287195534Sscottl		 */
1288195534Sscottl		if ((path->device->flags & CAM_DEV_UNCONFIGURED) == 0)
1289195534Sscottl			/* Send the async notification. */
1290195534Sscottl			xpt_async(AC_LOST_DEVICE, path, NULL);
1291236613Smav		PROBE_SET_ACTION(softc, PROBE_INVALID);
1292195534Sscottl
1293195534Sscottl		xpt_release_ccb(done_ccb);
1294195534Sscottl		break;
1295195534Sscottl	}
1296208911Smjacob	case PROBE_REPORT_LUNS:
1297208911Smjacob	{
1298208911Smjacob		struct ccb_scsiio *csio;
1299208911Smjacob		struct scsi_report_luns_data *lp;
1300208911Smjacob		u_int nlun, maxlun;
1301208911Smjacob
1302208911Smjacob		csio = &done_ccb->csio;
1303208911Smjacob
1304208911Smjacob		lp = (struct scsi_report_luns_data *)csio->data_ptr;
1305208911Smjacob		nlun = scsi_4btoul(lp->length) / 8;
1306208911Smjacob		maxlun = (csio->dxfer_len / 8) - 1;
1307208911Smjacob
1308252382Sscottl		if (cam_ccb_status(done_ccb) != CAM_REQ_CMP) {
1309208911Smjacob			if (cam_periph_error(done_ccb, 0,
1310208911Smjacob			    done_ccb->ccb_h.target_lun > 0 ?
1311208911Smjacob			    SF_RETRY_UA|SF_QUIET_IR : SF_RETRY_UA,
1312208911Smjacob			    &softc->saved_ccb) == ERESTART) {
1313260547Smav				goto outr;
1314208911Smjacob			}
1315208911Smjacob			if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
1316208911Smjacob				xpt_release_devq(done_ccb->ccb_h.path, 1,
1317208911Smjacob				    TRUE);
1318208911Smjacob			}
1319208911Smjacob			free(lp, M_CAMXPT);
1320208911Smjacob			lp = NULL;
1321208911Smjacob		} else if (nlun > maxlun) {
1322208911Smjacob			/*
1323208911Smjacob			 * Reallocate and retry to cover all luns
1324208911Smjacob			 */
1325236613Smav			CAM_DEBUG(path, CAM_DEBUG_PROBE,
1326236613Smav			    ("Probe: reallocating REPORT_LUNS for %u luns\n",
1327236613Smav			     nlun));
1328208911Smjacob			free(lp, M_CAMXPT);
1329208911Smjacob			path->target->rpl_size = (nlun << 3) + 8;
1330208911Smjacob			xpt_release_ccb(done_ccb);
1331208911Smjacob			xpt_schedule(periph, priority);
1332249466Smav			goto out;
1333208911Smjacob		} else if (nlun == 0) {
1334208911Smjacob			/*
1335208911Smjacob			 * If there don't appear to be any luns, bail.
1336208911Smjacob			 */
1337208911Smjacob			free(lp, M_CAMXPT);
1338208911Smjacob			lp = NULL;
1339208911Smjacob		} else {
1340208911Smjacob			lun_id_t lun;
1341208911Smjacob			int idx;
1342208911Smjacob
1343236613Smav			CAM_DEBUG(path, CAM_DEBUG_PROBE,
1344236613Smav			   ("Probe: %u lun(s) reported\n", nlun));
1345208911Smjacob
1346257345Snwhitehorn			CAM_GET_LUN(lp, 0, lun);
1347208911Smjacob			/*
1348208911Smjacob			 * If the first lun is not lun 0, then either there
1349208911Smjacob			 * is no lun 0 in the list, or the list is unsorted.
1350208911Smjacob			 */
1351208911Smjacob			if (lun != 0) {
1352208911Smjacob				for (idx = 0; idx < nlun; idx++) {
1353257345Snwhitehorn					CAM_GET_LUN(lp, idx, lun);
1354208911Smjacob					if (lun == 0) {
1355208911Smjacob						break;
1356208911Smjacob					}
1357208911Smjacob				}
1358208911Smjacob				if (idx != nlun) {
1359208911Smjacob					uint8_t tlun[8];
1360208911Smjacob					memcpy(tlun,
1361208911Smjacob					    lp->luns[0].lundata, 8);
1362208911Smjacob					memcpy(lp->luns[0].lundata,
1363208911Smjacob					    lp->luns[idx].lundata, 8);
1364208911Smjacob					memcpy(lp->luns[idx].lundata,
1365208911Smjacob					    tlun, 8);
1366236613Smav					CAM_DEBUG(path, CAM_DEBUG_PROBE,
1367236613Smav					    ("lun 0 in position %u\n", idx));
1368208911Smjacob				}
1369208911Smjacob			}
1370208911Smjacob			/*
1371208911Smjacob			 * If we have an old lun list, We can either
1372208911Smjacob			 * retest luns that appear to have been dropped,
1373208911Smjacob			 * or just nuke them.  We'll opt for the latter.
1374208911Smjacob			 * This function will also install the new list
1375208911Smjacob			 * in the target structure.
1376208911Smjacob			 */
1377257345Snwhitehorn			probe_purge_old(path, lp, softc->flags);
1378208911Smjacob			lp = NULL;
1379208911Smjacob		}
1380344393Sdab		/* The processing above should either exit via a `goto
1381344393Sdab		 * out` or leave the `lp` variable `NULL` and (if
1382344393Sdab		 * applicable) `free()` the storage to which it had
1383344393Sdab		 * pointed. Assert here that is the case.
1384344393Sdab		 */
1385344393Sdab		KASSERT(lp == NULL, ("%s: lp is not NULL", __func__));
1386287289Smav		inq_buf = &path->device->inq_data;
1387272406Smav		if (path->device->flags & CAM_DEV_INQUIRY_DATA_VALID &&
1388287289Smav		    (SID_QUAL(inq_buf) == SID_QUAL_LU_CONNECTED ||
1389287289Smav		    SID_QUAL(inq_buf) == SID_QUAL_LU_OFFLINE)) {
1390208911Smjacob			if (INQ_DATA_TQ_ENABLED(inq_buf))
1391208911Smjacob				PROBE_SET_ACTION(softc, PROBE_MODE_SENSE);
1392208911Smjacob			else
1393216088Sken				PROBE_SET_ACTION(softc,
1394216088Sken				    PROBE_SUPPORTED_VPD_LIST);
1395208911Smjacob			xpt_release_ccb(done_ccb);
1396208911Smjacob			xpt_schedule(periph, priority);
1397249466Smav			goto out;
1398208911Smjacob		}
1399272406Smav		PROBE_SET_ACTION(softc, PROBE_INVALID);
1400272406Smav		xpt_release_ccb(done_ccb);
1401208911Smjacob		break;
1402208911Smjacob	}
1403195534Sscottl	case PROBE_MODE_SENSE:
1404195534Sscottl	{
1405195534Sscottl		struct ccb_scsiio *csio;
1406195534Sscottl		struct scsi_mode_header_6 *mode_hdr;
1407195534Sscottl
1408195534Sscottl		csio = &done_ccb->csio;
1409195534Sscottl		mode_hdr = (struct scsi_mode_header_6 *)csio->data_ptr;
1410252382Sscottl		if (cam_ccb_status(done_ccb) == CAM_REQ_CMP) {
1411195534Sscottl			struct scsi_control_page *page;
1412195534Sscottl			u_int8_t *offset;
1413195534Sscottl
1414195534Sscottl			offset = ((u_int8_t *)&mode_hdr[1])
1415195534Sscottl			    + mode_hdr->blk_desc_len;
1416195534Sscottl			page = (struct scsi_control_page *)offset;
1417195534Sscottl			path->device->queue_flags = page->queue_flags;
1418195534Sscottl		} else if (cam_periph_error(done_ccb, 0,
1419195534Sscottl					    SF_RETRY_UA|SF_NO_PRINT,
1420195534Sscottl					    &softc->saved_ccb) == ERESTART) {
1421260547Smav			goto outr;
1422195534Sscottl		} else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
1423195534Sscottl			/* Don't wedge the queue */
1424195534Sscottl			xpt_release_devq(done_ccb->ccb_h.path,
1425195534Sscottl					 /*count*/1, /*run_queue*/TRUE);
1426195534Sscottl		}
1427195534Sscottl		xpt_release_ccb(done_ccb);
1428195534Sscottl		free(mode_hdr, M_CAMXPT);
1429216088Sken		PROBE_SET_ACTION(softc, PROBE_SUPPORTED_VPD_LIST);
1430195534Sscottl		xpt_schedule(periph, priority);
1431249466Smav		goto out;
1432195534Sscottl	}
1433216088Sken	case PROBE_SUPPORTED_VPD_LIST:
1434195534Sscottl	{
1435195534Sscottl		struct ccb_scsiio *csio;
1436195534Sscottl		struct scsi_vpd_supported_page_list *page_list;
1437195534Sscottl
1438195534Sscottl		csio = &done_ccb->csio;
1439195534Sscottl		page_list =
1440195534Sscottl		    (struct scsi_vpd_supported_page_list *)csio->data_ptr;
1441195534Sscottl
1442216088Sken		if (path->device->supported_vpds != NULL) {
1443216088Sken			free(path->device->supported_vpds, M_CAMXPT);
1444216088Sken			path->device->supported_vpds = NULL;
1445216088Sken			path->device->supported_vpds_len = 0;
1446216088Sken		}
1447216088Sken
1448195534Sscottl		if (page_list == NULL) {
1449195534Sscottl			/*
1450195534Sscottl			 * Don't process the command as it was never sent
1451195534Sscottl			 */
1452216088Sken		} else if (CCB_COMPLETED_OK(csio->ccb_h)) {
1453216088Sken			/* Got vpd list */
1454216088Sken			path->device->supported_vpds_len = page_list->length +
1455216088Sken			    SVPD_SUPPORTED_PAGES_HDR_LEN;
1456216088Sken			path->device->supported_vpds = (uint8_t *)page_list;
1457216088Sken			xpt_release_ccb(done_ccb);
1458216088Sken			PROBE_SET_ACTION(softc, PROBE_DEVICE_ID);
1459216088Sken			xpt_schedule(periph, priority);
1460249466Smav			goto out;
1461195534Sscottl		} else if (cam_periph_error(done_ccb, 0,
1462195534Sscottl					    SF_RETRY_UA|SF_NO_PRINT,
1463195534Sscottl					    &softc->saved_ccb) == ERESTART) {
1464260547Smav			goto outr;
1465195534Sscottl		} else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
1466195534Sscottl			/* Don't wedge the queue */
1467195534Sscottl			xpt_release_devq(done_ccb->ccb_h.path, /*count*/1,
1468195534Sscottl					 /*run_queue*/TRUE);
1469195534Sscottl		}
1470195534Sscottl
1471216088Sken		if (page_list)
1472195685Semaste			free(page_list, M_CAMXPT);
1473216088Sken		/* No VPDs available, skip to device check. */
1474216088Sken		csio->data_ptr = NULL;
1475216088Sken		goto probe_device_check;
1476216088Sken	}
1477216088Sken	case PROBE_DEVICE_ID:
1478216088Sken	{
1479216088Sken		struct scsi_vpd_device_id *devid;
1480216088Sken		struct ccb_scsiio *csio;
1481216088Sken		uint32_t length = 0;
1482195534Sscottl
1483216088Sken		csio = &done_ccb->csio;
1484216088Sken		devid = (struct scsi_vpd_device_id *)csio->data_ptr;
1485216088Sken
1486216088Sken		/* Clean up from previous instance of this device */
1487216088Sken		if (path->device->device_id != NULL) {
1488216088Sken			path->device->device_id_len = 0;
1489216088Sken			free(path->device->device_id, M_CAMXPT);
1490216088Sken			path->device->device_id = NULL;
1491216088Sken		}
1492216088Sken
1493216088Sken		if (devid == NULL) {
1494216088Sken			/* Don't process the command as it was never sent */
1495216088Sken		} else if (CCB_COMPLETED_OK(csio->ccb_h)) {
1496216088Sken			length = scsi_2btoul(devid->length);
1497216088Sken			if (length != 0) {
1498216088Sken				/*
1499216088Sken				 * NB: device_id_len is actual response
1500216088Sken				 * size, not buffer size.
1501216088Sken				 */
1502216088Sken				path->device->device_id_len = length +
1503216088Sken				    SVPD_DEVICE_ID_HDR_LEN;
1504216088Sken				path->device->device_id = (uint8_t *)devid;
1505216088Sken			}
1506216088Sken		} else if (cam_periph_error(done_ccb, 0,
1507223081Sgibbs					    SF_RETRY_UA,
1508216088Sken					    &softc->saved_ccb) == ERESTART) {
1509260547Smav			goto outr;
1510216088Sken		} else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
1511216088Sken			/* Don't wedge the queue */
1512216088Sken			xpt_release_devq(done_ccb->ccb_h.path, /*count*/1,
1513216088Sken					 /*run_queue*/TRUE);
1514195534Sscottl		}
1515195534Sscottl
1516216088Sken		/* Free the device id space if we don't use it */
1517216088Sken		if (devid && length == 0)
1518216088Sken			free(devid, M_CAMXPT);
1519216088Sken		xpt_release_ccb(done_ccb);
1520278228Sken		PROBE_SET_ACTION(softc, PROBE_EXTENDED_INQUIRY);
1521278228Sken		xpt_schedule(periph, priority);
1522278228Sken		goto out;
1523278228Sken	}
1524278228Sken	case PROBE_EXTENDED_INQUIRY: {
1525278228Sken		struct scsi_vpd_extended_inquiry_data *ext_inq;
1526278228Sken		struct ccb_scsiio *csio;
1527278228Sken		int32_t length = 0;
1528278228Sken
1529278228Sken		csio = &done_ccb->csio;
1530278228Sken		ext_inq = (struct scsi_vpd_extended_inquiry_data *)
1531278228Sken		    csio->data_ptr;
1532278228Sken		if (path->device->ext_inq != NULL) {
1533278228Sken			path->device->ext_inq_len = 0;
1534278228Sken			free(path->device->ext_inq, M_CAMXPT);
1535278228Sken			path->device->ext_inq = NULL;
1536278228Sken		}
1537278228Sken
1538278228Sken		if (ext_inq == NULL) {
1539278228Sken			/* Don't process the command as it was never sent */
1540278228Sken		} else if (CCB_COMPLETED_OK(csio->ccb_h)) {
1541278228Sken			length = scsi_2btoul(ext_inq->page_length) +
1542278228Sken			    __offsetof(struct scsi_vpd_extended_inquiry_data,
1543278228Sken			    flags1);
1544278228Sken			length = min(length, sizeof(*ext_inq));
1545278228Sken			length -= csio->resid;
1546278228Sken			if (length > 0) {
1547278228Sken				path->device->ext_inq_len = length;
1548278228Sken				path->device->ext_inq = (uint8_t *)ext_inq;
1549278228Sken			}
1550278228Sken		} else if (cam_periph_error(done_ccb, 0,
1551278228Sken					    SF_RETRY_UA,
1552278228Sken					    &softc->saved_ccb) == ERESTART) {
1553295417Sken			goto outr;
1554278228Sken		} else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
1555278228Sken			/* Don't wedge the queue */
1556278228Sken			xpt_release_devq(done_ccb->ccb_h.path, /*count*/1,
1557278228Sken					 /*run_queue*/TRUE);
1558278228Sken		}
1559278228Sken
1560278228Sken		/* Free the device id space if we don't use it */
1561278228Sken		if (ext_inq && length <= 0)
1562278228Sken			free(ext_inq, M_CAMXPT);
1563278228Sken		xpt_release_ccb(done_ccb);
1564216088Sken		PROBE_SET_ACTION(softc, PROBE_SERIAL_NUM);
1565216088Sken		xpt_schedule(periph, priority);
1566249466Smav		goto out;
1567195534Sscottl	}
1568195534Sscottl
1569216088Skenprobe_device_check:
1570216088Sken	case PROBE_SERIAL_NUM:
1571195534Sscottl	{
1572195534Sscottl		struct ccb_scsiio *csio;
1573195534Sscottl		struct scsi_vpd_unit_serial_number *serial_buf;
1574195534Sscottl		u_int32_t  priority;
1575195534Sscottl		int changed;
1576195534Sscottl		int have_serialnum;
1577195534Sscottl
1578195534Sscottl		changed = 1;
1579195534Sscottl		have_serialnum = 0;
1580195534Sscottl		csio = &done_ccb->csio;
1581195534Sscottl		priority = done_ccb->ccb_h.pinfo.priority;
1582195534Sscottl		serial_buf =
1583195534Sscottl		    (struct scsi_vpd_unit_serial_number *)csio->data_ptr;
1584195534Sscottl
1585195534Sscottl		if (serial_buf == NULL) {
1586195534Sscottl			/*
1587195534Sscottl			 * Don't process the command as it was never sent
1588195534Sscottl			 */
1589252382Sscottl		} else if (cam_ccb_status(done_ccb) == CAM_REQ_CMP
1590195534Sscottl			&& (serial_buf->length > 0)) {
1591195534Sscottl
1592195534Sscottl			have_serialnum = 1;
1593195534Sscottl			path->device->serial_num =
1594195534Sscottl				(u_int8_t *)malloc((serial_buf->length + 1),
1595195534Sscottl						   M_CAMXPT, M_NOWAIT);
1596195534Sscottl			if (path->device->serial_num != NULL) {
1597300880Sasomers				int start, slen;
1598300880Sasomers
1599300880Sasomers				start = strspn(serial_buf->serial_num, " ");
1600300880Sasomers				slen = serial_buf->length - start;
1601300880Sasomers				if (slen <= 0) {
1602350783Smav					/*
1603300880Sasomers					 * SPC5r05 says that an all-space serial
1604300880Sasomers					 * number means no product serial number
1605300880Sasomers					 * is available
1606300880Sasomers					 */
1607300880Sasomers					slen = 0;
1608300880Sasomers				}
1609223081Sgibbs				memcpy(path->device->serial_num,
1610300880Sasomers				       &serial_buf->serial_num[start], slen);
1611300880Sasomers				path->device->serial_num_len = slen;
1612300880Sasomers				path->device->serial_num[slen] = '\0';
1613195534Sscottl			}
1614195534Sscottl		} else if (cam_periph_error(done_ccb, 0,
1615195534Sscottl					    SF_RETRY_UA|SF_NO_PRINT,
1616195534Sscottl					    &softc->saved_ccb) == ERESTART) {
1617260547Smav			goto outr;
1618195534Sscottl		} else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
1619195534Sscottl			/* Don't wedge the queue */
1620195534Sscottl			xpt_release_devq(done_ccb->ccb_h.path, /*count*/1,
1621195534Sscottl					 /*run_queue*/TRUE);
1622195534Sscottl		}
1623195534Sscottl
1624195534Sscottl		/*
1625195534Sscottl		 * Let's see if we have seen this device before.
1626195534Sscottl		 */
1627195534Sscottl		if ((softc->flags & PROBE_INQUIRY_CKSUM) != 0) {
1628195534Sscottl			MD5_CTX context;
1629195534Sscottl			u_int8_t digest[16];
1630195534Sscottl
1631195534Sscottl			MD5Init(&context);
1632195534Sscottl
1633195534Sscottl			MD5Update(&context,
1634195534Sscottl				  (unsigned char *)&path->device->inq_data,
1635195534Sscottl				  sizeof(struct scsi_inquiry_data));
1636195534Sscottl
1637195534Sscottl			if (have_serialnum)
1638309273Sasomers				MD5Update(&context, path->device->serial_num,
1639309273Sasomers					  path->device->serial_num_len);
1640195534Sscottl
1641195534Sscottl			MD5Final(digest, &context);
1642195534Sscottl			if (bcmp(softc->digest, digest, 16) == 0)
1643195534Sscottl				changed = 0;
1644195534Sscottl
1645195534Sscottl			/*
1646195534Sscottl			 * XXX Do we need to do a TUR in order to ensure
1647195534Sscottl			 *     that the device really hasn't changed???
1648195534Sscottl			 */
1649195534Sscottl			if ((changed != 0)
1650195534Sscottl			 && ((softc->flags & PROBE_NO_ANNOUNCE) == 0))
1651195534Sscottl				xpt_async(AC_LOST_DEVICE, path, NULL);
1652195534Sscottl		}
1653195534Sscottl		if (serial_buf != NULL)
1654195534Sscottl			free(serial_buf, M_CAMXPT);
1655195534Sscottl
1656195534Sscottl		if (changed != 0) {
1657195534Sscottl			/*
1658195534Sscottl			 * Now that we have all the necessary
1659195534Sscottl			 * information to safely perform transfer
1660195534Sscottl			 * negotiations... Controllers don't perform
1661195534Sscottl			 * any negotiation or tagged queuing until
1662195534Sscottl			 * after the first XPT_SET_TRAN_SETTINGS ccb is
1663195534Sscottl			 * received.  So, on a new device, just retrieve
1664195534Sscottl			 * the user settings, and set them as the current
1665195534Sscottl			 * settings to set the device up.
1666195534Sscottl			 */
1667195534Sscottl			proberequestdefaultnegotiation(periph);
1668195534Sscottl			xpt_release_ccb(done_ccb);
1669195534Sscottl
1670195534Sscottl			/*
1671195534Sscottl			 * Perform a TUR to allow the controller to
1672195534Sscottl			 * perform any necessary transfer negotiation.
1673195534Sscottl			 */
1674195534Sscottl			PROBE_SET_ACTION(softc, PROBE_TUR_FOR_NEGOTIATION);
1675195534Sscottl			xpt_schedule(periph, priority);
1676249466Smav			goto out;
1677195534Sscottl		}
1678195534Sscottl		xpt_release_ccb(done_ccb);
1679195534Sscottl		break;
1680195534Sscottl	}
1681195534Sscottl	case PROBE_TUR_FOR_NEGOTIATION:
1682236814Smav	case PROBE_DV_EXIT:
1683252382Sscottl		if (cam_ccb_status(done_ccb) != CAM_REQ_CMP) {
1684351746Smav			if (cam_periph_error(done_ccb, 0, SF_NO_PRINT |
1685351746Smav			    SF_NO_RECOVERY | SF_NO_RETRY, NULL) == ERESTART)
1686351746Smav				goto outr;
1687195534Sscottl		}
1688195534Sscottl		if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
1689195534Sscottl			/* Don't wedge the queue */
1690195534Sscottl			xpt_release_devq(done_ccb->ccb_h.path, /*count*/1,
1691195534Sscottl					 /*run_queue*/TRUE);
1692195534Sscottl		}
1693195534Sscottl		/*
1694195534Sscottl		 * Do Domain Validation for lun 0 on devices that claim
1695195534Sscottl		 * to support Synchronous Transfer modes.
1696195534Sscottl		 */
1697195534Sscottl	 	if (softc->action == PROBE_TUR_FOR_NEGOTIATION
1698195534Sscottl		 && done_ccb->ccb_h.target_lun == 0
1699195534Sscottl		 && (path->device->inq_data.flags & SID_Sync) != 0
1700195534Sscottl                 && (path->device->flags & CAM_DEV_IN_DV) == 0) {
1701236613Smav			CAM_DEBUG(periph->path, CAM_DEBUG_PROBE,
1702195534Sscottl			    ("Begin Domain Validation\n"));
1703195534Sscottl			path->device->flags |= CAM_DEV_IN_DV;
1704195534Sscottl			xpt_release_ccb(done_ccb);
1705195534Sscottl			PROBE_SET_ACTION(softc, PROBE_INQUIRY_BASIC_DV1);
1706195534Sscottl			xpt_schedule(periph, priority);
1707249466Smav			goto out;
1708195534Sscottl		}
1709195534Sscottl		if (softc->action == PROBE_DV_EXIT) {
1710236613Smav			CAM_DEBUG(periph->path, CAM_DEBUG_PROBE,
1711195534Sscottl			    ("Leave Domain Validation\n"));
1712195534Sscottl		}
1713198748Smav		if (path->device->flags & CAM_DEV_UNCONFIGURED) {
1714198748Smav			path->device->flags &= ~CAM_DEV_UNCONFIGURED;
1715198748Smav			xpt_acquire_device(path->device);
1716198748Smav		}
1717195534Sscottl		path->device->flags &=
1718198748Smav		    ~(CAM_DEV_IN_DV|CAM_DEV_DV_HIT_BOTTOM);
1719195534Sscottl		if ((softc->flags & PROBE_NO_ANNOUNCE) == 0) {
1720195534Sscottl			/* Inform the XPT that a new device has been found */
1721195534Sscottl			done_ccb->ccb_h.func_code = XPT_GDEV_TYPE;
1722195534Sscottl			xpt_action(done_ccb);
1723195534Sscottl			xpt_async(AC_FOUND_DEVICE, done_ccb->ccb_h.path,
1724195534Sscottl				  done_ccb);
1725195534Sscottl		}
1726236613Smav		PROBE_SET_ACTION(softc, PROBE_DONE);
1727195534Sscottl		xpt_release_ccb(done_ccb);
1728195534Sscottl		break;
1729195534Sscottl	case PROBE_INQUIRY_BASIC_DV1:
1730195534Sscottl	case PROBE_INQUIRY_BASIC_DV2:
1731195534Sscottl	{
1732195534Sscottl		struct scsi_inquiry_data *nbuf;
1733195534Sscottl		struct ccb_scsiio *csio;
1734195534Sscottl
1735252382Sscottl		if (cam_ccb_status(done_ccb) != CAM_REQ_CMP) {
1736351746Smav			if (cam_periph_error(done_ccb, 0, SF_NO_PRINT |
1737351746Smav			    SF_NO_RECOVERY | SF_NO_RETRY, NULL) == ERESTART)
1738351746Smav				goto outr;
1739236814Smav		}
1740195534Sscottl		if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
1741195534Sscottl			/* Don't wedge the queue */
1742195534Sscottl			xpt_release_devq(done_ccb->ccb_h.path, /*count*/1,
1743195534Sscottl					 /*run_queue*/TRUE);
1744195534Sscottl		}
1745195534Sscottl		csio = &done_ccb->csio;
1746195534Sscottl		nbuf = (struct scsi_inquiry_data *)csio->data_ptr;
1747195534Sscottl		if (bcmp(nbuf, &path->device->inq_data, SHORT_INQUIRY_LENGTH)) {
1748195534Sscottl			xpt_print(path,
1749195534Sscottl			    "inquiry data fails comparison at DV%d step\n",
1750195534Sscottl			    softc->action == PROBE_INQUIRY_BASIC_DV1 ? 1 : 2);
1751195534Sscottl			if (proberequestbackoff(periph, path->device)) {
1752195534Sscottl				path->device->flags &= ~CAM_DEV_IN_DV;
1753195534Sscottl				PROBE_SET_ACTION(softc, PROBE_TUR_FOR_NEGOTIATION);
1754195534Sscottl			} else {
1755195534Sscottl				/* give up */
1756195534Sscottl				PROBE_SET_ACTION(softc, PROBE_DV_EXIT);
1757195534Sscottl			}
1758195534Sscottl			free(nbuf, M_CAMXPT);
1759195534Sscottl			xpt_release_ccb(done_ccb);
1760195534Sscottl			xpt_schedule(periph, priority);
1761249466Smav			goto out;
1762195534Sscottl		}
1763195534Sscottl		free(nbuf, M_CAMXPT);
1764195534Sscottl		if (softc->action == PROBE_INQUIRY_BASIC_DV1) {
1765195534Sscottl			PROBE_SET_ACTION(softc, PROBE_INQUIRY_BASIC_DV2);
1766195534Sscottl			xpt_release_ccb(done_ccb);
1767195534Sscottl			xpt_schedule(periph, priority);
1768249466Smav			goto out;
1769195534Sscottl		}
1770195534Sscottl		if (softc->action == PROBE_INQUIRY_BASIC_DV2) {
1771236613Smav			CAM_DEBUG(periph->path, CAM_DEBUG_PROBE,
1772195534Sscottl			    ("Leave Domain Validation Successfully\n"));
1773195534Sscottl		}
1774198748Smav		if (path->device->flags & CAM_DEV_UNCONFIGURED) {
1775198748Smav			path->device->flags &= ~CAM_DEV_UNCONFIGURED;
1776198748Smav			xpt_acquire_device(path->device);
1777198748Smav		}
1778195534Sscottl		path->device->flags &=
1779198748Smav		    ~(CAM_DEV_IN_DV|CAM_DEV_DV_HIT_BOTTOM);
1780195534Sscottl		if ((softc->flags & PROBE_NO_ANNOUNCE) == 0) {
1781195534Sscottl			/* Inform the XPT that a new device has been found */
1782195534Sscottl			done_ccb->ccb_h.func_code = XPT_GDEV_TYPE;
1783195534Sscottl			xpt_action(done_ccb);
1784195534Sscottl			xpt_async(AC_FOUND_DEVICE, done_ccb->ccb_h.path,
1785195534Sscottl				  done_ccb);
1786195534Sscottl		}
1787236613Smav		PROBE_SET_ACTION(softc, PROBE_DONE);
1788195534Sscottl		xpt_release_ccb(done_ccb);
1789195534Sscottl		break;
1790195534Sscottl	}
1791195534Sscottl	default:
1792236613Smav		panic("probedone: invalid action state 0x%x\n", softc->action);
1793195534Sscottl	}
1794195534Sscottl	done_ccb = (union ccb *)TAILQ_FIRST(&softc->request_ccbs);
1795195534Sscottl	TAILQ_REMOVE(&softc->request_ccbs, &done_ccb->ccb_h, periph_links.tqe);
1796195534Sscottl	done_ccb->ccb_h.status = CAM_REQ_CMP;
1797195534Sscottl	xpt_done(done_ccb);
1798195534Sscottl	if (TAILQ_FIRST(&softc->request_ccbs) == NULL) {
1799236613Smav		CAM_DEBUG(periph->path, CAM_DEBUG_PROBE, ("Probe completed\n"));
1800249466Smav		/* Drop freeze taken due to CAM_DEV_QFREEZE flag set. */
1801249466Smav		cam_release_devq(path, 0, 0, 0, FALSE);
1802260541Smav		cam_periph_release_locked(periph);
1803236228Smav		cam_periph_invalidate(periph);
1804195534Sscottl		cam_periph_release_locked(periph);
1805195534Sscottl	} else {
1806195534Sscottl		probeschedule(periph);
1807249466Smav		goto out;
1808195534Sscottl	}
1809195534Sscottl}
1810195534Sscottl
1811195534Sscottlstatic void
1812257345Snwhitehornprobe_purge_old(struct cam_path *path, struct scsi_report_luns_data *new,
1813257345Snwhitehorn    probe_flags flags)
1814208911Smjacob{
1815208911Smjacob	struct cam_path *tp;
1816208911Smjacob	struct scsi_report_luns_data *old;
1817257345Snwhitehorn	u_int idx1, idx2, nlun_old, nlun_new;
1818257345Snwhitehorn	lun_id_t this_lun;
1819208911Smjacob	u_int8_t *ol, *nl;
1820208911Smjacob
1821208911Smjacob	if (path->target == NULL) {
1822208911Smjacob		return;
1823208911Smjacob	}
1824256843Smav	mtx_lock(&path->target->luns_mtx);
1825256843Smav	old = path->target->luns;
1826256843Smav	path->target->luns = new;
1827256843Smav	mtx_unlock(&path->target->luns_mtx);
1828256843Smav	if (old == NULL)
1829208911Smjacob		return;
1830208911Smjacob	nlun_old = scsi_4btoul(old->length) / 8;
1831208911Smjacob	nlun_new = scsi_4btoul(new->length) / 8;
1832208911Smjacob
1833208911Smjacob	/*
1834208911Smjacob	 * We are not going to assume sorted lists. Deal.
1835208911Smjacob	 */
1836208911Smjacob	for (idx1 = 0; idx1 < nlun_old; idx1++) {
1837208911Smjacob		ol = old->luns[idx1].lundata;
1838208911Smjacob		for (idx2 = 0; idx2 < nlun_new; idx2++) {
1839208911Smjacob			nl = new->luns[idx2].lundata;
1840208911Smjacob			if (memcmp(nl, ol, 8) == 0) {
1841208911Smjacob				break;
1842208911Smjacob			}
1843208911Smjacob		}
1844208911Smjacob		if (idx2 < nlun_new) {
1845208911Smjacob			continue;
1846208911Smjacob		}
1847208911Smjacob		/*
1848208911Smjacob		 * An 'old' item not in the 'new' list.
1849208911Smjacob		 * Nuke it. Except that if it is lun 0,
1850208911Smjacob		 * that would be what the probe state
1851208911Smjacob		 * machine is currently working on,
1852208911Smjacob		 * so we won't do that.
1853208911Smjacob		 */
1854257345Snwhitehorn		CAM_GET_LUN(old, idx1, this_lun);
1855257345Snwhitehorn		if (this_lun == 0) {
1856208911Smjacob			continue;
1857208911Smjacob		}
1858257345Snwhitehorn
1859257345Snwhitehorn		/*
1860257345Snwhitehorn		 * We also cannot nuke it if it is
1861257345Snwhitehorn		 * not in a lun format we understand
1862257345Snwhitehorn		 * and replace the LUN with a "simple" LUN
1863257345Snwhitehorn		 * if that is all the HBA supports.
1864257345Snwhitehorn		 */
1865257345Snwhitehorn		if (!(flags & PROBE_EXTLUN)) {
1866257345Snwhitehorn			if (!CAM_CAN_GET_SIMPLE_LUN(old, idx1))
1867257345Snwhitehorn				continue;
1868257345Snwhitehorn			CAM_GET_SIMPLE_LUN(old, idx1, this_lun);
1869257345Snwhitehorn		}
1870257345Snwhitehorn
1871208911Smjacob		if (xpt_create_path(&tp, NULL, xpt_path_path_id(path),
1872208911Smjacob		    xpt_path_target_id(path), this_lun) == CAM_REQ_CMP) {
1873208911Smjacob			xpt_async(AC_LOST_DEVICE, tp, NULL);
1874208911Smjacob			xpt_free_path(tp);
1875208911Smjacob		}
1876208911Smjacob	}
1877208911Smjacob	free(old, M_CAMXPT);
1878208911Smjacob}
1879208911Smjacob
1880208911Smjacobstatic void
1881195534Sscottlprobecleanup(struct cam_periph *periph)
1882195534Sscottl{
1883195534Sscottl	free(periph->softc, M_CAMXPT);
1884195534Sscottl}
1885195534Sscottl
1886195534Sscottlstatic void
1887195534Sscottlscsi_find_quirk(struct cam_ed *device)
1888195534Sscottl{
1889195534Sscottl	struct scsi_quirk_entry *quirk;
1890195534Sscottl	caddr_t	match;
1891195534Sscottl
1892195534Sscottl	match = cam_quirkmatch((caddr_t)&device->inq_data,
1893195534Sscottl			       (caddr_t)scsi_quirk_table,
1894298431Spfg			       nitems(scsi_quirk_table),
1895195534Sscottl			       sizeof(*scsi_quirk_table), scsi_inquiry_match);
1896195534Sscottl
1897195534Sscottl	if (match == NULL)
1898195534Sscottl		panic("xpt_find_quirk: device didn't match wildcard entry!!");
1899195534Sscottl
1900195534Sscottl	quirk = (struct scsi_quirk_entry *)match;
1901195534Sscottl	device->quirk = quirk;
1902195534Sscottl	device->mintags = quirk->mintags;
1903195534Sscottl	device->maxtags = quirk->maxtags;
1904195534Sscottl}
1905195534Sscottl
1906195534Sscottlstatic int
1907195534Sscottlsysctl_cam_search_luns(SYSCTL_HANDLER_ARGS)
1908195534Sscottl{
1909228442Smdf	int error, val;
1910195534Sscottl
1911228442Smdf	val = cam_srch_hi;
1912228442Smdf	error = sysctl_handle_int(oidp, &val, 0, req);
1913195534Sscottl	if (error != 0 || req->newptr == NULL)
1914195534Sscottl		return (error);
1915228442Smdf	if (val == 0 || val == 1) {
1916228442Smdf		cam_srch_hi = val;
1917195534Sscottl		return (0);
1918195534Sscottl	} else {
1919195534Sscottl		return (EINVAL);
1920195534Sscottl	}
1921195534Sscottl}
1922195534Sscottl
1923195534Sscottltypedef struct {
1924195534Sscottl	union	ccb *request_ccb;
1925195534Sscottl	struct 	ccb_pathinq *cpi;
1926195534Sscottl	int	counter;
1927208911Smjacob	int	lunindex[0];
1928195534Sscottl} scsi_scan_bus_info;
1929195534Sscottl
1930195534Sscottl/*
1931195534Sscottl * To start a scan, request_ccb is an XPT_SCAN_BUS ccb.
1932195688Semaste * As the scan progresses, scsi_scan_bus is used as the
1933195534Sscottl * callback on completion function.
1934195534Sscottl */
1935195534Sscottlstatic void
1936195534Sscottlscsi_scan_bus(struct cam_periph *periph, union ccb *request_ccb)
1937195534Sscottl{
1938256843Smav	struct mtx *mtx;
1939256843Smav
1940195534Sscottl	CAM_DEBUG(request_ccb->ccb_h.path, CAM_DEBUG_TRACE,
1941195688Semaste		  ("scsi_scan_bus\n"));
1942195534Sscottl	switch (request_ccb->ccb_h.func_code) {
1943195534Sscottl	case XPT_SCAN_BUS:
1944208582Smjacob	case XPT_SCAN_TGT:
1945195534Sscottl	{
1946195534Sscottl		scsi_scan_bus_info *scan_info;
1947203108Smav		union	ccb *work_ccb, *reset_ccb;
1948195534Sscottl		struct	cam_path *path;
1949195534Sscottl		u_int	i;
1950208582Smjacob		u_int	low_target, max_target;
1951195534Sscottl		u_int	initiator_id;
1952195534Sscottl
1953195534Sscottl		/* Find out the characteristics of the bus */
1954195534Sscottl		work_ccb = xpt_alloc_ccb_nowait();
1955195534Sscottl		if (work_ccb == NULL) {
1956195534Sscottl			request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
1957195534Sscottl			xpt_done(request_ccb);
1958195534Sscottl			return;
1959195534Sscottl		}
1960195534Sscottl		xpt_setup_ccb(&work_ccb->ccb_h, request_ccb->ccb_h.path,
1961195534Sscottl			      request_ccb->ccb_h.pinfo.priority);
1962195534Sscottl		work_ccb->ccb_h.func_code = XPT_PATH_INQ;
1963195534Sscottl		xpt_action(work_ccb);
1964195534Sscottl		if (work_ccb->ccb_h.status != CAM_REQ_CMP) {
1965195534Sscottl			request_ccb->ccb_h.status = work_ccb->ccb_h.status;
1966195534Sscottl			xpt_free_ccb(work_ccb);
1967195534Sscottl			xpt_done(request_ccb);
1968195534Sscottl			return;
1969195534Sscottl		}
1970195534Sscottl
1971195534Sscottl		if ((work_ccb->cpi.hba_misc & PIM_NOINITIATOR) != 0) {
1972195534Sscottl			/*
1973195534Sscottl			 * Can't scan the bus on an adapter that
1974195534Sscottl			 * cannot perform the initiator role.
1975195534Sscottl			 */
1976195534Sscottl			request_ccb->ccb_h.status = CAM_REQ_CMP;
1977195534Sscottl			xpt_free_ccb(work_ccb);
1978195534Sscottl			xpt_done(request_ccb);
1979195534Sscottl			return;
1980195534Sscottl		}
1981195534Sscottl
1982203108Smav		/* We may need to reset bus first, if we haven't done it yet. */
1983203108Smav		if ((work_ccb->cpi.hba_inquiry &
1984203108Smav		    (PI_WIDE_32|PI_WIDE_16|PI_SDTR_ABLE)) &&
1985203108Smav		    !(work_ccb->cpi.hba_misc & PIM_NOBUSRESET) &&
1986253370Smav		    !timevalisset(&request_ccb->ccb_h.path->bus->last_reset) &&
1987253370Smav		    (reset_ccb = xpt_alloc_ccb_nowait()) != NULL) {
1988203108Smav			xpt_setup_ccb(&reset_ccb->ccb_h, request_ccb->ccb_h.path,
1989203108Smav			      CAM_PRIORITY_NONE);
1990203108Smav			reset_ccb->ccb_h.func_code = XPT_RESET_BUS;
1991203108Smav			xpt_action(reset_ccb);
1992203108Smav			if (reset_ccb->ccb_h.status != CAM_REQ_CMP) {
1993203108Smav				request_ccb->ccb_h.status = reset_ccb->ccb_h.status;
1994203108Smav				xpt_free_ccb(reset_ccb);
1995203108Smav				xpt_free_ccb(work_ccb);
1996203108Smav				xpt_done(request_ccb);
1997203108Smav				return;
1998203108Smav			}
1999203108Smav			xpt_free_ccb(reset_ccb);
2000203108Smav		}
2001203108Smav
2002195534Sscottl		/* Save some state for use while we probe for devices */
2003208911Smjacob		scan_info = (scsi_scan_bus_info *) malloc(sizeof(scsi_scan_bus_info) +
2004208911Smjacob		    (work_ccb->cpi.max_target * sizeof (u_int)), M_CAMXPT, M_ZERO|M_NOWAIT);
2005195534Sscottl		if (scan_info == NULL) {
2006195534Sscottl			request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
2007256843Smav			xpt_free_ccb(work_ccb);
2008195534Sscottl			xpt_done(request_ccb);
2009195534Sscottl			return;
2010195534Sscottl		}
2011236613Smav		CAM_DEBUG(request_ccb->ccb_h.path, CAM_DEBUG_TRACE,
2012208911Smjacob		   ("SCAN start for %p\n", scan_info));
2013195534Sscottl		scan_info->request_ccb = request_ccb;
2014195534Sscottl		scan_info->cpi = &work_ccb->cpi;
2015195534Sscottl
2016195534Sscottl		/* Cache on our stack so we can work asynchronously */
2017195534Sscottl		max_target = scan_info->cpi->max_target;
2018208582Smjacob		low_target = 0;
2019195534Sscottl		initiator_id = scan_info->cpi->initiator_id;
2020195534Sscottl
2021195534Sscottl
2022195534Sscottl		/*
2023195534Sscottl		 * We can scan all targets in parallel, or do it sequentially.
2024195534Sscottl		 */
2025208582Smjacob
2026208582Smjacob		if (request_ccb->ccb_h.func_code == XPT_SCAN_TGT) {
2027208582Smjacob			max_target = low_target = request_ccb->ccb_h.target_id;
2028208582Smjacob			scan_info->counter = 0;
2029208582Smjacob		} else if (scan_info->cpi->hba_misc & PIM_SEQSCAN) {
2030195534Sscottl			max_target = 0;
2031195534Sscottl			scan_info->counter = 0;
2032195534Sscottl		} else {
2033195534Sscottl			scan_info->counter = scan_info->cpi->max_target + 1;
2034195534Sscottl			if (scan_info->cpi->initiator_id < scan_info->counter) {
2035195534Sscottl				scan_info->counter--;
2036195534Sscottl			}
2037195534Sscottl		}
2038256843Smav		mtx = xpt_path_mtx(scan_info->request_ccb->ccb_h.path);
2039256843Smav		mtx_unlock(mtx);
2040195534Sscottl
2041208582Smjacob		for (i = low_target; i <= max_target; i++) {
2042195534Sscottl			cam_status status;
2043195534Sscottl			if (i == initiator_id)
2044195534Sscottl				continue;
2045195534Sscottl
2046249468Smav			status = xpt_create_path(&path, NULL,
2047195534Sscottl						 request_ccb->ccb_h.path_id,
2048195534Sscottl						 i, 0);
2049195534Sscottl			if (status != CAM_REQ_CMP) {
2050195688Semaste				printf("scsi_scan_bus: xpt_create_path failed"
2051195534Sscottl				       " with status %#x, bus scan halted\n",
2052195534Sscottl				       status);
2053195534Sscottl				free(scan_info, M_CAMXPT);
2054195534Sscottl				request_ccb->ccb_h.status = status;
2055195534Sscottl				xpt_free_ccb(work_ccb);
2056195534Sscottl				xpt_done(request_ccb);
2057195534Sscottl				break;
2058195534Sscottl			}
2059195534Sscottl			work_ccb = xpt_alloc_ccb_nowait();
2060195534Sscottl			if (work_ccb == NULL) {
2061195685Semaste				xpt_free_ccb((union ccb *)scan_info->cpi);
2062195534Sscottl				free(scan_info, M_CAMXPT);
2063195534Sscottl				xpt_free_path(path);
2064195534Sscottl				request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
2065195534Sscottl				xpt_done(request_ccb);
2066195534Sscottl				break;
2067195534Sscottl			}
2068195534Sscottl			xpt_setup_ccb(&work_ccb->ccb_h, path,
2069195534Sscottl				      request_ccb->ccb_h.pinfo.priority);
2070195534Sscottl			work_ccb->ccb_h.func_code = XPT_SCAN_LUN;
2071195534Sscottl			work_ccb->ccb_h.cbfcnp = scsi_scan_bus;
2072256843Smav			work_ccb->ccb_h.flags |= CAM_UNLOCKED;
2073195534Sscottl			work_ccb->ccb_h.ppriv_ptr0 = scan_info;
2074195534Sscottl			work_ccb->crcn.flags = request_ccb->crcn.flags;
2075195534Sscottl			xpt_action(work_ccb);
2076195534Sscottl		}
2077256843Smav
2078256843Smav		mtx_lock(mtx);
2079195534Sscottl		break;
2080195534Sscottl	}
2081195534Sscottl	case XPT_SCAN_LUN:
2082195534Sscottl	{
2083195534Sscottl		cam_status status;
2084208911Smjacob		struct cam_path *path, *oldpath;
2085195534Sscottl		scsi_scan_bus_info *scan_info;
2086208911Smjacob		struct cam_et *target;
2087272401Smav		struct cam_ed *device, *nextdev;
2088208911Smjacob		int next_target;
2089195534Sscottl		path_id_t path_id;
2090195534Sscottl		target_id_t target_id;
2091195534Sscottl		lun_id_t lun_id;
2092195534Sscottl
2093208911Smjacob		oldpath = request_ccb->ccb_h.path;
2094208911Smjacob
2095252382Sscottl		status = cam_ccb_status(request_ccb);
2096195534Sscottl		scan_info = (scsi_scan_bus_info *)request_ccb->ccb_h.ppriv_ptr0;
2097195534Sscottl		path_id = request_ccb->ccb_h.path_id;
2098195534Sscottl		target_id = request_ccb->ccb_h.target_id;
2099195534Sscottl		lun_id = request_ccb->ccb_h.target_lun;
2100208911Smjacob		target = request_ccb->ccb_h.path->target;
2101208911Smjacob		next_target = 1;
2102208911Smjacob
2103256843Smav		mtx = xpt_path_mtx(scan_info->request_ccb->ccb_h.path);
2104256843Smav		mtx_lock(mtx);
2105256843Smav		mtx_lock(&target->luns_mtx);
2106208911Smjacob		if (target->luns) {
2107257345Snwhitehorn			lun_id_t first;
2108208911Smjacob			u_int nluns = scsi_4btoul(target->luns->length) / 8;
2109208911Smjacob
2110208911Smjacob			/*
2111208911Smjacob			 * Make sure we skip over lun 0 if it's the first member
2112208911Smjacob			 * of the list as we've actually just finished probing
2113208911Smjacob			 * it.
2114208911Smjacob			 */
2115257345Snwhitehorn			CAM_GET_LUN(target->luns, 0, first);
2116208911Smjacob			if (first == 0 && scan_info->lunindex[target_id] == 0) {
2117208911Smjacob				scan_info->lunindex[target_id]++;
2118350783Smav			}
2119208911Smjacob
2120257345Snwhitehorn			/*
2121257345Snwhitehorn			 * Skip any LUNs that the HBA can't deal with.
2122257345Snwhitehorn			 */
2123257345Snwhitehorn			while (scan_info->lunindex[target_id] < nluns) {
2124257345Snwhitehorn				if (scan_info->cpi->hba_misc & PIM_EXTLUNS) {
2125257345Snwhitehorn					CAM_GET_LUN(target->luns,
2126257345Snwhitehorn					    scan_info->lunindex[target_id],
2127257345Snwhitehorn					    lun_id);
2128257345Snwhitehorn					break;
2129257345Snwhitehorn				}
2130257345Snwhitehorn
2131257345Snwhitehorn				if (CAM_CAN_GET_SIMPLE_LUN(target->luns,
2132257345Snwhitehorn				    scan_info->lunindex[target_id])) {
2133257345Snwhitehorn					CAM_GET_SIMPLE_LUN(target->luns,
2134257345Snwhitehorn					    scan_info->lunindex[target_id],
2135257345Snwhitehorn					    lun_id);
2136257345Snwhitehorn					break;
2137257345Snwhitehorn				}
2138257345Snwhitehorn
2139257345Snwhitehorn				scan_info->lunindex[target_id]++;
2140257345Snwhitehorn			}
2141257345Snwhitehorn
2142208911Smjacob			if (scan_info->lunindex[target_id] < nluns) {
2143256843Smav				mtx_unlock(&target->luns_mtx);
2144208911Smjacob				next_target = 0;
2145236613Smav				CAM_DEBUG(request_ccb->ccb_h.path,
2146236613Smav				    CAM_DEBUG_PROBE,
2147257345Snwhitehorn				   ("next lun to try at index %u is %jx\n",
2148257345Snwhitehorn				   scan_info->lunindex[target_id],
2149257345Snwhitehorn				   (uintmax_t)lun_id));
2150208911Smjacob				scan_info->lunindex[target_id]++;
2151208911Smjacob			} else {
2152256843Smav				mtx_unlock(&target->luns_mtx);
2153274756Smav				/* We're done with scanning all luns. */
2154208911Smjacob			}
2155256843Smav		} else {
2156272401Smav			mtx_unlock(&target->luns_mtx);
2157195534Sscottl			device = request_ccb->ccb_h.path->device;
2158272401Smav			/* Continue sequential LUN scan if: */
2159272401Smav			/*  -- we have more LUNs that need recheck */
2160272401Smav			mtx_lock(&target->bus->eb_mtx);
2161272401Smav			nextdev = device;
2162272401Smav			while ((nextdev = TAILQ_NEXT(nextdev, links)) != NULL)
2163272401Smav				if ((nextdev->flags & CAM_DEV_UNCONFIGURED) == 0)
2164272401Smav					break;
2165272401Smav			mtx_unlock(&target->bus->eb_mtx);
2166272401Smav			if (nextdev != NULL) {
2167272401Smav				next_target = 0;
2168272402Smav			/*  -- stop if CAM_QUIRK_NOLUNS is set. */
2169272402Smav			} else if (SCSI_QUIRK(device)->quirks & CAM_QUIRK_NOLUNS) {
2170272402Smav				next_target = 1;
2171272401Smav			/*  -- this LUN is connected and its SCSI version
2172272401Smav			 *     allows more LUNs. */
2173272401Smav			} else if ((device->flags & CAM_DEV_UNCONFIGURED) == 0) {
2174272401Smav				if (lun_id < (CAM_SCSI2_MAXLUN-1) ||
2175272401Smav				    CAN_SRCH_HI_DENSE(device))
2176208911Smjacob					next_target = 0;
2177272401Smav			/*  -- this LUN is disconnected, its SCSI version
2178272401Smav			 *     allows more LUNs and we guess they may be. */
2179272401Smav			} else if ((device->flags & CAM_DEV_INQUIRY_DATA_VALID) != 0) {
2180272401Smav				if (lun_id < (CAM_SCSI2_MAXLUN-1) ||
2181272401Smav				    CAN_SRCH_HI_SPARSE(device))
2182272401Smav					next_target = 0;
2183195534Sscottl			}
2184272401Smav			if (next_target == 0) {
2185272401Smav				lun_id++;
2186272401Smav				if (lun_id > scan_info->cpi->max_lun)
2187272401Smav					next_target = 1;
2188272401Smav			}
2189195534Sscottl		}
2190195534Sscottl
2191195534Sscottl		/*
2192195534Sscottl		 * Check to see if we scan any further luns.
2193195534Sscottl		 */
2194208911Smjacob		if (next_target) {
2195195534Sscottl			int done;
2196195534Sscottl
2197208911Smjacob			/*
2198208911Smjacob			 * Free the current request path- we're done with it.
2199208911Smjacob			 */
2200208911Smjacob			xpt_free_path(oldpath);
2201195534Sscottl hop_again:
2202195534Sscottl			done = 0;
2203208582Smjacob			if (scan_info->request_ccb->ccb_h.func_code == XPT_SCAN_TGT) {
2204208582Smjacob				done = 1;
2205208582Smjacob			} else if (scan_info->cpi->hba_misc & PIM_SEQSCAN) {
2206195534Sscottl				scan_info->counter++;
2207195534Sscottl				if (scan_info->counter ==
2208195534Sscottl				    scan_info->cpi->initiator_id) {
2209195534Sscottl					scan_info->counter++;
2210195534Sscottl				}
2211195534Sscottl				if (scan_info->counter >=
2212195534Sscottl				    scan_info->cpi->max_target+1) {
2213195534Sscottl					done = 1;
2214195534Sscottl				}
2215195534Sscottl			} else {
2216195534Sscottl				scan_info->counter--;
2217195534Sscottl				if (scan_info->counter == 0) {
2218195534Sscottl					done = 1;
2219195534Sscottl				}
2220195534Sscottl			}
2221195534Sscottl			if (done) {
2222256843Smav				mtx_unlock(mtx);
2223195534Sscottl				xpt_free_ccb(request_ccb);
2224195534Sscottl				xpt_free_ccb((union ccb *)scan_info->cpi);
2225195534Sscottl				request_ccb = scan_info->request_ccb;
2226236613Smav				CAM_DEBUG(request_ccb->ccb_h.path,
2227236613Smav				    CAM_DEBUG_TRACE,
2228208911Smjacob				   ("SCAN done for %p\n", scan_info));
2229195534Sscottl				free(scan_info, M_CAMXPT);
2230195534Sscottl				request_ccb->ccb_h.status = CAM_REQ_CMP;
2231195534Sscottl				xpt_done(request_ccb);
2232195534Sscottl				break;
2233195534Sscottl			}
2234195534Sscottl
2235195534Sscottl			if ((scan_info->cpi->hba_misc & PIM_SEQSCAN) == 0) {
2236256843Smav				mtx_unlock(mtx);
2237195685Semaste				xpt_free_ccb(request_ccb);
2238195534Sscottl				break;
2239195534Sscottl			}
2240249468Smav			status = xpt_create_path(&path, NULL,
2241195534Sscottl			    scan_info->request_ccb->ccb_h.path_id,
2242195534Sscottl			    scan_info->counter, 0);
2243195534Sscottl			if (status != CAM_REQ_CMP) {
2244256843Smav				mtx_unlock(mtx);
2245195688Semaste				printf("scsi_scan_bus: xpt_create_path failed"
2246195534Sscottl				    " with status %#x, bus scan halted\n",
2247195534Sscottl			       	    status);
2248195534Sscottl				xpt_free_ccb(request_ccb);
2249195534Sscottl				xpt_free_ccb((union ccb *)scan_info->cpi);
2250195534Sscottl				request_ccb = scan_info->request_ccb;
2251195534Sscottl				free(scan_info, M_CAMXPT);
2252195534Sscottl				request_ccb->ccb_h.status = status;
2253195534Sscottl				xpt_done(request_ccb);
2254195534Sscottl				break;
2255195534Sscottl			}
2256195534Sscottl			xpt_setup_ccb(&request_ccb->ccb_h, path,
2257195534Sscottl			    request_ccb->ccb_h.pinfo.priority);
2258195534Sscottl			request_ccb->ccb_h.func_code = XPT_SCAN_LUN;
2259195534Sscottl			request_ccb->ccb_h.cbfcnp = scsi_scan_bus;
2260256843Smav			request_ccb->ccb_h.flags |= CAM_UNLOCKED;
2261195534Sscottl			request_ccb->ccb_h.ppriv_ptr0 = scan_info;
2262195534Sscottl			request_ccb->crcn.flags =
2263195534Sscottl			    scan_info->request_ccb->crcn.flags;
2264195534Sscottl		} else {
2265249468Smav			status = xpt_create_path(&path, NULL,
2266195534Sscottl						 path_id, target_id, lun_id);
2267208911Smjacob			/*
2268208911Smjacob			 * Free the old request path- we're done with it. We
2269208911Smjacob			 * do this *after* creating the new path so that
2270208911Smjacob			 * we don't remove a target that has our lun list
2271208911Smjacob			 * in the case that lun 0 is not present.
2272208911Smjacob			 */
2273208911Smjacob			xpt_free_path(oldpath);
2274195534Sscottl			if (status != CAM_REQ_CMP) {
2275195688Semaste				printf("scsi_scan_bus: xpt_create_path failed "
2276195534Sscottl				       "with status %#x, halting LUN scan\n",
2277195534Sscottl			 	       status);
2278195534Sscottl				goto hop_again;
2279195534Sscottl			}
2280195534Sscottl			xpt_setup_ccb(&request_ccb->ccb_h, path,
2281195534Sscottl				      request_ccb->ccb_h.pinfo.priority);
2282195534Sscottl			request_ccb->ccb_h.func_code = XPT_SCAN_LUN;
2283195534Sscottl			request_ccb->ccb_h.cbfcnp = scsi_scan_bus;
2284256843Smav			request_ccb->ccb_h.flags |= CAM_UNLOCKED;
2285195534Sscottl			request_ccb->ccb_h.ppriv_ptr0 = scan_info;
2286195534Sscottl			request_ccb->crcn.flags =
2287195534Sscottl				scan_info->request_ccb->crcn.flags;
2288195534Sscottl		}
2289256843Smav		mtx_unlock(mtx);
2290195534Sscottl		xpt_action(request_ccb);
2291195534Sscottl		break;
2292195534Sscottl	}
2293195534Sscottl	default:
2294195534Sscottl		break;
2295195534Sscottl	}
2296195534Sscottl}
2297195534Sscottl
2298195534Sscottlstatic void
2299195534Sscottlscsi_scan_lun(struct cam_periph *periph, struct cam_path *path,
2300195534Sscottl	     cam_flags flags, union ccb *request_ccb)
2301195534Sscottl{
2302195534Sscottl	struct ccb_pathinq cpi;
2303195534Sscottl	cam_status status;
2304195534Sscottl	struct cam_path *new_path;
2305195534Sscottl	struct cam_periph *old_periph;
2306256843Smav	int lock;
2307195534Sscottl
2308203108Smav	CAM_DEBUG(path, CAM_DEBUG_TRACE, ("scsi_scan_lun\n"));
2309195534Sscottl
2310203108Smav	xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NONE);
2311195534Sscottl	cpi.ccb_h.func_code = XPT_PATH_INQ;
2312195534Sscottl	xpt_action((union ccb *)&cpi);
2313195534Sscottl
2314195534Sscottl	if (cpi.ccb_h.status != CAM_REQ_CMP) {
2315195534Sscottl		if (request_ccb != NULL) {
2316195534Sscottl			request_ccb->ccb_h.status = cpi.ccb_h.status;
2317195534Sscottl			xpt_done(request_ccb);
2318195534Sscottl		}
2319195534Sscottl		return;
2320195534Sscottl	}
2321195534Sscottl
2322195534Sscottl	if ((cpi.hba_misc & PIM_NOINITIATOR) != 0) {
2323195534Sscottl		/*
2324195534Sscottl		 * Can't scan the bus on an adapter that
2325195534Sscottl		 * cannot perform the initiator role.
2326195534Sscottl		 */
2327195534Sscottl		if (request_ccb != NULL) {
2328195534Sscottl			request_ccb->ccb_h.status = CAM_REQ_CMP;
2329195534Sscottl			xpt_done(request_ccb);
2330195534Sscottl		}
2331195534Sscottl		return;
2332195534Sscottl	}
2333195534Sscottl
2334195534Sscottl	if (request_ccb == NULL) {
2335241455Smav		request_ccb = xpt_alloc_ccb_nowait();
2336195534Sscottl		if (request_ccb == NULL) {
2337195688Semaste			xpt_print(path, "scsi_scan_lun: can't allocate CCB, "
2338195534Sscottl			    "can't continue\n");
2339195534Sscottl			return;
2340195534Sscottl		}
2341249468Smav		status = xpt_create_path(&new_path, NULL,
2342195534Sscottl					  path->bus->path_id,
2343195534Sscottl					  path->target->target_id,
2344195534Sscottl					  path->device->lun_id);
2345195534Sscottl		if (status != CAM_REQ_CMP) {
2346241455Smav			xpt_print(path, "scsi_scan_lun: can't create path, "
2347195534Sscottl			    "can't continue\n");
2348241455Smav			xpt_free_ccb(request_ccb);
2349195534Sscottl			return;
2350195534Sscottl		}
2351203108Smav		xpt_setup_ccb(&request_ccb->ccb_h, new_path, CAM_PRIORITY_XPT);
2352195534Sscottl		request_ccb->ccb_h.cbfcnp = xptscandone;
2353195534Sscottl		request_ccb->ccb_h.func_code = XPT_SCAN_LUN;
2354256843Smav		request_ccb->ccb_h.flags |= CAM_UNLOCKED;
2355195534Sscottl		request_ccb->crcn.flags = flags;
2356195534Sscottl	}
2357195534Sscottl
2358256843Smav	lock = (xpt_path_owned(path) == 0);
2359256843Smav	if (lock)
2360256843Smav		xpt_path_lock(path);
2361195534Sscottl	if ((old_periph = cam_periph_find(path, "probe")) != NULL) {
2362236228Smav		if ((old_periph->flags & CAM_PERIPH_INVALID) == 0) {
2363236228Smav			probe_softc *softc;
2364195534Sscottl
2365236228Smav			softc = (probe_softc *)old_periph->softc;
2366236228Smav			TAILQ_INSERT_TAIL(&softc->request_ccbs,
2367236228Smav			    &request_ccb->ccb_h, periph_links.tqe);
2368236228Smav		} else {
2369236228Smav			request_ccb->ccb_h.status = CAM_REQ_CMP_ERR;
2370236228Smav			xpt_done(request_ccb);
2371236228Smav		}
2372195534Sscottl	} else {
2373195534Sscottl		status = cam_periph_alloc(proberegister, NULL, probecleanup,
2374195534Sscottl					  probestart, "probe",
2375195534Sscottl					  CAM_PERIPH_BIO,
2376195534Sscottl					  request_ccb->ccb_h.path, NULL, 0,
2377195534Sscottl					  request_ccb);
2378195534Sscottl
2379195534Sscottl		if (status != CAM_REQ_CMP) {
2380195688Semaste			xpt_print(path, "scsi_scan_lun: cam_alloc_periph "
2381195534Sscottl			    "returned an error, can't continue probe\n");
2382195534Sscottl			request_ccb->ccb_h.status = status;
2383195534Sscottl			xpt_done(request_ccb);
2384195534Sscottl		}
2385195534Sscottl	}
2386256843Smav	if (lock)
2387256843Smav		xpt_path_unlock(path);
2388195534Sscottl}
2389195534Sscottl
2390195534Sscottlstatic void
2391195534Sscottlxptscandone(struct cam_periph *periph, union ccb *done_ccb)
2392195534Sscottl{
2393241455Smav
2394241455Smav	xpt_free_path(done_ccb->ccb_h.path);
2395241455Smav	xpt_free_ccb(done_ccb);
2396195534Sscottl}
2397195534Sscottl
2398195534Sscottlstatic struct cam_ed *
2399195534Sscottlscsi_alloc_device(struct cam_eb *bus, struct cam_et *target, lun_id_t lun_id)
2400195534Sscottl{
2401195534Sscottl	struct scsi_quirk_entry *quirk;
2402195534Sscottl	struct cam_ed *device;
2403195534Sscottl
2404195534Sscottl	device = xpt_alloc_device(bus, target, lun_id);
2405195534Sscottl	if (device == NULL)
2406195534Sscottl		return (NULL);
2407195534Sscottl
2408195534Sscottl	/*
2409195534Sscottl	 * Take the default quirk entry until we have inquiry
2410195534Sscottl	 * data and can determine a better quirk to use.
2411195534Sscottl	 */
2412299186Spfg	quirk = &scsi_quirk_table[nitems(scsi_quirk_table) - 1];
2413195534Sscottl	device->quirk = (void *)quirk;
2414195534Sscottl	device->mintags = quirk->mintags;
2415195534Sscottl	device->maxtags = quirk->maxtags;
2416195534Sscottl	bzero(&device->inq_data, sizeof(device->inq_data));
2417195534Sscottl	device->inq_flags = 0;
2418195534Sscottl	device->queue_flags = 0;
2419195534Sscottl	device->serial_num = NULL;
2420195534Sscottl	device->serial_num_len = 0;
2421216088Sken	device->device_id = NULL;
2422216088Sken	device->device_id_len = 0;
2423216088Sken	device->supported_vpds = NULL;
2424216088Sken	device->supported_vpds_len = 0;
2425195534Sscottl	return (device);
2426195534Sscottl}
2427195534Sscottl
2428195534Sscottlstatic void
2429195534Sscottlscsi_devise_transport(struct cam_path *path)
2430195534Sscottl{
2431195534Sscottl	struct ccb_pathinq cpi;
2432195534Sscottl	struct ccb_trans_settings cts;
2433195534Sscottl	struct scsi_inquiry_data *inq_buf;
2434195534Sscottl
2435195534Sscottl	/* Get transport information from the SIM */
2436203108Smav	xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NONE);
2437195534Sscottl	cpi.ccb_h.func_code = XPT_PATH_INQ;
2438195534Sscottl	xpt_action((union ccb *)&cpi);
2439195534Sscottl
2440195534Sscottl	inq_buf = NULL;
2441195534Sscottl	if ((path->device->flags & CAM_DEV_INQUIRY_DATA_VALID) != 0)
2442195534Sscottl		inq_buf = &path->device->inq_data;
2443195534Sscottl	path->device->protocol = PROTO_SCSI;
2444195534Sscottl	path->device->protocol_version =
2445195534Sscottl	    inq_buf != NULL ? SID_ANSI_REV(inq_buf) : cpi.protocol_version;
2446195534Sscottl	path->device->transport = cpi.transport;
2447195534Sscottl	path->device->transport_version = cpi.transport_version;
2448195534Sscottl
2449195534Sscottl	/*
2450195534Sscottl	 * Any device not using SPI3 features should
2451195534Sscottl	 * be considered SPI2 or lower.
2452195534Sscottl	 */
2453195534Sscottl	if (inq_buf != NULL) {
2454195534Sscottl		if (path->device->transport == XPORT_SPI
2455195534Sscottl		 && (inq_buf->spi3data & SID_SPI_MASK) == 0
2456195534Sscottl		 && path->device->transport_version > 2)
2457195534Sscottl			path->device->transport_version = 2;
2458195534Sscottl	} else {
2459195534Sscottl		struct cam_ed* otherdev;
2460195534Sscottl
2461195534Sscottl		for (otherdev = TAILQ_FIRST(&path->target->ed_entries);
2462195534Sscottl		     otherdev != NULL;
2463195534Sscottl		     otherdev = TAILQ_NEXT(otherdev, links)) {
2464195534Sscottl			if (otherdev != path->device)
2465195534Sscottl				break;
2466195534Sscottl		}
2467195534Sscottl
2468195534Sscottl		if (otherdev != NULL) {
2469195534Sscottl			/*
2470195534Sscottl			 * Initially assume the same versioning as
2471195534Sscottl			 * prior luns for this target.
2472195534Sscottl			 */
2473195534Sscottl			path->device->protocol_version =
2474195534Sscottl			    otherdev->protocol_version;
2475195534Sscottl			path->device->transport_version =
2476195534Sscottl			    otherdev->transport_version;
2477195534Sscottl		} else {
2478298810Spfg			/* Until we know better, opt for safety */
2479195534Sscottl			path->device->protocol_version = 2;
2480195534Sscottl			if (path->device->transport == XPORT_SPI)
2481195534Sscottl				path->device->transport_version = 2;
2482195534Sscottl			else
2483195534Sscottl				path->device->transport_version = 0;
2484195534Sscottl		}
2485195534Sscottl	}
2486195534Sscottl
2487195534Sscottl	/*
2488195534Sscottl	 * XXX
2489195534Sscottl	 * For a device compliant with SPC-2 we should be able
2490195534Sscottl	 * to determine the transport version supported by
2491195534Sscottl	 * scrutinizing the version descriptors in the
2492195534Sscottl	 * inquiry buffer.
2493195534Sscottl	 */
2494195534Sscottl
2495195534Sscottl	/* Tell the controller what we think */
2496203108Smav	xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE);
2497195534Sscottl	cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
2498195534Sscottl	cts.type = CTS_TYPE_CURRENT_SETTINGS;
2499195534Sscottl	cts.transport = path->device->transport;
2500195534Sscottl	cts.transport_version = path->device->transport_version;
2501195534Sscottl	cts.protocol = path->device->protocol;
2502195534Sscottl	cts.protocol_version = path->device->protocol_version;
2503195534Sscottl	cts.proto_specific.valid = 0;
2504195534Sscottl	cts.xport_specific.valid = 0;
2505195534Sscottl	xpt_action((union ccb *)&cts);
2506195534Sscottl}
2507195534Sscottl
2508195534Sscottlstatic void
2509223081Sgibbsscsi_dev_advinfo(union ccb *start_ccb)
2510216088Sken{
2511216088Sken	struct cam_ed *device;
2512223081Sgibbs	struct ccb_dev_advinfo *cdai;
2513216088Sken	off_t amt;
2514216088Sken
2515351754Smav	xpt_path_assert(start_ccb->ccb_h.path, MA_OWNED);
2516223448Swill	start_ccb->ccb_h.status = CAM_REQ_INVALID;
2517216088Sken	device = start_ccb->ccb_h.path->device;
2518223081Sgibbs	cdai = &start_ccb->cdai;
2519223081Sgibbs	switch(cdai->buftype) {
2520223081Sgibbs	case CDAI_TYPE_SCSI_DEVID:
2521223081Sgibbs		if (cdai->flags & CDAI_FLAG_STORE)
2522223448Swill			return;
2523223081Sgibbs		cdai->provsiz = device->device_id_len;
2524216088Sken		if (device->device_id_len == 0)
2525216088Sken			break;
2526216088Sken		amt = device->device_id_len;
2527223081Sgibbs		if (cdai->provsiz > cdai->bufsiz)
2528223081Sgibbs			amt = cdai->bufsiz;
2529223081Sgibbs		memcpy(cdai->buf, device->device_id, amt);
2530216088Sken		break;
2531223081Sgibbs	case CDAI_TYPE_SERIAL_NUM:
2532223081Sgibbs		if (cdai->flags & CDAI_FLAG_STORE)
2533223448Swill			return;
2534223081Sgibbs		cdai->provsiz = device->serial_num_len;
2535223081Sgibbs		if (device->serial_num_len == 0)
2536223081Sgibbs			break;
2537223081Sgibbs		amt = device->serial_num_len;
2538223081Sgibbs		if (cdai->provsiz > cdai->bufsiz)
2539223081Sgibbs			amt = cdai->bufsiz;
2540223081Sgibbs		memcpy(cdai->buf, device->serial_num, amt);
2541223081Sgibbs		break;
2542223081Sgibbs	case CDAI_TYPE_PHYS_PATH:
2543223081Sgibbs		if (cdai->flags & CDAI_FLAG_STORE) {
2544230590Sken			if (device->physpath != NULL) {
2545223081Sgibbs				free(device->physpath, M_CAMXPT);
2546230590Sken				device->physpath = NULL;
2547326680Sasomers				device->physpath_len = 0;
2548230590Sken			}
2549223081Sgibbs			/* Clear existing buffer if zero length */
2550223081Sgibbs			if (cdai->bufsiz == 0)
2551223081Sgibbs				break;
2552223081Sgibbs			device->physpath = malloc(cdai->bufsiz, M_CAMXPT, M_NOWAIT);
2553223081Sgibbs			if (device->physpath == NULL) {
2554223081Sgibbs				start_ccb->ccb_h.status = CAM_REQ_ABORTED;
2555223081Sgibbs				return;
2556223081Sgibbs			}
2557326680Sasomers			device->physpath_len = cdai->bufsiz;
2558223081Sgibbs			memcpy(device->physpath, cdai->buf, cdai->bufsiz);
2559223081Sgibbs		} else {
2560223081Sgibbs			cdai->provsiz = device->physpath_len;
2561223081Sgibbs			if (device->physpath_len == 0)
2562223081Sgibbs				break;
2563223081Sgibbs			amt = device->physpath_len;
2564223081Sgibbs			if (cdai->provsiz > cdai->bufsiz)
2565223081Sgibbs				amt = cdai->bufsiz;
2566223081Sgibbs			memcpy(cdai->buf, device->physpath, amt);
2567223081Sgibbs		}
2568223081Sgibbs		break;
2569230590Sken	case CDAI_TYPE_RCAPLONG:
2570230590Sken		if (cdai->flags & CDAI_FLAG_STORE) {
2571230590Sken			if (device->rcap_buf != NULL) {
2572230590Sken				free(device->rcap_buf, M_CAMXPT);
2573230590Sken				device->rcap_buf = NULL;
2574230590Sken			}
2575230590Sken
2576230590Sken			device->rcap_len = cdai->bufsiz;
2577230590Sken			/* Clear existing buffer if zero length */
2578230590Sken			if (cdai->bufsiz == 0)
2579230590Sken				break;
2580230590Sken
2581230590Sken			device->rcap_buf = malloc(cdai->bufsiz, M_CAMXPT,
2582230590Sken						  M_NOWAIT);
2583230590Sken			if (device->rcap_buf == NULL) {
2584230590Sken				start_ccb->ccb_h.status = CAM_REQ_ABORTED;
2585230590Sken				return;
2586230590Sken			}
2587230590Sken
2588230590Sken			memcpy(device->rcap_buf, cdai->buf, cdai->bufsiz);
2589230590Sken		} else {
2590230590Sken			cdai->provsiz = device->rcap_len;
2591230590Sken			if (device->rcap_len == 0)
2592230590Sken				break;
2593230590Sken			amt = device->rcap_len;
2594230590Sken			if (cdai->provsiz > cdai->bufsiz)
2595230590Sken				amt = cdai->bufsiz;
2596230590Sken			memcpy(cdai->buf, device->rcap_buf, amt);
2597230590Sken		}
2598230590Sken		break;
2599278228Sken	case CDAI_TYPE_EXT_INQ:
2600278228Sken		/*
2601278228Sken		 * We fetch extended inquiry data during probe, if
2602278228Sken		 * available.  We don't allow changing it.
2603278228Sken		 */
2604350783Smav		if (cdai->flags & CDAI_FLAG_STORE)
2605278228Sken			return;
2606278228Sken		cdai->provsiz = device->ext_inq_len;
2607278228Sken		if (device->ext_inq_len == 0)
2608278228Sken			break;
2609278228Sken		amt = device->ext_inq_len;
2610278228Sken		if (cdai->provsiz > cdai->bufsiz)
2611278228Sken			amt = cdai->bufsiz;
2612278228Sken		memcpy(cdai->buf, device->ext_inq, amt);
2613278228Sken		break;
2614216088Sken	default:
2615223448Swill		return;
2616216088Sken	}
2617216088Sken	start_ccb->ccb_h.status = CAM_REQ_CMP;
2618223081Sgibbs
2619223081Sgibbs	if (cdai->flags & CDAI_FLAG_STORE) {
2620223081Sgibbs		xpt_async(AC_ADVINFO_CHANGED, start_ccb->ccb_h.path,
2621223081Sgibbs			  (void *)(uintptr_t)cdai->buftype);
2622223081Sgibbs	}
2623216088Sken}
2624216088Sken
2625216088Skenstatic void
2626195534Sscottlscsi_action(union ccb *start_ccb)
2627195534Sscottl{
2628195534Sscottl
2629195534Sscottl	switch (start_ccb->ccb_h.func_code) {
2630195534Sscottl	case XPT_SET_TRAN_SETTINGS:
2631195534Sscottl	{
2632195534Sscottl		scsi_set_transfer_settings(&start_ccb->cts,
2633256843Smav					   start_ccb->ccb_h.path,
2634195534Sscottl					   /*async_update*/FALSE);
2635195534Sscottl		break;
2636195534Sscottl	}
2637195534Sscottl	case XPT_SCAN_BUS:
2638208582Smjacob	case XPT_SCAN_TGT:
2639195534Sscottl		scsi_scan_bus(start_ccb->ccb_h.path->periph, start_ccb);
2640195534Sscottl		break;
2641195534Sscottl	case XPT_SCAN_LUN:
2642195534Sscottl		scsi_scan_lun(start_ccb->ccb_h.path->periph,
2643195534Sscottl			      start_ccb->ccb_h.path, start_ccb->crcn.flags,
2644195534Sscottl			      start_ccb);
2645195534Sscottl		break;
2646223081Sgibbs	case XPT_DEV_ADVINFO:
2647216088Sken	{
2648223081Sgibbs		scsi_dev_advinfo(start_ccb);
2649216088Sken		break;
2650216088Sken	}
2651195534Sscottl	default:
2652195534Sscottl		xpt_action_default(start_ccb);
2653195534Sscottl		break;
2654195534Sscottl	}
2655195534Sscottl}
2656195534Sscottl
2657195534Sscottlstatic void
2658256843Smavscsi_set_transfer_settings(struct ccb_trans_settings *cts, struct cam_path *path,
2659195534Sscottl			   int async_update)
2660195534Sscottl{
2661195534Sscottl	struct	ccb_pathinq cpi;
2662195534Sscottl	struct	ccb_trans_settings cur_cts;
2663195534Sscottl	struct	ccb_trans_settings_scsi *scsi;
2664195534Sscottl	struct	ccb_trans_settings_scsi *cur_scsi;
2665195534Sscottl	struct	scsi_inquiry_data *inq_data;
2666256843Smav	struct	cam_ed *device;
2667195534Sscottl
2668256843Smav	if (path == NULL || (device = path->device) == NULL) {
2669195534Sscottl		cts->ccb_h.status = CAM_PATH_INVALID;
2670195534Sscottl		xpt_done((union ccb *)cts);
2671195534Sscottl		return;
2672195534Sscottl	}
2673195534Sscottl
2674195534Sscottl	if (cts->protocol == PROTO_UNKNOWN
2675195534Sscottl	 || cts->protocol == PROTO_UNSPECIFIED) {
2676195534Sscottl		cts->protocol = device->protocol;
2677195534Sscottl		cts->protocol_version = device->protocol_version;
2678195534Sscottl	}
2679195534Sscottl
2680195534Sscottl	if (cts->protocol_version == PROTO_VERSION_UNKNOWN
2681195534Sscottl	 || cts->protocol_version == PROTO_VERSION_UNSPECIFIED)
2682195534Sscottl		cts->protocol_version = device->protocol_version;
2683195534Sscottl
2684195534Sscottl	if (cts->protocol != device->protocol) {
2685256843Smav		xpt_print(path, "Uninitialized Protocol %x:%x?\n",
2686195534Sscottl		       cts->protocol, device->protocol);
2687195534Sscottl		cts->protocol = device->protocol;
2688195534Sscottl	}
2689195534Sscottl
2690195534Sscottl	if (cts->protocol_version > device->protocol_version) {
2691195534Sscottl		if (bootverbose) {
2692256843Smav			xpt_print(path, "Down reving Protocol "
2693195534Sscottl			    "Version from %d to %d?\n", cts->protocol_version,
2694195534Sscottl			    device->protocol_version);
2695195534Sscottl		}
2696195534Sscottl		cts->protocol_version = device->protocol_version;
2697195534Sscottl	}
2698195534Sscottl
2699195534Sscottl	if (cts->transport == XPORT_UNKNOWN
2700195534Sscottl	 || cts->transport == XPORT_UNSPECIFIED) {
2701195534Sscottl		cts->transport = device->transport;
2702195534Sscottl		cts->transport_version = device->transport_version;
2703195534Sscottl	}
2704195534Sscottl
2705195534Sscottl	if (cts->transport_version == XPORT_VERSION_UNKNOWN
2706195534Sscottl	 || cts->transport_version == XPORT_VERSION_UNSPECIFIED)
2707195534Sscottl		cts->transport_version = device->transport_version;
2708195534Sscottl
2709195534Sscottl	if (cts->transport != device->transport) {
2710256843Smav		xpt_print(path, "Uninitialized Transport %x:%x?\n",
2711195534Sscottl		    cts->transport, device->transport);
2712195534Sscottl		cts->transport = device->transport;
2713195534Sscottl	}
2714195534Sscottl
2715195534Sscottl	if (cts->transport_version > device->transport_version) {
2716195534Sscottl		if (bootverbose) {
2717256843Smav			xpt_print(path, "Down reving Transport "
2718195534Sscottl			    "Version from %d to %d?\n", cts->transport_version,
2719195534Sscottl			    device->transport_version);
2720195534Sscottl		}
2721195534Sscottl		cts->transport_version = device->transport_version;
2722195534Sscottl	}
2723195534Sscottl
2724195534Sscottl	/*
2725195534Sscottl	 * Nothing more of interest to do unless
2726195534Sscottl	 * this is a device connected via the
2727195534Sscottl	 * SCSI protocol.
2728195534Sscottl	 */
2729195534Sscottl	if (cts->protocol != PROTO_SCSI) {
2730195534Sscottl		if (async_update == FALSE)
2731256843Smav			xpt_action_default((union ccb *)cts);
2732195534Sscottl		return;
2733195534Sscottl	}
2734195534Sscottl
2735195534Sscottl	inq_data = &device->inq_data;
2736195534Sscottl	scsi = &cts->proto_specific.scsi;
2737256843Smav	xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NONE);
2738195534Sscottl	cpi.ccb_h.func_code = XPT_PATH_INQ;
2739195534Sscottl	xpt_action((union ccb *)&cpi);
2740195534Sscottl
2741195534Sscottl	/* SCSI specific sanity checking */
2742195534Sscottl	if ((cpi.hba_inquiry & PI_TAG_ABLE) == 0
2743195534Sscottl	 || (INQ_DATA_TQ_ENABLED(inq_data)) == 0
2744195534Sscottl	 || (device->queue_flags & SCP_QUEUE_DQUE) != 0
2745195534Sscottl	 || (device->mintags == 0)) {
2746195534Sscottl		/*
2747195534Sscottl		 * Can't tag on hardware that doesn't support tags,
2748195534Sscottl		 * doesn't have it enabled, or has broken tag support.
2749195534Sscottl		 */
2750195534Sscottl		scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
2751195534Sscottl	}
2752195534Sscottl
2753195534Sscottl	if (async_update == FALSE) {
2754195534Sscottl		/*
2755195534Sscottl		 * Perform sanity checking against what the
2756195534Sscottl		 * controller and device can do.
2757195534Sscottl		 */
2758256843Smav		xpt_setup_ccb(&cur_cts.ccb_h, path, CAM_PRIORITY_NONE);
2759195534Sscottl		cur_cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
2760195534Sscottl		cur_cts.type = cts->type;
2761195534Sscottl		xpt_action((union ccb *)&cur_cts);
2762252382Sscottl		if (cam_ccb_status((union ccb *)&cur_cts) != CAM_REQ_CMP) {
2763195534Sscottl			return;
2764195534Sscottl		}
2765195534Sscottl		cur_scsi = &cur_cts.proto_specific.scsi;
2766195534Sscottl		if ((scsi->valid & CTS_SCSI_VALID_TQ) == 0) {
2767195534Sscottl			scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
2768195534Sscottl			scsi->flags |= cur_scsi->flags & CTS_SCSI_FLAGS_TAG_ENB;
2769195534Sscottl		}
2770195534Sscottl		if ((cur_scsi->valid & CTS_SCSI_VALID_TQ) == 0)
2771195534Sscottl			scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
2772195534Sscottl	}
2773195534Sscottl
2774195534Sscottl	/* SPI specific sanity checking */
2775195534Sscottl	if (cts->transport == XPORT_SPI && async_update == FALSE) {
2776195534Sscottl		u_int spi3caps;
2777195534Sscottl		struct ccb_trans_settings_spi *spi;
2778195534Sscottl		struct ccb_trans_settings_spi *cur_spi;
2779195534Sscottl
2780195534Sscottl		spi = &cts->xport_specific.spi;
2781195534Sscottl
2782195534Sscottl		cur_spi = &cur_cts.xport_specific.spi;
2783195534Sscottl
2784195534Sscottl		/* Fill in any gaps in what the user gave us */
2785195534Sscottl		if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) == 0)
2786195534Sscottl			spi->sync_period = cur_spi->sync_period;
2787195534Sscottl		if ((cur_spi->valid & CTS_SPI_VALID_SYNC_RATE) == 0)
2788195534Sscottl			spi->sync_period = 0;
2789195534Sscottl		if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) == 0)
2790195534Sscottl			spi->sync_offset = cur_spi->sync_offset;
2791195534Sscottl		if ((cur_spi->valid & CTS_SPI_VALID_SYNC_OFFSET) == 0)
2792195534Sscottl			spi->sync_offset = 0;
2793195534Sscottl		if ((spi->valid & CTS_SPI_VALID_PPR_OPTIONS) == 0)
2794195534Sscottl			spi->ppr_options = cur_spi->ppr_options;
2795195534Sscottl		if ((cur_spi->valid & CTS_SPI_VALID_PPR_OPTIONS) == 0)
2796195534Sscottl			spi->ppr_options = 0;
2797195534Sscottl		if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) == 0)
2798195534Sscottl			spi->bus_width = cur_spi->bus_width;
2799195534Sscottl		if ((cur_spi->valid & CTS_SPI_VALID_BUS_WIDTH) == 0)
2800195534Sscottl			spi->bus_width = 0;
2801195534Sscottl		if ((spi->valid & CTS_SPI_VALID_DISC) == 0) {
2802195534Sscottl			spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB;
2803195534Sscottl			spi->flags |= cur_spi->flags & CTS_SPI_FLAGS_DISC_ENB;
2804195534Sscottl		}
2805195534Sscottl		if ((cur_spi->valid & CTS_SPI_VALID_DISC) == 0)
2806195534Sscottl			spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB;
2807195534Sscottl		if (((device->flags & CAM_DEV_INQUIRY_DATA_VALID) != 0
2808195534Sscottl		  && (inq_data->flags & SID_Sync) == 0
2809195534Sscottl		  && cts->type == CTS_TYPE_CURRENT_SETTINGS)
2810195534Sscottl		 || ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0)) {
2811195534Sscottl			/* Force async */
2812195534Sscottl			spi->sync_period = 0;
2813195534Sscottl			spi->sync_offset = 0;
2814195534Sscottl		}
2815195534Sscottl
2816195534Sscottl		switch (spi->bus_width) {
2817195534Sscottl		case MSG_EXT_WDTR_BUS_32_BIT:
2818195534Sscottl			if (((device->flags & CAM_DEV_INQUIRY_DATA_VALID) == 0
2819195534Sscottl			  || (inq_data->flags & SID_WBus32) != 0
2820195534Sscottl			  || cts->type == CTS_TYPE_USER_SETTINGS)
2821195534Sscottl			 && (cpi.hba_inquiry & PI_WIDE_32) != 0)
2822195534Sscottl				break;
2823195534Sscottl			/* Fall Through to 16-bit */
2824195534Sscottl		case MSG_EXT_WDTR_BUS_16_BIT:
2825195534Sscottl			if (((device->flags & CAM_DEV_INQUIRY_DATA_VALID) == 0
2826195534Sscottl			  || (inq_data->flags & SID_WBus16) != 0
2827195534Sscottl			  || cts->type == CTS_TYPE_USER_SETTINGS)
2828195534Sscottl			 && (cpi.hba_inquiry & PI_WIDE_16) != 0) {
2829195534Sscottl				spi->bus_width = MSG_EXT_WDTR_BUS_16_BIT;
2830195534Sscottl				break;
2831195534Sscottl			}
2832195534Sscottl			/* Fall Through to 8-bit */
2833195534Sscottl		default: /* New bus width?? */
2834195534Sscottl		case MSG_EXT_WDTR_BUS_8_BIT:
2835195534Sscottl			/* All targets can do this */
2836195534Sscottl			spi->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
2837195534Sscottl			break;
2838195534Sscottl		}
2839195534Sscottl
2840195534Sscottl		spi3caps = cpi.xport_specific.spi.ppr_options;
2841195534Sscottl		if ((device->flags & CAM_DEV_INQUIRY_DATA_VALID) != 0
2842195534Sscottl		 && cts->type == CTS_TYPE_CURRENT_SETTINGS)
2843195534Sscottl			spi3caps &= inq_data->spi3data;
2844195534Sscottl
2845195534Sscottl		if ((spi3caps & SID_SPI_CLOCK_DT) == 0)
2846195534Sscottl			spi->ppr_options &= ~MSG_EXT_PPR_DT_REQ;
2847195534Sscottl
2848195534Sscottl		if ((spi3caps & SID_SPI_IUS) == 0)
2849195534Sscottl			spi->ppr_options &= ~MSG_EXT_PPR_IU_REQ;
2850195534Sscottl
2851195534Sscottl		if ((spi3caps & SID_SPI_QAS) == 0)
2852195534Sscottl			spi->ppr_options &= ~MSG_EXT_PPR_QAS_REQ;
2853195534Sscottl
2854195534Sscottl		/* No SPI Transfer settings are allowed unless we are wide */
2855195534Sscottl		if (spi->bus_width == 0)
2856195534Sscottl			spi->ppr_options = 0;
2857195534Sscottl
2858195534Sscottl		if ((spi->valid & CTS_SPI_VALID_DISC)
2859195534Sscottl		 && ((spi->flags & CTS_SPI_FLAGS_DISC_ENB) == 0)) {
2860195534Sscottl			/*
2861195534Sscottl			 * Can't tag queue without disconnection.
2862195534Sscottl			 */
2863195534Sscottl			scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
2864195534Sscottl			scsi->valid |= CTS_SCSI_VALID_TQ;
2865195534Sscottl		}
2866195534Sscottl
2867195534Sscottl		/*
2868195534Sscottl		 * If we are currently performing tagged transactions to
2869195534Sscottl		 * this device and want to change its negotiation parameters,
2870195534Sscottl		 * go non-tagged for a bit to give the controller a chance to
2871195534Sscottl		 * negotiate unhampered by tag messages.
2872195534Sscottl		 */
2873195534Sscottl		if (cts->type == CTS_TYPE_CURRENT_SETTINGS
2874195534Sscottl		 && (device->inq_flags & SID_CmdQue) != 0
2875195534Sscottl		 && (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0
2876195534Sscottl		 && (spi->flags & (CTS_SPI_VALID_SYNC_RATE|
2877195534Sscottl				   CTS_SPI_VALID_SYNC_OFFSET|
2878195534Sscottl				   CTS_SPI_VALID_BUS_WIDTH)) != 0)
2879256843Smav			scsi_toggle_tags(path);
2880195534Sscottl	}
2881195534Sscottl
2882195534Sscottl	if (cts->type == CTS_TYPE_CURRENT_SETTINGS
2883195534Sscottl	 && (scsi->valid & CTS_SCSI_VALID_TQ) != 0) {
2884195534Sscottl		int device_tagenb;
2885195534Sscottl
2886195534Sscottl		/*
2887195534Sscottl		 * If we are transitioning from tags to no-tags or
2888195534Sscottl		 * vice-versa, we need to carefully freeze and restart
2889195534Sscottl		 * the queue so that we don't overlap tagged and non-tagged
2890195534Sscottl		 * commands.  We also temporarily stop tags if there is
2891195534Sscottl		 * a change in transfer negotiation settings to allow
2892195534Sscottl		 * "tag-less" negotiation.
2893195534Sscottl		 */
2894195534Sscottl		if ((device->flags & CAM_DEV_TAG_AFTER_COUNT) != 0
2895195534Sscottl		 || (device->inq_flags & SID_CmdQue) != 0)
2896195534Sscottl			device_tagenb = TRUE;
2897195534Sscottl		else
2898195534Sscottl			device_tagenb = FALSE;
2899195534Sscottl
2900195534Sscottl		if (((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0
2901195534Sscottl		  && device_tagenb == FALSE)
2902195534Sscottl		 || ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) == 0
2903195534Sscottl		  && device_tagenb == TRUE)) {
2904195534Sscottl
2905195534Sscottl			if ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0) {
2906195534Sscottl				/*
2907195534Sscottl				 * Delay change to use tags until after a
2908195534Sscottl				 * few commands have gone to this device so
2909195534Sscottl				 * the controller has time to perform transfer
2910195534Sscottl				 * negotiations without tagged messages getting
2911195534Sscottl				 * in the way.
2912195534Sscottl				 */
2913195534Sscottl				device->tag_delay_count = CAM_TAG_DELAY_COUNT;
2914195534Sscottl				device->flags |= CAM_DEV_TAG_AFTER_COUNT;
2915195534Sscottl			} else {
2916256843Smav				xpt_stop_tags(path);
2917195534Sscottl			}
2918195534Sscottl		}
2919195534Sscottl	}
2920195534Sscottl	if (async_update == FALSE)
2921256843Smav		xpt_action_default((union ccb *)cts);
2922195534Sscottl}
2923195534Sscottl
2924195534Sscottlstatic void
2925195534Sscottlscsi_toggle_tags(struct cam_path *path)
2926195534Sscottl{
2927195534Sscottl	struct cam_ed *dev;
2928195534Sscottl
2929195534Sscottl	/*
2930195534Sscottl	 * Give controllers a chance to renegotiate
2931195534Sscottl	 * before starting tag operations.  We
2932195534Sscottl	 * "toggle" tagged queuing off then on
2933195534Sscottl	 * which causes the tag enable command delay
2934195534Sscottl	 * counter to come into effect.
2935195534Sscottl	 */
2936195534Sscottl	dev = path->device;
2937195534Sscottl	if ((dev->flags & CAM_DEV_TAG_AFTER_COUNT) != 0
2938195534Sscottl	 || ((dev->inq_flags & SID_CmdQue) != 0
2939195534Sscottl 	  && (dev->inq_flags & (SID_Sync|SID_WBus16|SID_WBus32)) != 0)) {
2940195534Sscottl		struct ccb_trans_settings cts;
2941195534Sscottl
2942203108Smav		xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE);
2943195534Sscottl		cts.protocol = PROTO_SCSI;
2944195534Sscottl		cts.protocol_version = PROTO_VERSION_UNSPECIFIED;
2945195534Sscottl		cts.transport = XPORT_UNSPECIFIED;
2946195534Sscottl		cts.transport_version = XPORT_VERSION_UNSPECIFIED;
2947195534Sscottl		cts.proto_specific.scsi.flags = 0;
2948195534Sscottl		cts.proto_specific.scsi.valid = CTS_SCSI_VALID_TQ;
2949256843Smav		scsi_set_transfer_settings(&cts, path,
2950195534Sscottl					  /*async_update*/TRUE);
2951195534Sscottl		cts.proto_specific.scsi.flags = CTS_SCSI_FLAGS_TAG_ENB;
2952256843Smav		scsi_set_transfer_settings(&cts, path,
2953195534Sscottl					  /*async_update*/TRUE);
2954195534Sscottl	}
2955195534Sscottl}
2956195534Sscottl
2957195534Sscottl/*
2958195534Sscottl * Handle any per-device event notifications that require action by the XPT.
2959195534Sscottl */
2960195534Sscottlstatic void
2961195534Sscottlscsi_dev_async(u_int32_t async_code, struct cam_eb *bus, struct cam_et *target,
2962195534Sscottl	      struct cam_ed *device, void *async_arg)
2963195534Sscottl{
2964195534Sscottl	cam_status status;
2965195534Sscottl	struct cam_path newpath;
2966195534Sscottl
2967195534Sscottl	/*
2968195534Sscottl	 * We only need to handle events for real devices.
2969195534Sscottl	 */
2970195534Sscottl	if (target->target_id == CAM_TARGET_WILDCARD
2971195534Sscottl	 || device->lun_id == CAM_LUN_WILDCARD)
2972195534Sscottl		return;
2973195534Sscottl
2974195534Sscottl	/*
2975195534Sscottl	 * We need our own path with wildcards expanded to
2976195534Sscottl	 * handle certain types of events.
2977195534Sscottl	 */
2978195534Sscottl	if ((async_code == AC_SENT_BDR)
2979195534Sscottl	 || (async_code == AC_BUS_RESET)
2980195534Sscottl	 || (async_code == AC_INQ_CHANGED))
2981195534Sscottl		status = xpt_compile_path(&newpath, NULL,
2982195534Sscottl					  bus->path_id,
2983195534Sscottl					  target->target_id,
2984195534Sscottl					  device->lun_id);
2985195534Sscottl	else
2986195534Sscottl		status = CAM_REQ_CMP_ERR;
2987195534Sscottl
2988195534Sscottl	if (status == CAM_REQ_CMP) {
2989195534Sscottl
2990195534Sscottl		/*
2991195534Sscottl		 * Allow transfer negotiation to occur in a
2992203108Smav		 * tag free environment and after settle delay.
2993195534Sscottl		 */
2994195534Sscottl		if (async_code == AC_SENT_BDR
2995203108Smav		 || async_code == AC_BUS_RESET) {
2996350783Smav			cam_freeze_devq(&newpath);
2997203108Smav			cam_release_devq(&newpath,
2998203108Smav				RELSIM_RELEASE_AFTER_TIMEOUT,
2999203108Smav				/*reduction*/0,
3000203108Smav				/*timeout*/scsi_delay,
3001203108Smav				/*getcount_only*/0);
3002195534Sscottl			scsi_toggle_tags(&newpath);
3003203108Smav		}
3004195534Sscottl
3005195534Sscottl		if (async_code == AC_INQ_CHANGED) {
3006195534Sscottl			/*
3007195534Sscottl			 * We've sent a start unit command, or
3008195534Sscottl			 * something similar to a device that
3009195534Sscottl			 * may have caused its inquiry data to
3010195534Sscottl			 * change. So we re-scan the device to
3011195534Sscottl			 * refresh the inquiry data for it.
3012195534Sscottl			 */
3013195534Sscottl			scsi_scan_lun(newpath.periph, &newpath,
3014195534Sscottl				     CAM_EXPECT_INQ_CHANGE, NULL);
3015195534Sscottl		}
3016195534Sscottl		xpt_release_path(&newpath);
3017198748Smav	} else if (async_code == AC_LOST_DEVICE &&
3018198748Smav	    (device->flags & CAM_DEV_UNCONFIGURED) == 0) {
3019195534Sscottl		device->flags |= CAM_DEV_UNCONFIGURED;
3020198748Smav		xpt_release_device(device);
3021195534Sscottl	} else if (async_code == AC_TRANSFER_NEG) {
3022195534Sscottl		struct ccb_trans_settings *settings;
3023256843Smav		struct cam_path path;
3024195534Sscottl
3025195534Sscottl		settings = (struct ccb_trans_settings *)async_arg;
3026256843Smav		xpt_compile_path(&path, NULL, bus->path_id, target->target_id,
3027256843Smav				 device->lun_id);
3028256843Smav		scsi_set_transfer_settings(settings, &path,
3029195534Sscottl					  /*async_update*/TRUE);
3030256843Smav		xpt_release_path(&path);
3031195534Sscottl	}
3032195534Sscottl}
3033195534Sscottl
3034204220Smavstatic void
3035204220Smavscsi_announce_periph(struct cam_periph *periph)
3036204220Smav{
3037204220Smav	struct	ccb_pathinq cpi;
3038204220Smav	struct	ccb_trans_settings cts;
3039204220Smav	struct	cam_path *path = periph->path;
3040204220Smav	u_int	speed;
3041204220Smav	u_int	freq;
3042204220Smav	u_int	mb;
3043204220Smav
3044256843Smav	cam_periph_assert(periph, MA_OWNED);
3045204220Smav
3046204220Smav	xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NORMAL);
3047204220Smav	cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
3048204220Smav	cts.type = CTS_TYPE_CURRENT_SETTINGS;
3049204220Smav	xpt_action((union ccb*)&cts);
3050252382Sscottl	if (cam_ccb_status((union ccb *)&cts) != CAM_REQ_CMP)
3051204220Smav		return;
3052204220Smav	/* Ask the SIM for its base transfer speed */
3053204220Smav	xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NORMAL);
3054204220Smav	cpi.ccb_h.func_code = XPT_PATH_INQ;
3055204220Smav	xpt_action((union ccb *)&cpi);
3056350783Smav	/* Report connection speed */
3057204220Smav	speed = cpi.base_transfer_speed;
3058204220Smav	freq = 0;
3059204220Smav	if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_SPI) {
3060204220Smav		struct	ccb_trans_settings_spi *spi =
3061204220Smav		    &cts.xport_specific.spi;
3062204220Smav
3063204220Smav		if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0
3064204220Smav		  && spi->sync_offset != 0) {
3065204220Smav			freq = scsi_calc_syncsrate(spi->sync_period);
3066204220Smav			speed = freq;
3067204220Smav		}
3068204220Smav		if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0)
3069204220Smav			speed *= (0x01 << spi->bus_width);
3070204220Smav	}
3071204220Smav	if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_FC) {
3072204220Smav		struct	ccb_trans_settings_fc *fc =
3073204220Smav		    &cts.xport_specific.fc;
3074204220Smav
3075204220Smav		if (fc->valid & CTS_FC_VALID_SPEED)
3076204220Smav			speed = fc->bitrate;
3077204220Smav	}
3078204220Smav	if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_SAS) {
3079204220Smav		struct	ccb_trans_settings_sas *sas =
3080204220Smav		    &cts.xport_specific.sas;
3081204220Smav
3082204220Smav		if (sas->valid & CTS_SAS_VALID_SPEED)
3083204220Smav			speed = sas->bitrate;
3084204220Smav	}
3085204220Smav	mb = speed / 1000;
3086204220Smav	if (mb > 0)
3087204220Smav		printf("%s%d: %d.%03dMB/s transfers",
3088204220Smav		       periph->periph_name, periph->unit_number,
3089204220Smav		       mb, speed % 1000);
3090204220Smav	else
3091204220Smav		printf("%s%d: %dKB/s transfers", periph->periph_name,
3092204220Smav		       periph->unit_number, speed);
3093204220Smav	/* Report additional information about SPI connections */
3094204220Smav	if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_SPI) {
3095204220Smav		struct	ccb_trans_settings_spi *spi;
3096204220Smav
3097204220Smav		spi = &cts.xport_specific.spi;
3098204220Smav		if (freq != 0) {
3099204220Smav			printf(" (%d.%03dMHz%s, offset %d", freq / 1000,
3100204220Smav			       freq % 1000,
3101204220Smav			       (spi->ppr_options & MSG_EXT_PPR_DT_REQ) != 0
3102204220Smav			     ? " DT" : "",
3103204220Smav			       spi->sync_offset);
3104204220Smav		}
3105204220Smav		if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0
3106204220Smav		 && spi->bus_width > 0) {
3107204220Smav			if (freq != 0) {
3108204220Smav				printf(", ");
3109204220Smav			} else {
3110204220Smav				printf(" (");
3111204220Smav			}
3112204220Smav			printf("%dbit)", 8 * (0x01 << spi->bus_width));
3113204220Smav		} else if (freq != 0) {
3114204220Smav			printf(")");
3115204220Smav		}
3116204220Smav	}
3117204220Smav	if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_FC) {
3118204220Smav		struct	ccb_trans_settings_fc *fc;
3119204220Smav
3120204220Smav		fc = &cts.xport_specific.fc;
3121204220Smav		if (fc->valid & CTS_FC_VALID_WWNN)
3122204220Smav			printf(" WWNN 0x%llx", (long long) fc->wwnn);
3123204220Smav		if (fc->valid & CTS_FC_VALID_WWPN)
3124204220Smav			printf(" WWPN 0x%llx", (long long) fc->wwpn);
3125204220Smav		if (fc->valid & CTS_FC_VALID_PORT)
3126204220Smav			printf(" PortID 0x%x", fc->port);
3127204220Smav	}
3128204220Smav	printf("\n");
3129204220Smav}
3130204220Smav
3131328820Smavstatic void
3132328820Smavscsi_proto_announce(struct cam_ed *device)
3133328820Smav{
3134328820Smav	scsi_print_inquiry(&device->inq_data);
3135328820Smav}
3136328820Smav
3137328820Smavstatic void
3138328820Smavscsi_proto_denounce(struct cam_ed *device)
3139328820Smav{
3140328820Smav	scsi_print_inquiry_short(&device->inq_data);
3141328820Smav}
3142328820Smav
3143328820Smavstatic void
3144328820Smavscsi_proto_debug_out(union ccb *ccb)
3145328820Smav{
3146328820Smav	char cdb_str[(SCSI_MAX_CDBLEN * 3) + 1];
3147328820Smav	struct cam_ed *device;
3148328820Smav
3149328820Smav	if (ccb->ccb_h.func_code != XPT_SCSI_IO)
3150328820Smav		return;
3151328820Smav
3152328820Smav	device = ccb->ccb_h.path->device;
3153328820Smav	CAM_DEBUG(ccb->ccb_h.path,
3154328820Smav	    CAM_DEBUG_CDB,("%s. CDB: %s\n",
3155328820Smav		scsi_op_desc(ccb->csio.cdb_io.cdb_bytes[0], &device->inq_data),
3156328820Smav		scsi_cdb_string(ccb->csio.cdb_io.cdb_bytes, cdb_str, sizeof(cdb_str))));
3157328820Smav}
3158