ata_xpt.c revision 220886
1195534Sscottl/*-
2195534Sscottl * Copyright (c) 2009 Alexander Motin <mav@FreeBSD.org>
3195534Sscottl * All rights reserved.
4195534Sscottl *
5195534Sscottl * Redistribution and use in source and binary forms, with or without
6195534Sscottl * modification, are permitted provided that the following conditions
7195534Sscottl * are met:
8195534Sscottl * 1. Redistributions of source code must retain the above copyright
9195534Sscottl *    notice, this list of conditions and the following disclaimer,
10195534Sscottl *    without modification, immediately at the beginning of the file.
11195534Sscottl * 2. Redistributions in binary form must reproduce the above copyright
12195534Sscottl *    notice, this list of conditions and the following disclaimer in the
13195534Sscottl *    documentation and/or other materials provided with the distribution.
14195534Sscottl *
15195534Sscottl * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16195534Sscottl * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17195534Sscottl * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18195534Sscottl * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19195534Sscottl * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20195534Sscottl * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21195534Sscottl * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22195534Sscottl * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23195534Sscottl * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24195534Sscottl * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25195534Sscottl */
26195534Sscottl
27195534Sscottl#include <sys/cdefs.h>
28195534Sscottl__FBSDID("$FreeBSD: head/sys/cam/ata/ata_xpt.c 220886 2011-04-20 13:27:50Z mav $");
29195534Sscottl
30195534Sscottl#include <sys/param.h>
31195534Sscottl#include <sys/bus.h>
32195534Sscottl#include <sys/endian.h>
33195534Sscottl#include <sys/systm.h>
34195534Sscottl#include <sys/types.h>
35195534Sscottl#include <sys/malloc.h>
36195534Sscottl#include <sys/kernel.h>
37195534Sscottl#include <sys/time.h>
38195534Sscottl#include <sys/conf.h>
39195534Sscottl#include <sys/fcntl.h>
40195534Sscottl#include <sys/interrupt.h>
41195534Sscottl#include <sys/sbuf.h>
42195534Sscottl
43195534Sscottl#include <sys/lock.h>
44195534Sscottl#include <sys/mutex.h>
45195534Sscottl#include <sys/sysctl.h>
46195534Sscottl
47195534Sscottl#include <cam/cam.h>
48195534Sscottl#include <cam/cam_ccb.h>
49195534Sscottl#include <cam/cam_queue.h>
50195534Sscottl#include <cam/cam_periph.h>
51195534Sscottl#include <cam/cam_sim.h>
52195534Sscottl#include <cam/cam_xpt.h>
53195534Sscottl#include <cam/cam_xpt_sim.h>
54195534Sscottl#include <cam/cam_xpt_periph.h>
55195534Sscottl#include <cam/cam_xpt_internal.h>
56195534Sscottl#include <cam/cam_debug.h>
57195534Sscottl
58195534Sscottl#include <cam/scsi/scsi_all.h>
59195534Sscottl#include <cam/scsi/scsi_message.h>
60195534Sscottl#include <cam/ata/ata_all.h>
61195534Sscottl#include <machine/stdarg.h>	/* for xpt_print below */
62195534Sscottl#include "opt_cam.h"
63195534Sscottl
64199178Smavstruct ata_quirk_entry {
65195534Sscottl	struct scsi_inquiry_pattern inq_pat;
66195534Sscottl	u_int8_t quirks;
67199178Smav#define	CAM_QUIRK_MAXTAGS	0x01
68195534Sscottl	u_int maxtags;
69195534Sscottl};
70195534Sscottl
71195534Sscottlstatic periph_init_t probe_periph_init;
72195534Sscottl
73195534Sscottlstatic struct periph_driver probe_driver =
74195534Sscottl{
75195653Smav	probe_periph_init, "aprobe",
76198708Smav	TAILQ_HEAD_INITIALIZER(probe_driver.units), /* generation */ 0,
77198708Smav	CAM_PERIPH_DRV_EARLY
78195534Sscottl};
79195534Sscottl
80195653SmavPERIPHDRIVER_DECLARE(aprobe, probe_driver);
81195534Sscottl
82195534Sscottltypedef enum {
83195534Sscottl	PROBE_RESET,
84195534Sscottl	PROBE_IDENTIFY,
85203421Smav	PROBE_SPINUP,
86195534Sscottl	PROBE_SETMODE,
87207499Smav	PROBE_SETPM,
88207499Smav	PROBE_SETAPST,
89207499Smav	PROBE_SETDMAAA,
90220602Smav	PROBE_SETAN,
91198708Smav	PROBE_SET_MULTI,
92195534Sscottl	PROBE_INQUIRY,
93195534Sscottl	PROBE_FULL_INQUIRY,
94195534Sscottl	PROBE_PM_PID,
95195534Sscottl	PROBE_PM_PRV,
96195534Sscottl	PROBE_INVALID
97195534Sscottl} probe_action;
98195534Sscottl
99195534Sscottlstatic char *probe_action_text[] = {
100195534Sscottl	"PROBE_RESET",
101195534Sscottl	"PROBE_IDENTIFY",
102203421Smav	"PROBE_SPINUP",
103195534Sscottl	"PROBE_SETMODE",
104207499Smav	"PROBE_SETPM",
105207499Smav	"PROBE_SETAPST",
106207499Smav	"PROBE_SETDMAAA",
107220602Smav	"PROBE_SETAN",
108198708Smav	"PROBE_SET_MULTI",
109195534Sscottl	"PROBE_INQUIRY",
110195534Sscottl	"PROBE_FULL_INQUIRY",
111195534Sscottl	"PROBE_PM_PID",
112195534Sscottl	"PROBE_PM_PRV",
113195534Sscottl	"PROBE_INVALID"
114195534Sscottl};
115195534Sscottl
116195534Sscottl#define PROBE_SET_ACTION(softc, newaction)	\
117195534Sscottldo {									\
118195534Sscottl	char **text;							\
119195534Sscottl	text = probe_action_text;					\
120195534Sscottl	CAM_DEBUG((softc)->periph->path, CAM_DEBUG_INFO,		\
121195534Sscottl	    ("Probe %s to %s\n", text[(softc)->action],			\
122195534Sscottl	    text[(newaction)]));					\
123195534Sscottl	(softc)->action = (newaction);					\
124195534Sscottl} while(0)
125195534Sscottl
126195534Sscottltypedef enum {
127195534Sscottl	PROBE_NO_ANNOUNCE	= 0x04
128195534Sscottl} probe_flags;
129195534Sscottl
130195534Sscottltypedef struct {
131195534Sscottl	TAILQ_HEAD(, ccb_hdr) request_ccbs;
132203385Smav	struct ata_params	ident_data;
133195534Sscottl	probe_action	action;
134195534Sscottl	probe_flags	flags;
135195534Sscottl	uint32_t	pm_pid;
136195534Sscottl	uint32_t	pm_prv;
137203108Smav	int		restart;
138203421Smav	int		spinup;
139209744Smav	int		faults;
140207499Smav	u_int		caps;
141195534Sscottl	struct cam_periph *periph;
142195534Sscottl} probe_softc;
143195534Sscottl
144199178Smavstatic struct ata_quirk_entry ata_quirk_table[] =
145195534Sscottl{
146195534Sscottl	{
147195534Sscottl		/* Default tagged queuing parameters for all devices */
148195534Sscottl		{
149195534Sscottl		  T_ANY, SIP_MEDIA_REMOVABLE|SIP_MEDIA_FIXED,
150195534Sscottl		  /*vendor*/"*", /*product*/"*", /*revision*/"*"
151195534Sscottl		},
152199178Smav		/*quirks*/0, /*maxtags*/0
153195534Sscottl	},
154195534Sscottl};
155195534Sscottl
156199178Smavstatic const int ata_quirk_table_size =
157199178Smav	sizeof(ata_quirk_table) / sizeof(*ata_quirk_table);
158195534Sscottl
159195534Sscottlstatic cam_status	proberegister(struct cam_periph *periph,
160195534Sscottl				      void *arg);
161195534Sscottlstatic void	 probeschedule(struct cam_periph *probe_periph);
162195534Sscottlstatic void	 probestart(struct cam_periph *periph, union ccb *start_ccb);
163195534Sscottl//static void	 proberequestdefaultnegotiation(struct cam_periph *periph);
164195534Sscottl//static int       proberequestbackoff(struct cam_periph *periph,
165195534Sscottl//				     struct cam_ed *device);
166195534Sscottlstatic void	 probedone(struct cam_periph *periph, union ccb *done_ccb);
167195534Sscottlstatic void	 probecleanup(struct cam_periph *periph);
168199178Smavstatic void	 ata_find_quirk(struct cam_ed *device);
169195534Sscottlstatic void	 ata_scan_bus(struct cam_periph *periph, union ccb *ccb);
170195534Sscottlstatic void	 ata_scan_lun(struct cam_periph *periph,
171195534Sscottl			       struct cam_path *path, cam_flags flags,
172195534Sscottl			       union ccb *ccb);
173195534Sscottlstatic void	 xptscandone(struct cam_periph *periph, union ccb *done_ccb);
174195534Sscottlstatic struct cam_ed *
175195534Sscottl		 ata_alloc_device(struct cam_eb *bus, struct cam_et *target,
176195534Sscottl				   lun_id_t lun_id);
177195534Sscottlstatic void	 ata_device_transport(struct cam_path *path);
178199178Smavstatic void	 ata_set_transfer_settings(struct ccb_trans_settings *cts,
179195534Sscottl					    struct cam_ed *device,
180195534Sscottl					    int async_update);
181195534Sscottlstatic void	 ata_dev_async(u_int32_t async_code,
182195534Sscottl				struct cam_eb *bus,
183195534Sscottl				struct cam_et *target,
184195534Sscottl				struct cam_ed *device,
185195534Sscottl				void *async_arg);
186195534Sscottlstatic void	 ata_action(union ccb *start_ccb);
187204220Smavstatic void	 ata_announce_periph(struct cam_periph *periph);
188195534Sscottl
189195534Sscottlstatic struct xpt_xport ata_xport = {
190195534Sscottl	.alloc_device = ata_alloc_device,
191195534Sscottl	.action = ata_action,
192195534Sscottl	.async = ata_dev_async,
193204220Smav	.announce = ata_announce_periph,
194195534Sscottl};
195195534Sscottl
196195534Sscottlstruct xpt_xport *
197195534Sscottlata_get_xport(void)
198195534Sscottl{
199195534Sscottl	return (&ata_xport);
200195534Sscottl}
201195534Sscottl
202195534Sscottlstatic void
203195534Sscottlprobe_periph_init()
204195534Sscottl{
205195534Sscottl}
206195534Sscottl
207195534Sscottlstatic cam_status
208195534Sscottlproberegister(struct cam_periph *periph, void *arg)
209195534Sscottl{
210195534Sscottl	union ccb *request_ccb;	/* CCB representing the probe request */
211195534Sscottl	cam_status status;
212195534Sscottl	probe_softc *softc;
213195534Sscottl
214195534Sscottl	request_ccb = (union ccb *)arg;
215195534Sscottl	if (periph == NULL) {
216195534Sscottl		printf("proberegister: periph was NULL!!\n");
217195534Sscottl		return(CAM_REQ_CMP_ERR);
218195534Sscottl	}
219195534Sscottl
220195534Sscottl	if (request_ccb == NULL) {
221195534Sscottl		printf("proberegister: no probe CCB, "
222195534Sscottl		       "can't register device\n");
223195534Sscottl		return(CAM_REQ_CMP_ERR);
224195534Sscottl	}
225195534Sscottl
226203421Smav	softc = (probe_softc *)malloc(sizeof(*softc), M_CAMXPT, M_ZERO | M_NOWAIT);
227195534Sscottl
228195534Sscottl	if (softc == NULL) {
229195534Sscottl		printf("proberegister: Unable to probe new device. "
230195534Sscottl		       "Unable to allocate softc\n");
231195534Sscottl		return(CAM_REQ_CMP_ERR);
232195534Sscottl	}
233195534Sscottl	TAILQ_INIT(&softc->request_ccbs);
234195534Sscottl	TAILQ_INSERT_TAIL(&softc->request_ccbs, &request_ccb->ccb_h,
235195534Sscottl			  periph_links.tqe);
236195534Sscottl	softc->flags = 0;
237195534Sscottl	periph->softc = softc;
238195534Sscottl	softc->periph = periph;
239195534Sscottl	softc->action = PROBE_INVALID;
240195534Sscottl	status = cam_periph_acquire(periph);
241195534Sscottl	if (status != CAM_REQ_CMP) {
242195534Sscottl		return (status);
243195534Sscottl	}
244195534Sscottl	/*
245203108Smav	 * Ensure nobody slip in until probe finish.
246195534Sscottl	 */
247203108Smav	cam_freeze_devq_arg(periph->path,
248203108Smav	    RELSIM_RELEASE_RUNLEVEL, CAM_RL_XPT + 1);
249195534Sscottl	probeschedule(periph);
250195534Sscottl	return(CAM_REQ_CMP);
251195534Sscottl}
252195534Sscottl
253195534Sscottlstatic void
254195534Sscottlprobeschedule(struct cam_periph *periph)
255195534Sscottl{
256195534Sscottl	union ccb *ccb;
257195534Sscottl	probe_softc *softc;
258195534Sscottl
259195534Sscottl	softc = (probe_softc *)periph->softc;
260195534Sscottl	ccb = (union ccb *)TAILQ_FIRST(&softc->request_ccbs);
261195534Sscottl
262198389Smav	if ((periph->path->device->flags & CAM_DEV_UNCONFIGURED) ||
263198389Smav	    periph->path->device->protocol == PROTO_SATAPM)
264195534Sscottl		PROBE_SET_ACTION(softc, PROBE_RESET);
265195534Sscottl	else
266195534Sscottl		PROBE_SET_ACTION(softc, PROBE_IDENTIFY);
267195534Sscottl
268195534Sscottl	if (ccb->crcn.flags & CAM_EXPECT_INQ_CHANGE)
269195534Sscottl		softc->flags |= PROBE_NO_ANNOUNCE;
270195534Sscottl	else
271195534Sscottl		softc->flags &= ~PROBE_NO_ANNOUNCE;
272195534Sscottl
273203108Smav	xpt_schedule(periph, CAM_PRIORITY_XPT);
274195534Sscottl}
275195534Sscottl
276195534Sscottlstatic void
277195534Sscottlprobestart(struct cam_periph *periph, union ccb *start_ccb)
278195534Sscottl{
279199747Smav	struct ccb_trans_settings cts;
280195534Sscottl	struct ccb_ataio *ataio;
281195534Sscottl	struct ccb_scsiio *csio;
282195534Sscottl	probe_softc *softc;
283198708Smav	struct cam_path *path;
284198708Smav	struct ata_params *ident_buf;
285195534Sscottl
286195534Sscottl	CAM_DEBUG(start_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("probestart\n"));
287195534Sscottl
288195534Sscottl	softc = (probe_softc *)periph->softc;
289198708Smav	path = start_ccb->ccb_h.path;
290195534Sscottl	ataio = &start_ccb->ataio;
291195534Sscottl	csio = &start_ccb->csio;
292198708Smav	ident_buf = &periph->path->device->ident_data;
293195534Sscottl
294203108Smav	if (softc->restart) {
295203108Smav		softc->restart = 0;
296203108Smav		if ((path->device->flags & CAM_DEV_UNCONFIGURED) ||
297203108Smav		    path->device->protocol == PROTO_SATAPM)
298203108Smav			softc->action = PROBE_RESET;
299203108Smav		else
300203108Smav			softc->action = PROBE_IDENTIFY;
301203108Smav	}
302195534Sscottl	switch (softc->action) {
303195534Sscottl	case PROBE_RESET:
304195534Sscottl		cam_fill_ataio(ataio,
305195534Sscottl		      0,
306195534Sscottl		      probedone,
307195534Sscottl		      /*flags*/CAM_DIR_NONE,
308198389Smav		      0,
309195534Sscottl		      /*data_ptr*/NULL,
310195534Sscottl		      /*dxfer_len*/0,
311203108Smav		      15 * 1000);
312195534Sscottl		ata_reset_cmd(ataio);
313195534Sscottl		break;
314195534Sscottl	case PROBE_IDENTIFY:
315195534Sscottl		cam_fill_ataio(ataio,
316195534Sscottl		      1,
317195534Sscottl		      probedone,
318195534Sscottl		      /*flags*/CAM_DIR_IN,
319198389Smav		      0,
320203385Smav		      /*data_ptr*/(u_int8_t *)&softc->ident_data,
321203385Smav		      /*dxfer_len*/sizeof(softc->ident_data),
322195534Sscottl		      30 * 1000);
323195534Sscottl		if (periph->path->device->protocol == PROTO_ATA)
324196659Smav			ata_28bit_cmd(ataio, ATA_ATA_IDENTIFY, 0, 0, 0);
325195534Sscottl		else
326196659Smav			ata_28bit_cmd(ataio, ATA_ATAPI_IDENTIFY, 0, 0, 0);
327195534Sscottl		break;
328203421Smav	case PROBE_SPINUP:
329203421Smav		if (bootverbose)
330203421Smav			xpt_print(path, "Spinning up device\n");
331203421Smav		cam_fill_ataio(ataio,
332203421Smav		      1,
333203421Smav		      probedone,
334203421Smav		      /*flags*/CAM_DIR_NONE | CAM_HIGH_POWER,
335203421Smav		      0,
336203421Smav		      /*data_ptr*/NULL,
337203421Smav		      /*dxfer_len*/0,
338203421Smav		      30 * 1000);
339203421Smav		ata_28bit_cmd(ataio, ATA_SETFEATURES, ATA_SF_PUIS_SPINUP, 0, 0);
340203421Smav		break;
341195534Sscottl	case PROBE_SETMODE:
342199747Smav	{
343199747Smav		int mode, wantmode;
344199747Smav
345199747Smav		mode = 0;
346199747Smav		/* Fetch user modes from SIM. */
347199747Smav		bzero(&cts, sizeof(cts));
348203108Smav		xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE);
349199747Smav		cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
350199747Smav		cts.type = CTS_TYPE_USER_SETTINGS;
351199747Smav		xpt_action((union ccb *)&cts);
352199747Smav		if (path->device->transport == XPORT_ATA) {
353199747Smav			if (cts.xport_specific.ata.valid & CTS_ATA_VALID_MODE)
354199747Smav				mode = cts.xport_specific.ata.mode;
355199747Smav		} else {
356199799Smav			if (cts.xport_specific.sata.valid & CTS_SATA_VALID_MODE)
357199747Smav				mode = cts.xport_specific.sata.mode;
358199747Smav		}
359199747Smavnegotiate:
360199747Smav		/* Honor device capabilities. */
361199747Smav		wantmode = mode = ata_max_mode(ident_buf, mode);
362199747Smav		/* Report modes to SIM. */
363199747Smav		bzero(&cts, sizeof(cts));
364203108Smav		xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE);
365199747Smav		cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
366199747Smav		cts.type = CTS_TYPE_CURRENT_SETTINGS;
367199747Smav		if (path->device->transport == XPORT_ATA) {
368199747Smav			cts.xport_specific.ata.mode = mode;
369199747Smav			cts.xport_specific.ata.valid = CTS_ATA_VALID_MODE;
370199747Smav		} else {
371199747Smav			cts.xport_specific.sata.mode = mode;
372199747Smav			cts.xport_specific.sata.valid = CTS_SATA_VALID_MODE;
373199747Smav		}
374199747Smav		xpt_action((union ccb *)&cts);
375200171Smav		/* Fetch current modes from SIM. */
376199747Smav		bzero(&cts, sizeof(cts));
377203108Smav		xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE);
378199747Smav		cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
379199747Smav		cts.type = CTS_TYPE_CURRENT_SETTINGS;
380199747Smav		xpt_action((union ccb *)&cts);
381199747Smav		if (path->device->transport == XPORT_ATA) {
382199747Smav			if (cts.xport_specific.ata.valid & CTS_ATA_VALID_MODE)
383199747Smav				mode = cts.xport_specific.ata.mode;
384199747Smav		} else {
385199747Smav			if (cts.xport_specific.ata.valid & CTS_SATA_VALID_MODE)
386199747Smav				mode = cts.xport_specific.sata.mode;
387199747Smav		}
388199747Smav		/* If SIM disagree - renegotiate. */
389199747Smav		if (mode != wantmode)
390199747Smav			goto negotiate;
391220886Smav		/* Remember what transport thinks about DMA. */
392220886Smav		if (mode < ATA_DMA)
393220886Smav			path->device->inq_flags &= ~SID_DMA;
394220886Smav		else
395220886Smav			path->device->inq_flags |= SID_DMA;
396195534Sscottl		cam_fill_ataio(ataio,
397195534Sscottl		      1,
398195534Sscottl		      probedone,
399196353Smav		      /*flags*/CAM_DIR_NONE,
400196353Smav		      0,
401196353Smav		      /*data_ptr*/NULL,
402196353Smav		      /*dxfer_len*/0,
403195534Sscottl		      30 * 1000);
404199747Smav		ata_28bit_cmd(ataio, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode);
405195534Sscottl		break;
406199747Smav	}
407207499Smav	case PROBE_SETPM:
408207499Smav		cam_fill_ataio(ataio,
409207499Smav		    1,
410207499Smav		    probedone,
411207499Smav		    CAM_DIR_NONE,
412207499Smav		    0,
413207499Smav		    NULL,
414207499Smav		    0,
415207499Smav		    30*1000);
416207499Smav		ata_28bit_cmd(ataio, ATA_SETFEATURES,
417207499Smav		    (softc->caps & CTS_SATA_CAPS_H_PMREQ) ? 0x10 : 0x90,
418207499Smav		    0, 0x03);
419207499Smav		break;
420207499Smav	case PROBE_SETAPST:
421207499Smav		cam_fill_ataio(ataio,
422207499Smav		    1,
423207499Smav		    probedone,
424207499Smav		    CAM_DIR_NONE,
425207499Smav		    0,
426207499Smav		    NULL,
427207499Smav		    0,
428207499Smav		    30*1000);
429207499Smav		ata_28bit_cmd(ataio, ATA_SETFEATURES,
430207499Smav		    (softc->caps & CTS_SATA_CAPS_H_APST) ? 0x10 : 0x90,
431207499Smav		    0, 0x07);
432207499Smav		break;
433207499Smav	case PROBE_SETDMAAA:
434207499Smav		cam_fill_ataio(ataio,
435207499Smav		    1,
436207499Smav		    probedone,
437207499Smav		    CAM_DIR_NONE,
438207499Smav		    0,
439207499Smav		    NULL,
440207499Smav		    0,
441207499Smav		    30*1000);
442207499Smav		ata_28bit_cmd(ataio, ATA_SETFEATURES,
443207499Smav		    (softc->caps & CTS_SATA_CAPS_H_DMAAA) ? 0x10 : 0x90,
444207499Smav		    0, 0x02);
445207499Smav		break;
446220602Smav	case PROBE_SETAN:
447220602Smav		cam_fill_ataio(ataio,
448220602Smav		    1,
449220602Smav		    probedone,
450220602Smav		    CAM_DIR_NONE,
451220602Smav		    0,
452220602Smav		    NULL,
453220602Smav		    0,
454220602Smav		    30*1000);
455220602Smav		ata_28bit_cmd(ataio, ATA_SETFEATURES,
456220602Smav		    (softc->caps & CTS_SATA_CAPS_H_AN) ? 0x10 : 0x90,
457220602Smav		    0, 0x05);
458220602Smav		break;
459198708Smav	case PROBE_SET_MULTI:
460198708Smav	{
461200171Smav		u_int sectors, bytecount;
462198708Smav
463200171Smav		bytecount = 8192;	/* SATA maximum */
464200171Smav		/* Fetch user bytecount from SIM. */
465200171Smav		bzero(&cts, sizeof(cts));
466203108Smav		xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE);
467200171Smav		cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
468200171Smav		cts.type = CTS_TYPE_USER_SETTINGS;
469200171Smav		xpt_action((union ccb *)&cts);
470200171Smav		if (path->device->transport == XPORT_ATA) {
471200171Smav			if (cts.xport_specific.ata.valid & CTS_ATA_VALID_BYTECOUNT)
472200171Smav				bytecount = cts.xport_specific.ata.bytecount;
473200171Smav		} else {
474200171Smav			if (cts.xport_specific.sata.valid & CTS_SATA_VALID_BYTECOUNT)
475200171Smav				bytecount = cts.xport_specific.sata.bytecount;
476200171Smav		}
477200171Smav		/* Honor device capabilities. */
478200171Smav		sectors = max(1, min(ident_buf->sectors_intr & 0xff,
479200171Smav		    bytecount / ata_logical_sector_size(ident_buf)));
480198708Smav		/* Report bytecount to SIM. */
481198708Smav		bzero(&cts, sizeof(cts));
482203108Smav		xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE);
483198708Smav		cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
484198708Smav		cts.type = CTS_TYPE_CURRENT_SETTINGS;
485198708Smav		if (path->device->transport == XPORT_ATA) {
486198897Smav			cts.xport_specific.ata.bytecount = sectors *
487198897Smav			    ata_logical_sector_size(ident_buf);
488198708Smav			cts.xport_specific.ata.valid = CTS_ATA_VALID_BYTECOUNT;
489198708Smav		} else {
490198897Smav			cts.xport_specific.sata.bytecount = sectors *
491198897Smav			    ata_logical_sector_size(ident_buf);
492198708Smav			cts.xport_specific.sata.valid = CTS_SATA_VALID_BYTECOUNT;
493198708Smav		}
494198708Smav		xpt_action((union ccb *)&cts);
495200171Smav		/* Fetch current bytecount from SIM. */
496200171Smav		bzero(&cts, sizeof(cts));
497203108Smav		xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE);
498200171Smav		cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
499200171Smav		cts.type = CTS_TYPE_CURRENT_SETTINGS;
500200171Smav		xpt_action((union ccb *)&cts);
501200171Smav		if (path->device->transport == XPORT_ATA) {
502200171Smav			if (cts.xport_specific.ata.valid & CTS_ATA_VALID_BYTECOUNT)
503200171Smav				bytecount = cts.xport_specific.ata.bytecount;
504200171Smav		} else {
505200171Smav			if (cts.xport_specific.sata.valid & CTS_SATA_VALID_BYTECOUNT)
506200171Smav				bytecount = cts.xport_specific.sata.bytecount;
507200171Smav		}
508200171Smav		sectors = bytecount / ata_logical_sector_size(ident_buf);
509198708Smav
510198708Smav		cam_fill_ataio(ataio,
511198708Smav		    1,
512198708Smav		    probedone,
513198708Smav		    CAM_DIR_NONE,
514198708Smav		    0,
515198708Smav		    NULL,
516198708Smav		    0,
517198708Smav		    30*1000);
518198708Smav		ata_28bit_cmd(ataio, ATA_SET_MULTI, 0, 0, sectors);
519198708Smav		break;
520195534Sscottl	}
521195534Sscottl	case PROBE_INQUIRY:
522200171Smav	{
523200171Smav		u_int bytecount;
524200171Smav
525200171Smav		bytecount = 8192;	/* SATA maximum */
526200171Smav		/* Fetch user bytecount from SIM. */
527200171Smav		bzero(&cts, sizeof(cts));
528203108Smav		xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE);
529200171Smav		cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
530200171Smav		cts.type = CTS_TYPE_USER_SETTINGS;
531200171Smav		xpt_action((union ccb *)&cts);
532200171Smav		if (path->device->transport == XPORT_ATA) {
533200171Smav			if (cts.xport_specific.ata.valid & CTS_ATA_VALID_BYTECOUNT)
534200171Smav				bytecount = cts.xport_specific.ata.bytecount;
535200171Smav		} else {
536200171Smav			if (cts.xport_specific.sata.valid & CTS_SATA_VALID_BYTECOUNT)
537200171Smav				bytecount = cts.xport_specific.sata.bytecount;
538200171Smav		}
539200171Smav		/* Honor device capabilities. */
540200171Smav		bytecount &= ~1;
541200171Smav		bytecount = max(2, min(65534, bytecount));
542200171Smav		if (ident_buf->satacapabilities != 0x0000 &&
543200171Smav		    ident_buf->satacapabilities != 0xffff) {
544200171Smav			bytecount = min(8192, bytecount);
545200171Smav		}
546200171Smav		/* Report bytecount to SIM. */
547200171Smav		bzero(&cts, sizeof(cts));
548203108Smav		xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE);
549200171Smav		cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
550200171Smav		cts.type = CTS_TYPE_CURRENT_SETTINGS;
551200171Smav		if (path->device->transport == XPORT_ATA) {
552200171Smav			cts.xport_specific.ata.bytecount = bytecount;
553200171Smav			cts.xport_specific.ata.valid = CTS_ATA_VALID_BYTECOUNT;
554200171Smav		} else {
555200171Smav			cts.xport_specific.sata.bytecount = bytecount;
556200171Smav			cts.xport_specific.sata.valid = CTS_SATA_VALID_BYTECOUNT;
557200171Smav		}
558200171Smav		xpt_action((union ccb *)&cts);
559200171Smav		/* FALLTHROUGH */
560200171Smav	}
561195534Sscottl	case PROBE_FULL_INQUIRY:
562195534Sscottl	{
563195534Sscottl		u_int inquiry_len;
564195534Sscottl		struct scsi_inquiry_data *inq_buf =
565195534Sscottl		    &periph->path->device->inq_data;
566195534Sscottl
567195534Sscottl		if (softc->action == PROBE_INQUIRY)
568195534Sscottl			inquiry_len = SHORT_INQUIRY_LENGTH;
569195534Sscottl		else
570195534Sscottl			inquiry_len = SID_ADDITIONAL_LENGTH(inq_buf);
571195534Sscottl		/*
572195534Sscottl		 * Some parallel SCSI devices fail to send an
573195534Sscottl		 * ignore wide residue message when dealing with
574195534Sscottl		 * odd length inquiry requests.  Round up to be
575195534Sscottl		 * safe.
576195534Sscottl		 */
577195534Sscottl		inquiry_len = roundup2(inquiry_len, 2);
578195534Sscottl		scsi_inquiry(csio,
579195534Sscottl			     /*retries*/1,
580195534Sscottl			     probedone,
581195534Sscottl			     MSG_SIMPLE_Q_TAG,
582195534Sscottl			     (u_int8_t *)inq_buf,
583195534Sscottl			     inquiry_len,
584195534Sscottl			     /*evpd*/FALSE,
585195534Sscottl			     /*page_code*/0,
586195534Sscottl			     SSD_MIN_SIZE,
587195534Sscottl			     /*timeout*/60 * 1000);
588195534Sscottl		break;
589195534Sscottl	}
590195534Sscottl	case PROBE_PM_PID:
591195534Sscottl		cam_fill_ataio(ataio,
592195534Sscottl		      1,
593195534Sscottl		      probedone,
594195534Sscottl		      /*flags*/CAM_DIR_NONE,
595198389Smav		      0,
596195534Sscottl		      /*data_ptr*/NULL,
597195534Sscottl		      /*dxfer_len*/0,
598195534Sscottl		      10 * 1000);
599195534Sscottl		ata_pm_read_cmd(ataio, 0, 15);
600195534Sscottl		break;
601195534Sscottl	case PROBE_PM_PRV:
602195534Sscottl		cam_fill_ataio(ataio,
603195534Sscottl		      1,
604195534Sscottl		      probedone,
605195534Sscottl		      /*flags*/CAM_DIR_NONE,
606198389Smav		      0,
607195534Sscottl		      /*data_ptr*/NULL,
608195534Sscottl		      /*dxfer_len*/0,
609195534Sscottl		      10 * 1000);
610195534Sscottl		ata_pm_read_cmd(ataio, 1, 15);
611195534Sscottl		break;
612195534Sscottl	case PROBE_INVALID:
613198708Smav		CAM_DEBUG(path, CAM_DEBUG_INFO,
614195534Sscottl		    ("probestart: invalid action state\n"));
615195534Sscottl	default:
616195534Sscottl		break;
617195534Sscottl	}
618195534Sscottl	xpt_action(start_ccb);
619195534Sscottl}
620195534Sscottl#if 0
621195534Sscottlstatic void
622195534Sscottlproberequestdefaultnegotiation(struct cam_periph *periph)
623195534Sscottl{
624195534Sscottl	struct ccb_trans_settings cts;
625195534Sscottl
626203108Smav	xpt_setup_ccb(&cts.ccb_h, periph->path, CAM_PRIORITY_NONE);
627195534Sscottl	cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
628195534Sscottl	cts.type = CTS_TYPE_USER_SETTINGS;
629195534Sscottl	xpt_action((union ccb *)&cts);
630195534Sscottl	if ((cts.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
631195534Sscottl		return;
632195534Sscottl	}
633195534Sscottl	cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
634195534Sscottl	cts.type = CTS_TYPE_CURRENT_SETTINGS;
635195534Sscottl	xpt_action((union ccb *)&cts);
636195534Sscottl}
637195534Sscottl
638195534Sscottl/*
639195534Sscottl * Backoff Negotiation Code- only pertinent for SPI devices.
640195534Sscottl */
641195534Sscottlstatic int
642195534Sscottlproberequestbackoff(struct cam_periph *periph, struct cam_ed *device)
643195534Sscottl{
644195534Sscottl	struct ccb_trans_settings cts;
645195534Sscottl	struct ccb_trans_settings_spi *spi;
646195534Sscottl
647195534Sscottl	memset(&cts, 0, sizeof (cts));
648203108Smav	xpt_setup_ccb(&cts.ccb_h, periph->path, CAM_PRIORITY_NONE);
649195534Sscottl	cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
650195534Sscottl	cts.type = CTS_TYPE_CURRENT_SETTINGS;
651195534Sscottl	xpt_action((union ccb *)&cts);
652195534Sscottl	if ((cts.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
653195534Sscottl		if (bootverbose) {
654195534Sscottl			xpt_print(periph->path,
655195534Sscottl			    "failed to get current device settings\n");
656195534Sscottl		}
657195534Sscottl		return (0);
658195534Sscottl	}
659195534Sscottl	if (cts.transport != XPORT_SPI) {
660195534Sscottl		if (bootverbose) {
661195534Sscottl			xpt_print(periph->path, "not SPI transport\n");
662195534Sscottl		}
663195534Sscottl		return (0);
664195534Sscottl	}
665195534Sscottl	spi = &cts.xport_specific.spi;
666195534Sscottl
667195534Sscottl	/*
668195534Sscottl	 * We cannot renegotiate sync rate if we don't have one.
669195534Sscottl	 */
670195534Sscottl	if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) == 0) {
671195534Sscottl		if (bootverbose) {
672195534Sscottl			xpt_print(periph->path, "no sync rate known\n");
673195534Sscottl		}
674195534Sscottl		return (0);
675195534Sscottl	}
676195534Sscottl
677195534Sscottl	/*
678195534Sscottl	 * We'll assert that we don't have to touch PPR options- the
679195534Sscottl	 * SIM will see what we do with period and offset and adjust
680195534Sscottl	 * the PPR options as appropriate.
681195534Sscottl	 */
682195534Sscottl
683195534Sscottl	/*
684195534Sscottl	 * A sync rate with unknown or zero offset is nonsensical.
685195534Sscottl	 * A sync period of zero means Async.
686195534Sscottl	 */
687195534Sscottl	if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) == 0
688195534Sscottl	 || spi->sync_offset == 0 || spi->sync_period == 0) {
689195534Sscottl		if (bootverbose) {
690195534Sscottl			xpt_print(periph->path, "no sync rate available\n");
691195534Sscottl		}
692195534Sscottl		return (0);
693195534Sscottl	}
694195534Sscottl
695195534Sscottl	if (device->flags & CAM_DEV_DV_HIT_BOTTOM) {
696195534Sscottl		CAM_DEBUG(periph->path, CAM_DEBUG_INFO,
697195534Sscottl		    ("hit async: giving up on DV\n"));
698195534Sscottl		return (0);
699195534Sscottl	}
700195534Sscottl
701195534Sscottl
702195534Sscottl	/*
703195534Sscottl	 * Jump sync_period up by one, but stop at 5MHz and fall back to Async.
704195534Sscottl	 * We don't try to remember 'last' settings to see if the SIM actually
705195534Sscottl	 * gets into the speed we want to set. We check on the SIM telling
706195534Sscottl	 * us that a requested speed is bad, but otherwise don't try and
707195534Sscottl	 * check the speed due to the asynchronous and handshake nature
708195534Sscottl	 * of speed setting.
709195534Sscottl	 */
710195534Sscottl	spi->valid = CTS_SPI_VALID_SYNC_RATE | CTS_SPI_VALID_SYNC_OFFSET;
711195534Sscottl	for (;;) {
712195534Sscottl		spi->sync_period++;
713195534Sscottl		if (spi->sync_period >= 0xf) {
714195534Sscottl			spi->sync_period = 0;
715195534Sscottl			spi->sync_offset = 0;
716195534Sscottl			CAM_DEBUG(periph->path, CAM_DEBUG_INFO,
717195534Sscottl			    ("setting to async for DV\n"));
718195534Sscottl			/*
719195534Sscottl			 * Once we hit async, we don't want to try
720195534Sscottl			 * any more settings.
721195534Sscottl			 */
722195534Sscottl			device->flags |= CAM_DEV_DV_HIT_BOTTOM;
723195534Sscottl		} else if (bootverbose) {
724195534Sscottl			CAM_DEBUG(periph->path, CAM_DEBUG_INFO,
725195534Sscottl			    ("DV: period 0x%x\n", spi->sync_period));
726195534Sscottl			printf("setting period to 0x%x\n", spi->sync_period);
727195534Sscottl		}
728195534Sscottl		cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
729195534Sscottl		cts.type = CTS_TYPE_CURRENT_SETTINGS;
730195534Sscottl		xpt_action((union ccb *)&cts);
731195534Sscottl		if ((cts.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
732195534Sscottl			break;
733195534Sscottl		}
734195534Sscottl		CAM_DEBUG(periph->path, CAM_DEBUG_INFO,
735195534Sscottl		    ("DV: failed to set period 0x%x\n", spi->sync_period));
736195534Sscottl		if (spi->sync_period == 0) {
737195534Sscottl			return (0);
738195534Sscottl		}
739195534Sscottl	}
740195534Sscottl	return (1);
741195534Sscottl}
742195534Sscottl#endif
743195534Sscottlstatic void
744195534Sscottlprobedone(struct cam_periph *periph, union ccb *done_ccb)
745195534Sscottl{
746199747Smav	struct ccb_trans_settings cts;
747195534Sscottl	struct ata_params *ident_buf;
748195534Sscottl	probe_softc *softc;
749195534Sscottl	struct cam_path *path;
750217444Smav	cam_status status;
751195534Sscottl	u_int32_t  priority;
752207499Smav	u_int caps;
753198389Smav	int found = 1;
754195534Sscottl
755195534Sscottl	CAM_DEBUG(done_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("probedone\n"));
756195534Sscottl
757195534Sscottl	softc = (probe_softc *)periph->softc;
758195534Sscottl	path = done_ccb->ccb_h.path;
759195534Sscottl	priority = done_ccb->ccb_h.pinfo.priority;
760195534Sscottl	ident_buf = &path->device->ident_data;
761195534Sscottl
762198708Smav	if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
763209744Smav		if (softc->restart) {
764209744Smav			if (bootverbose) {
765209744Smav				cam_error_print(done_ccb,
766209744Smav				    CAM_ESF_ALL, CAM_EPF_ALL);
767209744Smav			}
768209744Smav		} else if (cam_periph_error(done_ccb, 0, 0, NULL) == ERESTART)
769195534Sscottl			return;
770209744Smav		if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
771195534Sscottl			/* Don't wedge the queue */
772195534Sscottl			xpt_release_devq(done_ccb->ccb_h.path, /*count*/1,
773195534Sscottl					 /*run_queue*/TRUE);
774195534Sscottl		}
775217444Smav		status = done_ccb->ccb_h.status & CAM_STATUS_MASK;
776209744Smav		if (softc->restart) {
777209744Smav			softc->faults++;
778209744Smav			if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) ==
779209744Smav			    CAM_CMD_TIMEOUT)
780209744Smav				softc->faults += 4;
781209744Smav			if (softc->faults < 10)
782209744Smav				goto done;
783209744Smav			else
784209744Smav				softc->restart = 0;
785217444Smav
786198708Smav		/* Old PIO2 devices may not support mode setting. */
787217444Smav		} else if (softc->action == PROBE_SETMODE &&
788217444Smav		    status == CAM_ATA_STATUS_ERROR &&
789198708Smav		    ata_max_pmode(ident_buf) <= ATA_PIO2 &&
790217444Smav		    (ident_buf->capabilities1 & ATA_SUPPORT_IORDY) == 0) {
791198708Smav			goto noerror;
792217444Smav
793198708Smav		/*
794217444Smav		 * Some old WD SATA disks report supported and enabled
795217444Smav		 * device-initiated interface power management, but return
796217444Smav		 * ABORT on attempt to disable it.
797217444Smav		 */
798217444Smav		} else if (softc->action == PROBE_SETPM &&
799217444Smav		    status == CAM_ATA_STATUS_ERROR) {
800217444Smav			goto noerror;
801217875Smav
802217875Smav		/*
803217875Smav		 * Some HP SATA disks report supported DMA Auto-Activation,
804217875Smav		 * but return ABORT on attempt to enable it.
805217875Smav		 */
806217875Smav		} else if (softc->action == PROBE_SETDMAAA &&
807217875Smav		    status == CAM_ATA_STATUS_ERROR) {
808217875Smav			goto noerror;
809217444Smav		}
810217444Smav
811217444Smav		/*
812198708Smav		 * If we get to this point, we got an error status back
813198708Smav		 * from the inquiry and the error status doesn't require
814198708Smav		 * automatically retrying the command.  Therefore, the
815198708Smav		 * inquiry failed.  If we had inquiry information before
816198708Smav		 * for this device, but this latest inquiry command failed,
817198708Smav		 * the device has probably gone away.  If this device isn't
818198708Smav		 * already marked unconfigured, notify the peripheral
819198708Smav		 * drivers that this device is no more.
820198708Smav		 */
821209744Smavdevice_fail:	if ((path->device->flags & CAM_DEV_UNCONFIGURED) == 0)
822198708Smav			xpt_async(AC_LOST_DEVICE, path, NULL);
823198708Smav		found = 0;
824198708Smav		goto done;
825198708Smav	}
826198708Smavnoerror:
827203385Smav	if (softc->restart)
828203385Smav		goto done;
829198708Smav	switch (softc->action) {
830198708Smav	case PROBE_RESET:
831195534Sscottl	{
832198708Smav		int sign = (done_ccb->ataio.res.lba_high << 8) +
833198708Smav		    done_ccb->ataio.res.lba_mid;
834200218Smav		if (bootverbose)
835200218Smav			xpt_print(path, "SIGNATURE: %04x\n", sign);
836198708Smav		if (sign == 0x0000 &&
837198708Smav		    done_ccb->ccb_h.target_id != 15) {
838198708Smav			path->device->protocol = PROTO_ATA;
839198708Smav			PROBE_SET_ACTION(softc, PROBE_IDENTIFY);
840198708Smav		} else if (sign == 0x9669 &&
841198708Smav		    done_ccb->ccb_h.target_id == 15) {
842199747Smav			/* Report SIM that PM is present. */
843198708Smav			bzero(&cts, sizeof(cts));
844203108Smav			xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE);
845198708Smav			cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
846198708Smav			cts.type = CTS_TYPE_CURRENT_SETTINGS;
847198708Smav			cts.xport_specific.sata.pm_present = 1;
848198708Smav			cts.xport_specific.sata.valid = CTS_SATA_VALID_PM;
849198708Smav			xpt_action((union ccb *)&cts);
850198708Smav			path->device->protocol = PROTO_SATAPM;
851198708Smav			PROBE_SET_ACTION(softc, PROBE_PM_PID);
852198708Smav		} else if (sign == 0xeb14 &&
853198708Smav		    done_ccb->ccb_h.target_id != 15) {
854198708Smav			path->device->protocol = PROTO_SCSI;
855198708Smav			PROBE_SET_ACTION(softc, PROBE_IDENTIFY);
856198708Smav		} else {
857198708Smav			if (done_ccb->ccb_h.target_id != 15) {
858198708Smav				xpt_print(path,
859198708Smav				    "Unexpected signature 0x%04x\n", sign);
860195534Sscottl			}
861198708Smav			goto device_fail;
862198708Smav		}
863198708Smav		xpt_release_ccb(done_ccb);
864198708Smav		xpt_schedule(periph, priority);
865198708Smav		return;
866198708Smav	}
867198708Smav	case PROBE_IDENTIFY:
868198708Smav	{
869207222Smav		struct ccb_pathinq cpi;
870198708Smav		int16_t *ptr;
871207282Smav		int changed = 1;
872195534Sscottl
873203385Smav		ident_buf = &softc->ident_data;
874198708Smav		for (ptr = (int16_t *)ident_buf;
875198708Smav		     ptr < (int16_t *)ident_buf + sizeof(struct ata_params)/2; ptr++) {
876198708Smav			*ptr = le16toh(*ptr);
877198708Smav		}
878198708Smav		if (strncmp(ident_buf->model, "FX", 2) &&
879198708Smav		    strncmp(ident_buf->model, "NEC", 3) &&
880198708Smav		    strncmp(ident_buf->model, "Pioneer", 7) &&
881198708Smav		    strncmp(ident_buf->model, "SHARP", 5)) {
882198708Smav			ata_bswap(ident_buf->model, sizeof(ident_buf->model));
883198708Smav			ata_bswap(ident_buf->revision, sizeof(ident_buf->revision));
884198708Smav			ata_bswap(ident_buf->serial, sizeof(ident_buf->serial));
885198708Smav		}
886198708Smav		ata_btrim(ident_buf->model, sizeof(ident_buf->model));
887198708Smav		ata_bpack(ident_buf->model, ident_buf->model, sizeof(ident_buf->model));
888198708Smav		ata_btrim(ident_buf->revision, sizeof(ident_buf->revision));
889198708Smav		ata_bpack(ident_buf->revision, ident_buf->revision, sizeof(ident_buf->revision));
890198708Smav		ata_btrim(ident_buf->serial, sizeof(ident_buf->serial));
891198708Smav		ata_bpack(ident_buf->serial, ident_buf->serial, sizeof(ident_buf->serial));
892203421Smav		/* Device may need spin-up before IDENTIFY become valid. */
893204354Smav		if ((ident_buf->specconf == 0x37c8 ||
894204354Smav		     ident_buf->specconf == 0x738c) &&
895204354Smav		    ((ident_buf->config & ATA_RESP_INCOMPLETE) ||
896204354Smav		     softc->spinup == 0)) {
897203421Smav			PROBE_SET_ACTION(softc, PROBE_SPINUP);
898203421Smav			xpt_release_ccb(done_ccb);
899203421Smav			xpt_schedule(periph, priority);
900203421Smav			return;
901203421Smav		}
902203385Smav		ident_buf = &path->device->ident_data;
903198708Smav		if ((periph->path->device->flags & CAM_DEV_UNCONFIGURED) == 0) {
904198708Smav			/* Check that it is the same device. */
905203385Smav			if (bcmp(softc->ident_data.model, ident_buf->model,
906203385Smav			     sizeof(ident_buf->model)) ||
907203385Smav			    bcmp(softc->ident_data.revision, ident_buf->revision,
908203385Smav			     sizeof(ident_buf->revision)) ||
909203385Smav			    bcmp(softc->ident_data.serial, ident_buf->serial,
910203385Smav			     sizeof(ident_buf->serial))) {
911198708Smav				/* Device changed. */
912198708Smav				xpt_async(AC_LOST_DEVICE, path, NULL);
913207282Smav			} else {
914203385Smav				bcopy(&softc->ident_data, ident_buf, sizeof(struct ata_params));
915207282Smav				changed = 0;
916207282Smav			}
917207282Smav		}
918207282Smav		if (changed) {
919203385Smav			bcopy(&softc->ident_data, ident_buf, sizeof(struct ata_params));
920195534Sscottl			/* Clean up from previous instance of this device */
921195534Sscottl			if (path->device->serial_num != NULL) {
922195534Sscottl				free(path->device->serial_num, M_CAMXPT);
923195534Sscottl				path->device->serial_num = NULL;
924195534Sscottl				path->device->serial_num_len = 0;
925195534Sscottl			}
926195534Sscottl			path->device->serial_num =
927195534Sscottl				(u_int8_t *)malloc((sizeof(ident_buf->serial) + 1),
928198708Smav					   M_CAMXPT, M_NOWAIT);
929195534Sscottl			if (path->device->serial_num != NULL) {
930195534Sscottl				bcopy(ident_buf->serial,
931195534Sscottl				      path->device->serial_num,
932195534Sscottl				      sizeof(ident_buf->serial));
933195534Sscottl				path->device->serial_num[sizeof(ident_buf->serial)]
934195534Sscottl				    = '\0';
935195534Sscottl				path->device->serial_num_len =
936195534Sscottl				    strlen(path->device->serial_num);
937195534Sscottl			}
938195534Sscottl
939198331Smav			path->device->flags |= CAM_DEV_IDENTIFY_DATA_VALID;
940195534Sscottl		}
941199178Smav		if (ident_buf->satacapabilities & ATA_SUPPORT_NCQ) {
942199178Smav			path->device->mintags = path->device->maxtags =
943199178Smav			    ATA_QUEUE_LEN(ident_buf->queue) + 1;
944199178Smav		}
945199178Smav		ata_find_quirk(path->device);
946199263Smav		if (path->device->mintags != 0 &&
947199263Smav		    path->bus->sim->max_tagged_dev_openings != 0) {
948207222Smav			/* Check if the SIM does not want queued commands. */
949207222Smav			bzero(&cpi, sizeof(cpi));
950207222Smav			xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NONE);
951207222Smav			cpi.ccb_h.func_code = XPT_PATH_INQ;
952207222Smav			xpt_action((union ccb *)&cpi);
953207222Smav			if (cpi.ccb_h.status == CAM_REQ_CMP &&
954207222Smav			    (cpi.hba_inquiry & PI_TAG_ABLE)) {
955207222Smav				/* Report SIM which tags are allowed. */
956207222Smav				bzero(&cts, sizeof(cts));
957207222Smav				xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE);
958207222Smav				cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
959207222Smav				cts.type = CTS_TYPE_CURRENT_SETTINGS;
960207222Smav				cts.xport_specific.sata.tags = path->device->maxtags;
961207222Smav				cts.xport_specific.sata.valid = CTS_SATA_VALID_TAGS;
962207222Smav				xpt_action((union ccb *)&cts);
963207222Smav				/* Reconfigure queues for tagged queueing. */
964207222Smav				xpt_start_tags(path);
965207222Smav			}
966199178Smav		}
967198708Smav		ata_device_transport(path);
968198708Smav		PROBE_SET_ACTION(softc, PROBE_SETMODE);
969195534Sscottl		xpt_release_ccb(done_ccb);
970198708Smav		xpt_schedule(periph, priority);
971198708Smav		return;
972195534Sscottl	}
973203421Smav	case PROBE_SPINUP:
974203421Smav		if (bootverbose)
975203421Smav			xpt_print(path, "Spin-up done\n");
976203421Smav		softc->spinup = 1;
977203421Smav		PROBE_SET_ACTION(softc, PROBE_IDENTIFY);
978203421Smav		xpt_release_ccb(done_ccb);
979203421Smav		xpt_schedule(periph, priority);
980203421Smav		return;
981195534Sscottl	case PROBE_SETMODE:
982207499Smav		if (path->device->transport != XPORT_SATA)
983207499Smav			goto notsata;
984207499Smav		/* Set supported bits. */
985207499Smav		bzero(&cts, sizeof(cts));
986207499Smav		xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE);
987207499Smav		cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
988207499Smav		cts.type = CTS_TYPE_CURRENT_SETTINGS;
989207499Smav		xpt_action((union ccb *)&cts);
990207499Smav		if (cts.xport_specific.sata.valid & CTS_SATA_VALID_CAPS)
991207499Smav			caps = cts.xport_specific.sata.caps & CTS_SATA_CAPS_H;
992207499Smav		else
993207499Smav			caps = 0;
994207499Smav		if (ident_buf->satacapabilities != 0xffff) {
995207499Smav			if (ident_buf->satacapabilities & ATA_SUPPORT_IFPWRMNGTRCV)
996207499Smav				caps |= CTS_SATA_CAPS_D_PMREQ;
997207499Smav			if (ident_buf->satacapabilities & ATA_SUPPORT_HAPST)
998207499Smav				caps |= CTS_SATA_CAPS_D_APST;
999207499Smav		}
1000207499Smav		/* Mask unwanted bits. */
1001207499Smav		bzero(&cts, sizeof(cts));
1002207499Smav		xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE);
1003207499Smav		cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
1004207499Smav		cts.type = CTS_TYPE_USER_SETTINGS;
1005207499Smav		xpt_action((union ccb *)&cts);
1006207499Smav		if (cts.xport_specific.sata.valid & CTS_SATA_VALID_CAPS)
1007207499Smav			caps &= cts.xport_specific.sata.caps;
1008215454Smav		else
1009215454Smav			caps = 0;
1010207499Smav		/* Store result to SIM. */
1011207499Smav		bzero(&cts, sizeof(cts));
1012207499Smav		xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE);
1013207499Smav		cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
1014207499Smav		cts.type = CTS_TYPE_CURRENT_SETTINGS;
1015207499Smav		cts.xport_specific.sata.caps = caps;
1016207499Smav		cts.xport_specific.sata.valid = CTS_SATA_VALID_CAPS;
1017207499Smav		xpt_action((union ccb *)&cts);
1018207499Smav		softc->caps = caps;
1019217874Smav		if ((ident_buf->satasupport & ATA_SUPPORT_IFPWRMNGT) &&
1020217874Smav		    (!(softc->caps & CTS_SATA_CAPS_H_PMREQ)) !=
1021217874Smav		    (!(ident_buf->sataenabled & ATA_SUPPORT_IFPWRMNGT))) {
1022207499Smav			PROBE_SET_ACTION(softc, PROBE_SETPM);
1023207499Smav			xpt_release_ccb(done_ccb);
1024207499Smav			xpt_schedule(periph, priority);
1025207499Smav			return;
1026207499Smav		}
1027207499Smav		/* FALLTHROUGH */
1028207499Smav	case PROBE_SETPM:
1029207499Smav		if (ident_buf->satacapabilities != 0xffff &&
1030217874Smav		    (ident_buf->satacapabilities & ATA_SUPPORT_DAPST) &&
1031217874Smav		    (!(softc->caps & CTS_SATA_CAPS_H_APST)) !=
1032217874Smav		    (!(ident_buf->sataenabled & ATA_ENABLED_DAPST))) {
1033207499Smav			PROBE_SET_ACTION(softc, PROBE_SETAPST);
1034207499Smav			xpt_release_ccb(done_ccb);
1035207499Smav			xpt_schedule(periph, priority);
1036207499Smav			return;
1037207499Smav		}
1038207499Smav		/* FALLTHROUGH */
1039207499Smav	case PROBE_SETAPST:
1040217874Smav		if ((ident_buf->satasupport & ATA_SUPPORT_AUTOACTIVATE) &&
1041217874Smav		    (!(softc->caps & CTS_SATA_CAPS_H_DMAAA)) !=
1042217874Smav		    (!(ident_buf->sataenabled & ATA_SUPPORT_AUTOACTIVATE))) {
1043207499Smav			PROBE_SET_ACTION(softc, PROBE_SETDMAAA);
1044207499Smav			xpt_release_ccb(done_ccb);
1045207499Smav			xpt_schedule(periph, priority);
1046207499Smav			return;
1047207499Smav		}
1048207499Smav		/* FALLTHROUGH */
1049207499Smav	case PROBE_SETDMAAA:
1050220602Smav		if ((ident_buf->satasupport & ATA_SUPPORT_ASYNCNOTIF) &&
1051220602Smav		    (!(softc->caps & CTS_SATA_CAPS_H_AN)) !=
1052220602Smav		    (!(ident_buf->sataenabled & ATA_SUPPORT_ASYNCNOTIF))) {
1053220602Smav			PROBE_SET_ACTION(softc, PROBE_SETAN);
1054220602Smav			xpt_release_ccb(done_ccb);
1055220602Smav			xpt_schedule(periph, priority);
1056220602Smav			return;
1057220602Smav		}
1058220602Smav		/* FALLTHROUGH */
1059220602Smav	case PROBE_SETAN:
1060207499Smavnotsata:
1061198708Smav		if (path->device->protocol == PROTO_ATA) {
1062198708Smav			PROBE_SET_ACTION(softc, PROBE_SET_MULTI);
1063198708Smav		} else {
1064198708Smav			PROBE_SET_ACTION(softc, PROBE_INQUIRY);
1065195534Sscottl		}
1066198708Smav		xpt_release_ccb(done_ccb);
1067198708Smav		xpt_schedule(periph, priority);
1068198708Smav		return;
1069198708Smav	case PROBE_SET_MULTI:
1070198708Smav		if (periph->path->device->flags & CAM_DEV_UNCONFIGURED) {
1071198708Smav			path->device->flags &= ~CAM_DEV_UNCONFIGURED;
1072198748Smav			xpt_acquire_device(path->device);
1073198708Smav			done_ccb->ccb_h.func_code = XPT_GDEV_TYPE;
1074198708Smav			xpt_action(done_ccb);
1075198708Smav			xpt_async(AC_FOUND_DEVICE, done_ccb->ccb_h.path,
1076198708Smav			    done_ccb);
1077198708Smav		}
1078198708Smav		break;
1079195534Sscottl	case PROBE_INQUIRY:
1080195534Sscottl	case PROBE_FULL_INQUIRY:
1081195534Sscottl	{
1082198708Smav		struct scsi_inquiry_data *inq_buf;
1083198708Smav		u_int8_t periph_qual, len;
1084195534Sscottl
1085198708Smav		path->device->flags |= CAM_DEV_INQUIRY_DATA_VALID;
1086198708Smav		inq_buf = &path->device->inq_data;
1087195534Sscottl
1088198708Smav		periph_qual = SID_QUAL(inq_buf);
1089195534Sscottl
1090198708Smav		if (periph_qual != SID_QUAL_LU_CONNECTED)
1091198708Smav			break;
1092195534Sscottl
1093198708Smav		/*
1094198708Smav		 * We conservatively request only
1095198708Smav		 * SHORT_INQUIRY_LEN bytes of inquiry
1096198708Smav		 * information during our first try
1097198708Smav		 * at sending an INQUIRY. If the device
1098198708Smav		 * has more information to give,
1099198708Smav		 * perform a second request specifying
1100198708Smav		 * the amount of information the device
1101198708Smav		 * is willing to give.
1102198708Smav		 */
1103198708Smav		len = inq_buf->additional_length
1104198708Smav		    + offsetof(struct scsi_inquiry_data, additional_length) + 1;
1105198708Smav		if (softc->action == PROBE_INQUIRY
1106198708Smav		    && len > SHORT_INQUIRY_LENGTH) {
1107198708Smav			PROBE_SET_ACTION(softc, PROBE_FULL_INQUIRY);
1108198708Smav			xpt_release_ccb(done_ccb);
1109198708Smav			xpt_schedule(periph, priority);
1110195534Sscottl			return;
1111195534Sscottl		}
1112198708Smav
1113198708Smav		ata_device_transport(path);
1114198708Smav		if (periph->path->device->flags & CAM_DEV_UNCONFIGURED) {
1115198708Smav			path->device->flags &= ~CAM_DEV_UNCONFIGURED;
1116198748Smav			xpt_acquire_device(path->device);
1117198708Smav			done_ccb->ccb_h.func_code = XPT_GDEV_TYPE;
1118198708Smav			xpt_action(done_ccb);
1119198708Smav			xpt_async(AC_FOUND_DEVICE, done_ccb->ccb_h.path, done_ccb);
1120198708Smav		}
1121198708Smav		break;
1122195534Sscottl	}
1123195534Sscottl	case PROBE_PM_PID:
1124198708Smav		if ((path->device->flags & CAM_DEV_IDENTIFY_DATA_VALID) == 0)
1125198708Smav			bzero(ident_buf, sizeof(*ident_buf));
1126198708Smav		softc->pm_pid = (done_ccb->ataio.res.lba_high << 24) +
1127198708Smav		    (done_ccb->ataio.res.lba_mid << 16) +
1128198708Smav		    (done_ccb->ataio.res.lba_low << 8) +
1129198708Smav		    done_ccb->ataio.res.sector_count;
1130198708Smav		((uint32_t *)ident_buf)[0] = softc->pm_pid;
1131198708Smav		snprintf(ident_buf->model, sizeof(ident_buf->model),
1132198708Smav		    "Port Multiplier %08x", softc->pm_pid);
1133198708Smav		PROBE_SET_ACTION(softc, PROBE_PM_PRV);
1134198708Smav		xpt_release_ccb(done_ccb);
1135198708Smav		xpt_schedule(periph, priority);
1136198708Smav		return;
1137195534Sscottl	case PROBE_PM_PRV:
1138198708Smav		softc->pm_prv = (done_ccb->ataio.res.lba_high << 24) +
1139198708Smav		    (done_ccb->ataio.res.lba_mid << 16) +
1140198708Smav		    (done_ccb->ataio.res.lba_low << 8) +
1141198708Smav		    done_ccb->ataio.res.sector_count;
1142198708Smav		((uint32_t *)ident_buf)[1] = softc->pm_prv;
1143198708Smav		snprintf(ident_buf->revision, sizeof(ident_buf->revision),
1144198708Smav		    "%04x", softc->pm_prv);
1145198708Smav		path->device->flags |= CAM_DEV_IDENTIFY_DATA_VALID;
1146207499Smav		/* Set supported bits. */
1147207499Smav		bzero(&cts, sizeof(cts));
1148207499Smav		xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE);
1149207499Smav		cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
1150207499Smav		cts.type = CTS_TYPE_CURRENT_SETTINGS;
1151207499Smav		xpt_action((union ccb *)&cts);
1152207499Smav		if (cts.xport_specific.sata.valid & CTS_SATA_VALID_CAPS)
1153207499Smav			caps = cts.xport_specific.sata.caps & CTS_SATA_CAPS_H;
1154207499Smav		else
1155207499Smav			caps = 0;
1156207499Smav		/* All PMPs must support PM requests. */
1157207499Smav		caps |= CTS_SATA_CAPS_D_PMREQ;
1158207499Smav		/* Mask unwanted bits. */
1159207499Smav		bzero(&cts, sizeof(cts));
1160207499Smav		xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE);
1161207499Smav		cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
1162207499Smav		cts.type = CTS_TYPE_USER_SETTINGS;
1163207499Smav		xpt_action((union ccb *)&cts);
1164207499Smav		if (cts.xport_specific.sata.valid & CTS_SATA_VALID_CAPS)
1165207499Smav			caps &= cts.xport_specific.sata.caps;
1166215454Smav		else
1167215454Smav			caps = 0;
1168207499Smav		/* Store result to SIM. */
1169207499Smav		bzero(&cts, sizeof(cts));
1170207499Smav		xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE);
1171207499Smav		cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
1172207499Smav		cts.type = CTS_TYPE_CURRENT_SETTINGS;
1173207499Smav		cts.xport_specific.sata.caps = caps;
1174207499Smav		cts.xport_specific.sata.valid = CTS_SATA_VALID_CAPS;
1175207499Smav		xpt_action((union ccb *)&cts);
1176207499Smav		softc->caps = caps;
1177198708Smav		if (periph->path->device->flags & CAM_DEV_UNCONFIGURED) {
1178198708Smav			path->device->flags &= ~CAM_DEV_UNCONFIGURED;
1179198748Smav			xpt_acquire_device(path->device);
1180198708Smav			done_ccb->ccb_h.func_code = XPT_GDEV_TYPE;
1181198708Smav			xpt_action(done_ccb);
1182198708Smav			xpt_async(AC_FOUND_DEVICE, done_ccb->ccb_h.path,
1183198708Smav			    done_ccb);
1184198708Smav		} else {
1185198708Smav			done_ccb->ccb_h.func_code = XPT_GDEV_TYPE;
1186198708Smav			xpt_action(done_ccb);
1187198708Smav			xpt_async(AC_SCSI_AEN, done_ccb->ccb_h.path, done_ccb);
1188195534Sscottl		}
1189198708Smav		break;
1190195534Sscottl	case PROBE_INVALID:
1191195534Sscottl		CAM_DEBUG(done_ccb->ccb_h.path, CAM_DEBUG_INFO,
1192195534Sscottl		    ("probedone: invalid action state\n"));
1193195534Sscottl	default:
1194195534Sscottl		break;
1195195534Sscottl	}
1196198708Smavdone:
1197203108Smav	if (softc->restart) {
1198203108Smav		softc->restart = 0;
1199203108Smav		xpt_release_ccb(done_ccb);
1200195534Sscottl		probeschedule(periph);
1201203108Smav		return;
1202195534Sscottl	}
1203203108Smav	xpt_release_ccb(done_ccb);
1204203108Smav	while ((done_ccb = (union ccb *)TAILQ_FIRST(&softc->request_ccbs))) {
1205203108Smav		TAILQ_REMOVE(&softc->request_ccbs,
1206203108Smav		    &done_ccb->ccb_h, periph_links.tqe);
1207203108Smav		done_ccb->ccb_h.status = found ? CAM_REQ_CMP : CAM_REQ_CMP_ERR;
1208203108Smav		xpt_done(done_ccb);
1209203108Smav	}
1210203108Smav	cam_release_devq(periph->path,
1211203108Smav	    RELSIM_RELEASE_RUNLEVEL, 0, CAM_RL_XPT + 1, FALSE);
1212203108Smav	cam_periph_invalidate(periph);
1213203108Smav	cam_periph_release_locked(periph);
1214195534Sscottl}
1215195534Sscottl
1216195534Sscottlstatic void
1217195534Sscottlprobecleanup(struct cam_periph *periph)
1218195534Sscottl{
1219195534Sscottl	free(periph->softc, M_CAMXPT);
1220195534Sscottl}
1221195534Sscottl
1222195534Sscottlstatic void
1223199178Smavata_find_quirk(struct cam_ed *device)
1224195534Sscottl{
1225199178Smav	struct ata_quirk_entry *quirk;
1226195534Sscottl	caddr_t	match;
1227195534Sscottl
1228199178Smav	match = cam_quirkmatch((caddr_t)&device->ident_data,
1229199178Smav			       (caddr_t)ata_quirk_table,
1230199178Smav			       ata_quirk_table_size,
1231199178Smav			       sizeof(*ata_quirk_table), ata_identify_match);
1232195534Sscottl
1233195534Sscottl	if (match == NULL)
1234195534Sscottl		panic("xpt_find_quirk: device didn't match wildcard entry!!");
1235195534Sscottl
1236199178Smav	quirk = (struct ata_quirk_entry *)match;
1237195534Sscottl	device->quirk = quirk;
1238199178Smav	if (quirk->quirks & CAM_QUIRK_MAXTAGS)
1239199178Smav		device->mintags = device->maxtags = quirk->maxtags;
1240195534Sscottl}
1241195534Sscottl
1242195534Sscottltypedef struct {
1243195534Sscottl	union	ccb *request_ccb;
1244195534Sscottl	struct 	ccb_pathinq *cpi;
1245195534Sscottl	int	counter;
1246195534Sscottl} ata_scan_bus_info;
1247195534Sscottl
1248195534Sscottl/*
1249195534Sscottl * To start a scan, request_ccb is an XPT_SCAN_BUS ccb.
1250195534Sscottl * As the scan progresses, xpt_scan_bus is used as the
1251195534Sscottl * callback on completion function.
1252195534Sscottl */
1253195534Sscottlstatic void
1254195534Sscottlata_scan_bus(struct cam_periph *periph, union ccb *request_ccb)
1255195534Sscottl{
1256195534Sscottl	struct	cam_path *path;
1257195534Sscottl	ata_scan_bus_info *scan_info;
1258203108Smav	union	ccb *work_ccb, *reset_ccb;
1259195534Sscottl	cam_status status;
1260195534Sscottl
1261195534Sscottl	CAM_DEBUG(request_ccb->ccb_h.path, CAM_DEBUG_TRACE,
1262195534Sscottl		  ("xpt_scan_bus\n"));
1263195534Sscottl	switch (request_ccb->ccb_h.func_code) {
1264195534Sscottl	case XPT_SCAN_BUS:
1265208582Smjacob	case XPT_SCAN_TGT:
1266195534Sscottl		/* Find out the characteristics of the bus */
1267195534Sscottl		work_ccb = xpt_alloc_ccb_nowait();
1268195534Sscottl		if (work_ccb == NULL) {
1269195534Sscottl			request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
1270195534Sscottl			xpt_done(request_ccb);
1271195534Sscottl			return;
1272195534Sscottl		}
1273195534Sscottl		xpt_setup_ccb(&work_ccb->ccb_h, request_ccb->ccb_h.path,
1274195534Sscottl			      request_ccb->ccb_h.pinfo.priority);
1275195534Sscottl		work_ccb->ccb_h.func_code = XPT_PATH_INQ;
1276195534Sscottl		xpt_action(work_ccb);
1277195534Sscottl		if (work_ccb->ccb_h.status != CAM_REQ_CMP) {
1278195534Sscottl			request_ccb->ccb_h.status = work_ccb->ccb_h.status;
1279195534Sscottl			xpt_free_ccb(work_ccb);
1280195534Sscottl			xpt_done(request_ccb);
1281195534Sscottl			return;
1282195534Sscottl		}
1283195534Sscottl
1284203108Smav		/* We may need to reset bus first, if we haven't done it yet. */
1285203108Smav		if ((work_ccb->cpi.hba_inquiry &
1286203108Smav		    (PI_WIDE_32|PI_WIDE_16|PI_SDTR_ABLE)) &&
1287203108Smav		    !(work_ccb->cpi.hba_misc & PIM_NOBUSRESET) &&
1288203108Smav		    !timevalisset(&request_ccb->ccb_h.path->bus->last_reset)) {
1289203108Smav			reset_ccb = xpt_alloc_ccb_nowait();
1290208823Smav			if (reset_ccb == NULL) {
1291208823Smav				request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
1292208823Smav				xpt_free_ccb(work_ccb);
1293208823Smav				xpt_done(request_ccb);
1294208823Smav				return;
1295208823Smav			}
1296203108Smav			xpt_setup_ccb(&reset_ccb->ccb_h, request_ccb->ccb_h.path,
1297203108Smav			      CAM_PRIORITY_NONE);
1298203108Smav			reset_ccb->ccb_h.func_code = XPT_RESET_BUS;
1299203108Smav			xpt_action(reset_ccb);
1300203108Smav			if (reset_ccb->ccb_h.status != CAM_REQ_CMP) {
1301203108Smav				request_ccb->ccb_h.status = reset_ccb->ccb_h.status;
1302203108Smav				xpt_free_ccb(reset_ccb);
1303203108Smav				xpt_free_ccb(work_ccb);
1304203108Smav				xpt_done(request_ccb);
1305203108Smav				return;
1306203108Smav			}
1307203108Smav			xpt_free_ccb(reset_ccb);
1308203108Smav		}
1309203108Smav
1310195534Sscottl		/* Save some state for use while we probe for devices */
1311195534Sscottl		scan_info = (ata_scan_bus_info *)
1312195534Sscottl		    malloc(sizeof(ata_scan_bus_info), M_CAMXPT, M_NOWAIT);
1313195534Sscottl		if (scan_info == NULL) {
1314195534Sscottl			request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
1315208823Smav			xpt_free_ccb(work_ccb);
1316195534Sscottl			xpt_done(request_ccb);
1317195534Sscottl			return;
1318195534Sscottl		}
1319195534Sscottl		scan_info->request_ccb = request_ccb;
1320195534Sscottl		scan_info->cpi = &work_ccb->cpi;
1321195534Sscottl		/* If PM supported, probe it first. */
1322195534Sscottl		if (scan_info->cpi->hba_inquiry & PI_SATAPM)
1323201990Smav			scan_info->counter = scan_info->cpi->max_target;
1324201990Smav		else
1325201990Smav			scan_info->counter = 0;
1326195534Sscottl
1327195534Sscottl		work_ccb = xpt_alloc_ccb_nowait();
1328195534Sscottl		if (work_ccb == NULL) {
1329195534Sscottl			free(scan_info, M_CAMXPT);
1330195534Sscottl			request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
1331195534Sscottl			xpt_done(request_ccb);
1332195534Sscottl			break;
1333195534Sscottl		}
1334195534Sscottl		goto scan_next;
1335195534Sscottl	case XPT_SCAN_LUN:
1336195534Sscottl		work_ccb = request_ccb;
1337195534Sscottl		/* Reuse the same CCB to query if a device was really found */
1338195534Sscottl		scan_info = (ata_scan_bus_info *)work_ccb->ccb_h.ppriv_ptr0;
1339198389Smav		/* If there is PMP... */
1340201990Smav		if ((scan_info->cpi->hba_inquiry & PI_SATAPM) &&
1341201990Smav		    (scan_info->counter == scan_info->cpi->max_target)) {
1342203108Smav			if (work_ccb->ccb_h.status == CAM_REQ_CMP) {
1343207428Smav				/* everything else will be probed by it */
1344207428Smav				/* Free the current request path- we're done with it. */
1345207428Smav				xpt_free_path(work_ccb->ccb_h.path);
1346201990Smav				goto done;
1347195534Sscottl			} else {
1348195534Sscottl				struct ccb_trans_settings cts;
1349195534Sscottl
1350195534Sscottl				/* Report SIM that PM is absent. */
1351195534Sscottl				bzero(&cts, sizeof(cts));
1352195534Sscottl				xpt_setup_ccb(&cts.ccb_h,
1353207428Smav				    work_ccb->ccb_h.path, CAM_PRIORITY_NONE);
1354195534Sscottl				cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
1355195534Sscottl				cts.type = CTS_TYPE_CURRENT_SETTINGS;
1356195665Smav				cts.xport_specific.sata.pm_present = 0;
1357195534Sscottl				cts.xport_specific.sata.valid = CTS_SATA_VALID_PM;
1358195534Sscottl				xpt_action((union ccb *)&cts);
1359195534Sscottl			}
1360195534Sscottl		}
1361207428Smav		/* Free the current request path- we're done with it. */
1362207428Smav		xpt_free_path(work_ccb->ccb_h.path);
1363201990Smav		if (scan_info->counter ==
1364201990Smav		    ((scan_info->cpi->hba_inquiry & PI_SATAPM) ?
1365201990Smav		    0 : scan_info->cpi->max_target)) {
1366201990Smavdone:
1367195534Sscottl			xpt_free_ccb(work_ccb);
1368195534Sscottl			xpt_free_ccb((union ccb *)scan_info->cpi);
1369195534Sscottl			request_ccb = scan_info->request_ccb;
1370195534Sscottl			free(scan_info, M_CAMXPT);
1371195534Sscottl			request_ccb->ccb_h.status = CAM_REQ_CMP;
1372195534Sscottl			xpt_done(request_ccb);
1373195534Sscottl			break;
1374195534Sscottl		}
1375201990Smav		/* Take next device. Wrap from max (PMP) to 0. */
1376201990Smav		scan_info->counter = (scan_info->counter + 1 ) %
1377201990Smav		    (scan_info->cpi->max_target + 1);
1378195534Sscottlscan_next:
1379195534Sscottl		status = xpt_create_path(&path, xpt_periph,
1380195534Sscottl		    scan_info->request_ccb->ccb_h.path_id,
1381195534Sscottl		    scan_info->counter, 0);
1382195534Sscottl		if (status != CAM_REQ_CMP) {
1383195534Sscottl			printf("xpt_scan_bus: xpt_create_path failed"
1384195534Sscottl			    " with status %#x, bus scan halted\n",
1385195534Sscottl			    status);
1386195534Sscottl			xpt_free_ccb(work_ccb);
1387195534Sscottl			xpt_free_ccb((union ccb *)scan_info->cpi);
1388195534Sscottl			request_ccb = scan_info->request_ccb;
1389195534Sscottl			free(scan_info, M_CAMXPT);
1390195534Sscottl			request_ccb->ccb_h.status = status;
1391195534Sscottl			xpt_done(request_ccb);
1392195534Sscottl			break;
1393195534Sscottl		}
1394195534Sscottl		xpt_setup_ccb(&work_ccb->ccb_h, path,
1395195534Sscottl		    scan_info->request_ccb->ccb_h.pinfo.priority);
1396195534Sscottl		work_ccb->ccb_h.func_code = XPT_SCAN_LUN;
1397195534Sscottl		work_ccb->ccb_h.cbfcnp = ata_scan_bus;
1398195534Sscottl		work_ccb->ccb_h.ppriv_ptr0 = scan_info;
1399195534Sscottl		work_ccb->crcn.flags = scan_info->request_ccb->crcn.flags;
1400195534Sscottl		xpt_action(work_ccb);
1401195534Sscottl		break;
1402195534Sscottl	default:
1403195534Sscottl		break;
1404195534Sscottl	}
1405195534Sscottl}
1406195534Sscottl
1407195534Sscottlstatic void
1408195534Sscottlata_scan_lun(struct cam_periph *periph, struct cam_path *path,
1409195534Sscottl	     cam_flags flags, union ccb *request_ccb)
1410195534Sscottl{
1411195534Sscottl	struct ccb_pathinq cpi;
1412195534Sscottl	cam_status status;
1413195534Sscottl	struct cam_path *new_path;
1414195534Sscottl	struct cam_periph *old_periph;
1415195534Sscottl
1416203108Smav	CAM_DEBUG(path, CAM_DEBUG_TRACE, ("xpt_scan_lun\n"));
1417195534Sscottl
1418203108Smav	xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NONE);
1419195534Sscottl	cpi.ccb_h.func_code = XPT_PATH_INQ;
1420195534Sscottl	xpt_action((union ccb *)&cpi);
1421195534Sscottl
1422195534Sscottl	if (cpi.ccb_h.status != CAM_REQ_CMP) {
1423195534Sscottl		if (request_ccb != NULL) {
1424195534Sscottl			request_ccb->ccb_h.status = cpi.ccb_h.status;
1425195534Sscottl			xpt_done(request_ccb);
1426195534Sscottl		}
1427195534Sscottl		return;
1428195534Sscottl	}
1429195534Sscottl
1430195534Sscottl	if (request_ccb == NULL) {
1431195534Sscottl		request_ccb = malloc(sizeof(union ccb), M_CAMXPT, M_NOWAIT);
1432195534Sscottl		if (request_ccb == NULL) {
1433195534Sscottl			xpt_print(path, "xpt_scan_lun: can't allocate CCB, "
1434195534Sscottl			    "can't continue\n");
1435195534Sscottl			return;
1436195534Sscottl		}
1437195534Sscottl		new_path = malloc(sizeof(*new_path), M_CAMXPT, M_NOWAIT);
1438195534Sscottl		if (new_path == NULL) {
1439195534Sscottl			xpt_print(path, "xpt_scan_lun: can't allocate path, "
1440195534Sscottl			    "can't continue\n");
1441195534Sscottl			free(request_ccb, M_CAMXPT);
1442195534Sscottl			return;
1443195534Sscottl		}
1444195534Sscottl		status = xpt_compile_path(new_path, xpt_periph,
1445195534Sscottl					  path->bus->path_id,
1446195534Sscottl					  path->target->target_id,
1447195534Sscottl					  path->device->lun_id);
1448195534Sscottl
1449195534Sscottl		if (status != CAM_REQ_CMP) {
1450195534Sscottl			xpt_print(path, "xpt_scan_lun: can't compile path, "
1451195534Sscottl			    "can't continue\n");
1452195534Sscottl			free(request_ccb, M_CAMXPT);
1453195534Sscottl			free(new_path, M_CAMXPT);
1454195534Sscottl			return;
1455195534Sscottl		}
1456203108Smav		xpt_setup_ccb(&request_ccb->ccb_h, new_path, CAM_PRIORITY_XPT);
1457195534Sscottl		request_ccb->ccb_h.cbfcnp = xptscandone;
1458195534Sscottl		request_ccb->ccb_h.func_code = XPT_SCAN_LUN;
1459195534Sscottl		request_ccb->crcn.flags = flags;
1460195534Sscottl	}
1461195534Sscottl
1462195653Smav	if ((old_periph = cam_periph_find(path, "aprobe")) != NULL) {
1463195534Sscottl		probe_softc *softc;
1464195534Sscottl
1465195534Sscottl		softc = (probe_softc *)old_periph->softc;
1466195534Sscottl		TAILQ_INSERT_TAIL(&softc->request_ccbs, &request_ccb->ccb_h,
1467195534Sscottl				  periph_links.tqe);
1468203108Smav		softc->restart = 1;
1469195534Sscottl	} else {
1470195534Sscottl		status = cam_periph_alloc(proberegister, NULL, probecleanup,
1471195653Smav					  probestart, "aprobe",
1472195534Sscottl					  CAM_PERIPH_BIO,
1473195534Sscottl					  request_ccb->ccb_h.path, NULL, 0,
1474195534Sscottl					  request_ccb);
1475195534Sscottl
1476195534Sscottl		if (status != CAM_REQ_CMP) {
1477195534Sscottl			xpt_print(path, "xpt_scan_lun: cam_alloc_periph "
1478195534Sscottl			    "returned an error, can't continue probe\n");
1479195534Sscottl			request_ccb->ccb_h.status = status;
1480195534Sscottl			xpt_done(request_ccb);
1481195534Sscottl		}
1482195534Sscottl	}
1483195534Sscottl}
1484195534Sscottl
1485195534Sscottlstatic void
1486195534Sscottlxptscandone(struct cam_periph *periph, union ccb *done_ccb)
1487195534Sscottl{
1488195534Sscottl	xpt_release_path(done_ccb->ccb_h.path);
1489195534Sscottl	free(done_ccb->ccb_h.path, M_CAMXPT);
1490195534Sscottl	free(done_ccb, M_CAMXPT);
1491195534Sscottl}
1492195534Sscottl
1493195534Sscottlstatic struct cam_ed *
1494195534Sscottlata_alloc_device(struct cam_eb *bus, struct cam_et *target, lun_id_t lun_id)
1495195534Sscottl{
1496195534Sscottl	struct cam_path path;
1497199178Smav	struct ata_quirk_entry *quirk;
1498195534Sscottl	struct cam_ed *device;
1499195534Sscottl	struct cam_ed *cur_device;
1500195534Sscottl
1501195534Sscottl	device = xpt_alloc_device(bus, target, lun_id);
1502195534Sscottl	if (device == NULL)
1503195534Sscottl		return (NULL);
1504195534Sscottl
1505195534Sscottl	/*
1506195534Sscottl	 * Take the default quirk entry until we have inquiry
1507195534Sscottl	 * data and can determine a better quirk to use.
1508195534Sscottl	 */
1509199178Smav	quirk = &ata_quirk_table[ata_quirk_table_size - 1];
1510195534Sscottl	device->quirk = (void *)quirk;
1511199178Smav	device->mintags = 0;
1512199178Smav	device->maxtags = 0;
1513195534Sscottl	bzero(&device->inq_data, sizeof(device->inq_data));
1514195534Sscottl	device->inq_flags = 0;
1515195534Sscottl	device->queue_flags = 0;
1516195534Sscottl	device->serial_num = NULL;
1517195534Sscottl	device->serial_num_len = 0;
1518195534Sscottl
1519195534Sscottl	/*
1520195534Sscottl	 * XXX should be limited by number of CCBs this bus can
1521195534Sscottl	 * do.
1522195534Sscottl	 */
1523195534Sscottl	bus->sim->max_ccbs += device->ccbq.devq_openings;
1524195534Sscottl	/* Insertion sort into our target's device list */
1525195534Sscottl	cur_device = TAILQ_FIRST(&target->ed_entries);
1526195534Sscottl	while (cur_device != NULL && cur_device->lun_id < lun_id)
1527195534Sscottl		cur_device = TAILQ_NEXT(cur_device, links);
1528195534Sscottl	if (cur_device != NULL) {
1529195534Sscottl		TAILQ_INSERT_BEFORE(cur_device, device, links);
1530195534Sscottl	} else {
1531195534Sscottl		TAILQ_INSERT_TAIL(&target->ed_entries, device, links);
1532195534Sscottl	}
1533195534Sscottl	target->generation++;
1534195534Sscottl	if (lun_id != CAM_LUN_WILDCARD) {
1535195534Sscottl		xpt_compile_path(&path,
1536195534Sscottl				 NULL,
1537195534Sscottl				 bus->path_id,
1538195534Sscottl				 target->target_id,
1539195534Sscottl				 lun_id);
1540195534Sscottl		ata_device_transport(&path);
1541195534Sscottl		xpt_release_path(&path);
1542195534Sscottl	}
1543195534Sscottl
1544195534Sscottl	return (device);
1545195534Sscottl}
1546195534Sscottl
1547195534Sscottlstatic void
1548195534Sscottlata_device_transport(struct cam_path *path)
1549195534Sscottl{
1550195534Sscottl	struct ccb_pathinq cpi;
1551198331Smav	struct ccb_trans_settings cts;
1552198331Smav	struct scsi_inquiry_data *inq_buf = NULL;
1553198331Smav	struct ata_params *ident_buf = NULL;
1554195534Sscottl
1555195534Sscottl	/* Get transport information from the SIM */
1556203108Smav	xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NONE);
1557195534Sscottl	cpi.ccb_h.func_code = XPT_PATH_INQ;
1558195534Sscottl	xpt_action((union ccb *)&cpi);
1559195534Sscottl
1560195534Sscottl	path->device->transport = cpi.transport;
1561198331Smav	if ((path->device->flags & CAM_DEV_INQUIRY_DATA_VALID) != 0)
1562198331Smav		inq_buf = &path->device->inq_data;
1563198331Smav	if ((path->device->flags & CAM_DEV_IDENTIFY_DATA_VALID) != 0)
1564198331Smav		ident_buf = &path->device->ident_data;
1565198331Smav	if (path->device->protocol == PROTO_ATA) {
1566198331Smav		path->device->protocol_version = ident_buf ?
1567198331Smav		    ata_version(ident_buf->version_major) : cpi.protocol_version;
1568198331Smav	} else if (path->device->protocol == PROTO_SCSI) {
1569198331Smav		path->device->protocol_version = inq_buf ?
1570198331Smav		    SID_ANSI_REV(inq_buf) : cpi.protocol_version;
1571195534Sscottl	}
1572198331Smav	path->device->transport_version = ident_buf ?
1573198331Smav	    ata_version(ident_buf->version_major) : cpi.transport_version;
1574195534Sscottl
1575195534Sscottl	/* Tell the controller what we think */
1576203108Smav	xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE);
1577195534Sscottl	cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
1578195534Sscottl	cts.type = CTS_TYPE_CURRENT_SETTINGS;
1579195534Sscottl	cts.transport = path->device->transport;
1580195534Sscottl	cts.transport_version = path->device->transport_version;
1581195534Sscottl	cts.protocol = path->device->protocol;
1582195534Sscottl	cts.protocol_version = path->device->protocol_version;
1583195534Sscottl	cts.proto_specific.valid = 0;
1584203376Smav	if (ident_buf) {
1585203376Smav		if (path->device->transport == XPORT_ATA) {
1586203376Smav			cts.xport_specific.ata.atapi =
1587203376Smav			    ((ident_buf->config & ATA_PROTO_MASK) == ATA_PROTO_ATAPI_16) ? 16 :
1588203376Smav			    ((ident_buf->config & ATA_PROTO_MASK) == ATA_PROTO_ATAPI_12) ? 12 : 0;
1589203376Smav			cts.xport_specific.ata.valid = CTS_ATA_VALID_ATAPI;
1590203376Smav		} else {
1591203376Smav			cts.xport_specific.sata.atapi =
1592203376Smav			    ((ident_buf->config & ATA_PROTO_MASK) == ATA_PROTO_ATAPI_16) ? 16 :
1593203376Smav			    ((ident_buf->config & ATA_PROTO_MASK) == ATA_PROTO_ATAPI_12) ? 12 : 0;
1594203376Smav			cts.xport_specific.sata.valid = CTS_SATA_VALID_ATAPI;
1595203376Smav		}
1596203376Smav	} else
1597203376Smav		cts.xport_specific.valid = 0;
1598195534Sscottl	xpt_action((union ccb *)&cts);
1599195534Sscottl}
1600195534Sscottl
1601195534Sscottlstatic void
1602195534Sscottlata_action(union ccb *start_ccb)
1603195534Sscottl{
1604195534Sscottl
1605195534Sscottl	switch (start_ccb->ccb_h.func_code) {
1606195534Sscottl	case XPT_SET_TRAN_SETTINGS:
1607195534Sscottl	{
1608199178Smav		ata_set_transfer_settings(&start_ccb->cts,
1609195534Sscottl					   start_ccb->ccb_h.path->device,
1610195534Sscottl					   /*async_update*/FALSE);
1611195534Sscottl		break;
1612195534Sscottl	}
1613195534Sscottl	case XPT_SCAN_BUS:
1614208582Smjacob	case XPT_SCAN_TGT:
1615195534Sscottl		ata_scan_bus(start_ccb->ccb_h.path->periph, start_ccb);
1616195534Sscottl		break;
1617195534Sscottl	case XPT_SCAN_LUN:
1618195534Sscottl		ata_scan_lun(start_ccb->ccb_h.path->periph,
1619195534Sscottl			      start_ccb->ccb_h.path, start_ccb->crcn.flags,
1620195534Sscottl			      start_ccb);
1621195534Sscottl		break;
1622195534Sscottl	case XPT_GET_TRAN_SETTINGS:
1623195534Sscottl	{
1624195534Sscottl		struct cam_sim *sim;
1625195534Sscottl
1626195534Sscottl		sim = start_ccb->ccb_h.path->bus->sim;
1627195534Sscottl		(*(sim->sim_action))(sim, start_ccb);
1628195534Sscottl		break;
1629195534Sscottl	}
1630203376Smav	case XPT_SCSI_IO:
1631203376Smav	{
1632203376Smav		struct cam_ed *device;
1633203376Smav		u_int	maxlen = 0;
1634203376Smav
1635203376Smav		device = start_ccb->ccb_h.path->device;
1636203376Smav		if (device->protocol == PROTO_SCSI &&
1637203376Smav		    (device->flags & CAM_DEV_IDENTIFY_DATA_VALID)) {
1638203376Smav			uint16_t p =
1639203376Smav			    device->ident_data.config & ATA_PROTO_MASK;
1640203376Smav
1641203376Smav			maxlen = (p == ATA_PROTO_ATAPI_16) ? 16 :
1642203376Smav			    (p == ATA_PROTO_ATAPI_12) ? 12 : 0;
1643203376Smav		}
1644203376Smav		if (start_ccb->csio.cdb_len > maxlen) {
1645203376Smav			start_ccb->ccb_h.status = CAM_REQ_INVALID;
1646203376Smav			xpt_done(start_ccb);
1647203376Smav			break;
1648203376Smav		}
1649203376Smav		/* FALLTHROUGH */
1650203376Smav	}
1651195534Sscottl	default:
1652195534Sscottl		xpt_action_default(start_ccb);
1653195534Sscottl		break;
1654195534Sscottl	}
1655195534Sscottl}
1656195534Sscottl
1657195534Sscottlstatic void
1658199178Smavata_set_transfer_settings(struct ccb_trans_settings *cts, struct cam_ed *device,
1659195534Sscottl			   int async_update)
1660195534Sscottl{
1661195534Sscottl	struct	ccb_pathinq cpi;
1662195534Sscottl	struct	ccb_trans_settings cur_cts;
1663195534Sscottl	struct	ccb_trans_settings_scsi *scsi;
1664195534Sscottl	struct	ccb_trans_settings_scsi *cur_scsi;
1665195534Sscottl	struct	cam_sim *sim;
1666195534Sscottl	struct	scsi_inquiry_data *inq_data;
1667195534Sscottl
1668195534Sscottl	if (device == NULL) {
1669195534Sscottl		cts->ccb_h.status = CAM_PATH_INVALID;
1670195534Sscottl		xpt_done((union ccb *)cts);
1671195534Sscottl		return;
1672195534Sscottl	}
1673195534Sscottl
1674195534Sscottl	if (cts->protocol == PROTO_UNKNOWN
1675195534Sscottl	 || cts->protocol == PROTO_UNSPECIFIED) {
1676195534Sscottl		cts->protocol = device->protocol;
1677195534Sscottl		cts->protocol_version = device->protocol_version;
1678195534Sscottl	}
1679195534Sscottl
1680195534Sscottl	if (cts->protocol_version == PROTO_VERSION_UNKNOWN
1681195534Sscottl	 || cts->protocol_version == PROTO_VERSION_UNSPECIFIED)
1682195534Sscottl		cts->protocol_version = device->protocol_version;
1683195534Sscottl
1684195534Sscottl	if (cts->protocol != device->protocol) {
1685195534Sscottl		xpt_print(cts->ccb_h.path, "Uninitialized Protocol %x:%x?\n",
1686195534Sscottl		       cts->protocol, device->protocol);
1687195534Sscottl		cts->protocol = device->protocol;
1688195534Sscottl	}
1689195534Sscottl
1690195534Sscottl	if (cts->protocol_version > device->protocol_version) {
1691195534Sscottl		if (bootverbose) {
1692195534Sscottl			xpt_print(cts->ccb_h.path, "Down reving Protocol "
1693195534Sscottl			    "Version from %d to %d?\n", cts->protocol_version,
1694195534Sscottl			    device->protocol_version);
1695195534Sscottl		}
1696195534Sscottl		cts->protocol_version = device->protocol_version;
1697195534Sscottl	}
1698195534Sscottl
1699195534Sscottl	if (cts->transport == XPORT_UNKNOWN
1700195534Sscottl	 || cts->transport == XPORT_UNSPECIFIED) {
1701195534Sscottl		cts->transport = device->transport;
1702195534Sscottl		cts->transport_version = device->transport_version;
1703195534Sscottl	}
1704195534Sscottl
1705195534Sscottl	if (cts->transport_version == XPORT_VERSION_UNKNOWN
1706195534Sscottl	 || cts->transport_version == XPORT_VERSION_UNSPECIFIED)
1707195534Sscottl		cts->transport_version = device->transport_version;
1708195534Sscottl
1709195534Sscottl	if (cts->transport != device->transport) {
1710195534Sscottl		xpt_print(cts->ccb_h.path, "Uninitialized Transport %x:%x?\n",
1711195534Sscottl		    cts->transport, device->transport);
1712195534Sscottl		cts->transport = device->transport;
1713195534Sscottl	}
1714195534Sscottl
1715195534Sscottl	if (cts->transport_version > device->transport_version) {
1716195534Sscottl		if (bootverbose) {
1717195534Sscottl			xpt_print(cts->ccb_h.path, "Down reving Transport "
1718195534Sscottl			    "Version from %d to %d?\n", cts->transport_version,
1719195534Sscottl			    device->transport_version);
1720195534Sscottl		}
1721195534Sscottl		cts->transport_version = device->transport_version;
1722195534Sscottl	}
1723195534Sscottl
1724195534Sscottl	sim = cts->ccb_h.path->bus->sim;
1725195534Sscottl
1726195534Sscottl	/*
1727195534Sscottl	 * Nothing more of interest to do unless
1728195534Sscottl	 * this is a device connected via the
1729195534Sscottl	 * SCSI protocol.
1730195534Sscottl	 */
1731195534Sscottl	if (cts->protocol != PROTO_SCSI) {
1732195534Sscottl		if (async_update == FALSE)
1733195534Sscottl			(*(sim->sim_action))(sim, (union ccb *)cts);
1734195534Sscottl		return;
1735195534Sscottl	}
1736195534Sscottl
1737195534Sscottl	inq_data = &device->inq_data;
1738195534Sscottl	scsi = &cts->proto_specific.scsi;
1739203108Smav	xpt_setup_ccb(&cpi.ccb_h, cts->ccb_h.path, CAM_PRIORITY_NONE);
1740195534Sscottl	cpi.ccb_h.func_code = XPT_PATH_INQ;
1741195534Sscottl	xpt_action((union ccb *)&cpi);
1742195534Sscottl
1743195534Sscottl	/* SCSI specific sanity checking */
1744195534Sscottl	if ((cpi.hba_inquiry & PI_TAG_ABLE) == 0
1745195534Sscottl	 || (INQ_DATA_TQ_ENABLED(inq_data)) == 0
1746195534Sscottl	 || (device->queue_flags & SCP_QUEUE_DQUE) != 0
1747195534Sscottl	 || (device->mintags == 0)) {
1748195534Sscottl		/*
1749195534Sscottl		 * Can't tag on hardware that doesn't support tags,
1750195534Sscottl		 * doesn't have it enabled, or has broken tag support.
1751195534Sscottl		 */
1752195534Sscottl		scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
1753195534Sscottl	}
1754195534Sscottl
1755195534Sscottl	if (async_update == FALSE) {
1756195534Sscottl		/*
1757195534Sscottl		 * Perform sanity checking against what the
1758195534Sscottl		 * controller and device can do.
1759195534Sscottl		 */
1760203108Smav		xpt_setup_ccb(&cur_cts.ccb_h, cts->ccb_h.path, CAM_PRIORITY_NONE);
1761195534Sscottl		cur_cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
1762195534Sscottl		cur_cts.type = cts->type;
1763195534Sscottl		xpt_action((union ccb *)&cur_cts);
1764195534Sscottl		if ((cur_cts.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1765195534Sscottl			return;
1766195534Sscottl		}
1767195534Sscottl		cur_scsi = &cur_cts.proto_specific.scsi;
1768195534Sscottl		if ((scsi->valid & CTS_SCSI_VALID_TQ) == 0) {
1769195534Sscottl			scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
1770195534Sscottl			scsi->flags |= cur_scsi->flags & CTS_SCSI_FLAGS_TAG_ENB;
1771195534Sscottl		}
1772195534Sscottl		if ((cur_scsi->valid & CTS_SCSI_VALID_TQ) == 0)
1773195534Sscottl			scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
1774195534Sscottl	}
1775195534Sscottl
1776195534Sscottl	if (cts->type == CTS_TYPE_CURRENT_SETTINGS
1777195534Sscottl	 && (scsi->valid & CTS_SCSI_VALID_TQ) != 0) {
1778195534Sscottl		int device_tagenb;
1779195534Sscottl
1780195534Sscottl		/*
1781195534Sscottl		 * If we are transitioning from tags to no-tags or
1782195534Sscottl		 * vice-versa, we need to carefully freeze and restart
1783195534Sscottl		 * the queue so that we don't overlap tagged and non-tagged
1784195534Sscottl		 * commands.  We also temporarily stop tags if there is
1785195534Sscottl		 * a change in transfer negotiation settings to allow
1786195534Sscottl		 * "tag-less" negotiation.
1787195534Sscottl		 */
1788195534Sscottl		if ((device->flags & CAM_DEV_TAG_AFTER_COUNT) != 0
1789195534Sscottl		 || (device->inq_flags & SID_CmdQue) != 0)
1790195534Sscottl			device_tagenb = TRUE;
1791195534Sscottl		else
1792195534Sscottl			device_tagenb = FALSE;
1793195534Sscottl
1794195534Sscottl		if (((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0
1795195534Sscottl		  && device_tagenb == FALSE)
1796195534Sscottl		 || ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) == 0
1797195534Sscottl		  && device_tagenb == TRUE)) {
1798195534Sscottl
1799195534Sscottl			if ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0) {
1800195534Sscottl				/*
1801195534Sscottl				 * Delay change to use tags until after a
1802195534Sscottl				 * few commands have gone to this device so
1803195534Sscottl				 * the controller has time to perform transfer
1804195534Sscottl				 * negotiations without tagged messages getting
1805195534Sscottl				 * in the way.
1806195534Sscottl				 */
1807195534Sscottl				device->tag_delay_count = CAM_TAG_DELAY_COUNT;
1808195534Sscottl				device->flags |= CAM_DEV_TAG_AFTER_COUNT;
1809195534Sscottl			} else {
1810199178Smav				xpt_stop_tags(cts->ccb_h.path);
1811195534Sscottl			}
1812195534Sscottl		}
1813195534Sscottl	}
1814195534Sscottl	if (async_update == FALSE)
1815195534Sscottl		(*(sim->sim_action))(sim, (union ccb *)cts);
1816195534Sscottl}
1817195534Sscottl
1818195534Sscottl/*
1819195534Sscottl * Handle any per-device event notifications that require action by the XPT.
1820195534Sscottl */
1821195534Sscottlstatic void
1822195534Sscottlata_dev_async(u_int32_t async_code, struct cam_eb *bus, struct cam_et *target,
1823195534Sscottl	      struct cam_ed *device, void *async_arg)
1824195534Sscottl{
1825195534Sscottl	cam_status status;
1826195534Sscottl	struct cam_path newpath;
1827195534Sscottl
1828195534Sscottl	/*
1829195534Sscottl	 * We only need to handle events for real devices.
1830195534Sscottl	 */
1831195534Sscottl	if (target->target_id == CAM_TARGET_WILDCARD
1832195534Sscottl	 || device->lun_id == CAM_LUN_WILDCARD)
1833195534Sscottl		return;
1834195534Sscottl
1835195534Sscottl	/*
1836195534Sscottl	 * We need our own path with wildcards expanded to
1837195534Sscottl	 * handle certain types of events.
1838195534Sscottl	 */
1839195534Sscottl	if ((async_code == AC_SENT_BDR)
1840195534Sscottl	 || (async_code == AC_BUS_RESET)
1841195534Sscottl	 || (async_code == AC_INQ_CHANGED))
1842195534Sscottl		status = xpt_compile_path(&newpath, NULL,
1843195534Sscottl					  bus->path_id,
1844195534Sscottl					  target->target_id,
1845195534Sscottl					  device->lun_id);
1846195534Sscottl	else
1847195534Sscottl		status = CAM_REQ_CMP_ERR;
1848195534Sscottl
1849195534Sscottl	if (status == CAM_REQ_CMP) {
1850195534Sscottl		if (async_code == AC_INQ_CHANGED) {
1851195534Sscottl			/*
1852195534Sscottl			 * We've sent a start unit command, or
1853195534Sscottl			 * something similar to a device that
1854195534Sscottl			 * may have caused its inquiry data to
1855195534Sscottl			 * change. So we re-scan the device to
1856195534Sscottl			 * refresh the inquiry data for it.
1857195534Sscottl			 */
1858195534Sscottl			ata_scan_lun(newpath.periph, &newpath,
1859195534Sscottl				     CAM_EXPECT_INQ_CHANGE, NULL);
1860203108Smav		} else {
1861203108Smav			/* We need to reinitialize device after reset. */
1862203108Smav			ata_scan_lun(newpath.periph, &newpath,
1863203108Smav				     0, NULL);
1864195534Sscottl		}
1865195534Sscottl		xpt_release_path(&newpath);
1866198748Smav	} else if (async_code == AC_LOST_DEVICE &&
1867198748Smav	    (device->flags & CAM_DEV_UNCONFIGURED) == 0) {
1868195534Sscottl		device->flags |= CAM_DEV_UNCONFIGURED;
1869198748Smav		xpt_release_device(device);
1870195534Sscottl	} else if (async_code == AC_TRANSFER_NEG) {
1871195534Sscottl		struct ccb_trans_settings *settings;
1872195534Sscottl
1873195534Sscottl		settings = (struct ccb_trans_settings *)async_arg;
1874199178Smav		ata_set_transfer_settings(settings, device,
1875195534Sscottl					  /*async_update*/TRUE);
1876195534Sscottl	}
1877195534Sscottl}
1878195534Sscottl
1879204220Smavstatic void
1880204220Smavata_announce_periph(struct cam_periph *periph)
1881204220Smav{
1882204220Smav	struct	ccb_pathinq cpi;
1883204220Smav	struct	ccb_trans_settings cts;
1884204220Smav	struct	cam_path *path = periph->path;
1885204220Smav	u_int	speed;
1886204220Smav	u_int	mb;
1887204220Smav
1888204220Smav	mtx_assert(periph->sim->mtx, MA_OWNED);
1889204220Smav
1890204220Smav	xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NORMAL);
1891204220Smav	cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
1892204220Smav	cts.type = CTS_TYPE_CURRENT_SETTINGS;
1893204220Smav	xpt_action((union ccb*)&cts);
1894204220Smav	if ((cts.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)
1895204220Smav		return;
1896204220Smav	/* Ask the SIM for its base transfer speed */
1897204220Smav	xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NORMAL);
1898204220Smav	cpi.ccb_h.func_code = XPT_PATH_INQ;
1899204220Smav	xpt_action((union ccb *)&cpi);
1900204220Smav	/* Report connection speed */
1901204220Smav	speed = cpi.base_transfer_speed;
1902204220Smav	if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_ATA) {
1903204220Smav		struct	ccb_trans_settings_ata *ata =
1904204220Smav		    &cts.xport_specific.ata;
1905204220Smav
1906204220Smav		if (ata->valid & CTS_ATA_VALID_MODE)
1907204220Smav			speed = ata_mode2speed(ata->mode);
1908204220Smav	}
1909204220Smav	if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_SATA) {
1910204220Smav		struct	ccb_trans_settings_sata *sata =
1911204220Smav		    &cts.xport_specific.sata;
1912204220Smav
1913204220Smav		if (sata->valid & CTS_SATA_VALID_REVISION)
1914204220Smav			speed = ata_revision2speed(sata->revision);
1915204220Smav	}
1916204220Smav	mb = speed / 1000;
1917204220Smav	if (mb > 0)
1918204220Smav		printf("%s%d: %d.%03dMB/s transfers",
1919204220Smav		       periph->periph_name, periph->unit_number,
1920204220Smav		       mb, speed % 1000);
1921204220Smav	else
1922204220Smav		printf("%s%d: %dKB/s transfers", periph->periph_name,
1923204220Smav		       periph->unit_number, speed);
1924204220Smav	/* Report additional information about connection */
1925204220Smav	if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_ATA) {
1926204220Smav		struct ccb_trans_settings_ata *ata =
1927204220Smav		    &cts.xport_specific.ata;
1928204220Smav
1929204220Smav		printf(" (");
1930204220Smav		if (ata->valid & CTS_ATA_VALID_MODE)
1931204220Smav			printf("%s, ", ata_mode2string(ata->mode));
1932204220Smav		if ((ata->valid & CTS_ATA_VALID_ATAPI) && ata->atapi != 0)
1933204220Smav			printf("ATAPI %dbytes, ", ata->atapi);
1934204220Smav		if (ata->valid & CTS_ATA_VALID_BYTECOUNT)
1935204220Smav			printf("PIO %dbytes", ata->bytecount);
1936204220Smav		printf(")");
1937204220Smav	}
1938204220Smav	if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_SATA) {
1939204220Smav		struct ccb_trans_settings_sata *sata =
1940204220Smav		    &cts.xport_specific.sata;
1941204220Smav
1942204220Smav		printf(" (");
1943204220Smav		if (sata->valid & CTS_SATA_VALID_REVISION)
1944204220Smav			printf("SATA %d.x, ", sata->revision);
1945204220Smav		else
1946204220Smav			printf("SATA, ");
1947204220Smav		if (sata->valid & CTS_SATA_VALID_MODE)
1948204220Smav			printf("%s, ", ata_mode2string(sata->mode));
1949204220Smav		if ((sata->valid & CTS_ATA_VALID_ATAPI) && sata->atapi != 0)
1950204220Smav			printf("ATAPI %dbytes, ", sata->atapi);
1951204220Smav		if (sata->valid & CTS_SATA_VALID_BYTECOUNT)
1952204220Smav			printf("PIO %dbytes", sata->bytecount);
1953204220Smav		printf(")");
1954204220Smav	}
1955204220Smav	printf("\n");
1956204220Smav}
1957204220Smav
1958