1195534Sscottl/*-
2238805Smav * Copyright (c) 2009-2012 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: stable/11/sys/dev/ahci/ahci.c 350793 2019-08-08 21:46:36Z mav $");
29195534Sscottl
30195534Sscottl#include <sys/param.h>
31195534Sscottl#include <sys/module.h>
32195534Sscottl#include <sys/systm.h>
33195534Sscottl#include <sys/kernel.h>
34195534Sscottl#include <sys/bus.h>
35220576Smav#include <sys/conf.h>
36195534Sscottl#include <sys/endian.h>
37195534Sscottl#include <sys/malloc.h>
38195534Sscottl#include <sys/lock.h>
39195534Sscottl#include <sys/mutex.h>
40350792Smav#include <sys/sysctl.h>
41195534Sscottl#include <machine/stdarg.h>
42195534Sscottl#include <machine/resource.h>
43195534Sscottl#include <machine/bus.h>
44195534Sscottl#include <sys/rman.h>
45195534Sscottl#include "ahci.h"
46195534Sscottl
47195534Sscottl#include <cam/cam.h>
48195534Sscottl#include <cam/cam_ccb.h>
49195534Sscottl#include <cam/cam_sim.h>
50195534Sscottl#include <cam/cam_xpt_sim.h>
51195534Sscottl#include <cam/cam_debug.h>
52195534Sscottl
53195534Sscottl/* local prototypes */
54195534Sscottlstatic void ahci_intr(void *data);
55195534Sscottlstatic void ahci_intr_one(void *data);
56256843Smavstatic void ahci_intr_one_edge(void *data);
57208375Smavstatic int ahci_ch_init(device_t dev);
58208375Smavstatic int ahci_ch_deinit(device_t dev);
59195534Sscottlstatic int ahci_ch_suspend(device_t dev);
60195534Sscottlstatic int ahci_ch_resume(device_t dev);
61196656Smavstatic void ahci_ch_pm(void *arg);
62256843Smavstatic void ahci_ch_intr(void *arg);
63256843Smavstatic void ahci_ch_intr_direct(void *arg);
64256843Smavstatic void ahci_ch_intr_main(struct ahci_channel *ch, uint32_t istatus);
65271261Smavstatic void ahci_begin_transaction(struct ahci_channel *ch, union ccb *ccb);
66195534Sscottlstatic void ahci_dmasetprd(void *arg, bus_dma_segment_t *segs, int nsegs, int error);
67195534Sscottlstatic void ahci_execute_transaction(struct ahci_slot *slot);
68195534Sscottlstatic void ahci_timeout(struct ahci_slot *slot);
69195534Sscottlstatic void ahci_end_transaction(struct ahci_slot *slot, enum ahci_err_type et);
70271261Smavstatic int ahci_setup_fis(struct ahci_channel *ch, struct ahci_cmd_tab *ctp, union ccb *ccb, int tag);
71195534Sscottlstatic void ahci_dmainit(device_t dev);
72195534Sscottlstatic void ahci_dmasetupc_cb(void *xsc, bus_dma_segment_t *segs, int nsegs, int error);
73195534Sscottlstatic void ahci_dmafini(device_t dev);
74195534Sscottlstatic void ahci_slotsalloc(device_t dev);
75195534Sscottlstatic void ahci_slotsfree(device_t dev);
76271261Smavstatic void ahci_reset(struct ahci_channel *ch);
77271261Smavstatic void ahci_start(struct ahci_channel *ch, int fbs);
78271261Smavstatic void ahci_stop(struct ahci_channel *ch);
79271261Smavstatic void ahci_clo(struct ahci_channel *ch);
80271261Smavstatic void ahci_start_fr(struct ahci_channel *ch);
81271261Smavstatic void ahci_stop_fr(struct ahci_channel *ch);
82350792Smavstatic int ahci_phy_check_events(struct ahci_channel *ch, u_int32_t serr);
83350792Smavstatic uint32_t ahci_ch_detval(struct ahci_channel *ch, uint32_t val);
84195534Sscottl
85195534Sscottlstatic int ahci_sata_connect(struct ahci_channel *ch);
86271261Smavstatic int ahci_sata_phy_reset(struct ahci_channel *ch);
87271261Smavstatic int ahci_wait_ready(struct ahci_channel *ch, int t, int t0);
88195534Sscottl
89271261Smavstatic void ahci_issue_recovery(struct ahci_channel *ch);
90271261Smavstatic void ahci_process_read_log(struct ahci_channel *ch, union ccb *ccb);
91271261Smavstatic void ahci_process_request_sense(struct ahci_channel *ch, union ccb *ccb);
92195534Sscottl
93195534Sscottlstatic void ahciaction(struct cam_sim *sim, union ccb *ccb);
94195534Sscottlstatic void ahcipoll(struct cam_sim *sim);
95195534Sscottl
96227293Sedstatic MALLOC_DEFINE(M_AHCI, "AHCI driver", "AHCI driver data buffers");
97195534Sscottl
98220565Smav#define recovery_type		spriv_field0
99220565Smav#define RECOVERY_NONE		0
100220565Smav#define RECOVERY_READ_LOG	1
101220565Smav#define RECOVERY_REQUEST_SENSE	2
102220565Smav#define recovery_slot		spriv_field1
103220565Smav
104350792Smavstatic uint32_t
105350792Smavahci_ch_detval(struct ahci_channel *ch, uint32_t val)
106350792Smav{
107350792Smav
108350792Smav	return ch->disablephy ? ATA_SC_DET_DISABLE : val;
109350792Smav}
110350792Smav
111271146Simpint
112271146Simpahci_ctlr_setup(device_t dev)
113195534Sscottl{
114271146Simp	struct ahci_controller *ctlr = device_get_softc(dev);
115271146Simp	/* Clear interrupts */
116271146Simp	ATA_OUTL(ctlr->r_mem, AHCI_IS, ATA_INL(ctlr->r_mem, AHCI_IS));
117271146Simp	/* Configure CCC */
118271146Simp	if (ctlr->ccc) {
119271146Simp		ATA_OUTL(ctlr->r_mem, AHCI_CCCP, ATA_INL(ctlr->r_mem, AHCI_PI));
120271146Simp		ATA_OUTL(ctlr->r_mem, AHCI_CCCC,
121271146Simp		    (ctlr->ccc << AHCI_CCCC_TV_SHIFT) |
122271146Simp		    (4 << AHCI_CCCC_CC_SHIFT) |
123271146Simp		    AHCI_CCCC_EN);
124271146Simp		ctlr->cccv = (ATA_INL(ctlr->r_mem, AHCI_CCCC) &
125271146Simp		    AHCI_CCCC_INT_MASK) >> AHCI_CCCC_INT_SHIFT;
126271146Simp		if (bootverbose) {
127271146Simp			device_printf(dev,
128271146Simp			    "CCC with %dms/4cmd enabled on vector %d\n",
129271146Simp			    ctlr->ccc, ctlr->cccv);
130199322Smav		}
131199322Smav	}
132271146Simp	/* Enable AHCI interrupts */
133271146Simp	ATA_OUTL(ctlr->r_mem, AHCI_GHC,
134271146Simp	    ATA_INL(ctlr->r_mem, AHCI_GHC) | AHCI_GHC_IE);
135271146Simp	return (0);
136199322Smav}
137199322Smav
138271146Simpint
139271146Simpahci_ctlr_reset(device_t dev)
140199322Smav{
141271146Simp	struct ahci_controller *ctlr = device_get_softc(dev);
142271146Simp	int timeout;
143195534Sscottl
144271146Simp	/* Enable AHCI mode */
145271146Simp	ATA_OUTL(ctlr->r_mem, AHCI_GHC, AHCI_GHC_AE);
146271146Simp	/* Reset AHCI controller */
147271146Simp	ATA_OUTL(ctlr->r_mem, AHCI_GHC, AHCI_GHC_AE|AHCI_GHC_HR);
148271146Simp	for (timeout = 1000; timeout > 0; timeout--) {
149271146Simp		DELAY(1000);
150271146Simp		if ((ATA_INL(ctlr->r_mem, AHCI_GHC) & AHCI_GHC_HR) == 0)
151271146Simp			break;
152199176Smav	}
153271146Simp	if (timeout == 0) {
154271146Simp		device_printf(dev, "AHCI controller reset failure\n");
155276019Ssmh		return (ENXIO);
156271146Simp	}
157271146Simp	/* Reenable AHCI mode */
158271146Simp	ATA_OUTL(ctlr->r_mem, AHCI_GHC, AHCI_GHC_AE);
159280184Szbb
160280184Szbb	if (ctlr->quirks & AHCI_Q_RESTORE_CAP) {
161280184Szbb		/*
162280184Szbb		 * Restore capability field.
163280184Szbb		 * This is write to a read-only register to restore its state.
164280184Szbb		 * On fully standard-compliant hardware this is not needed and
165280184Szbb		 * this operation shall not take place. See ahci_pci.c for
166280184Szbb		 * platforms using this quirk.
167280184Szbb		 */
168280184Szbb		ATA_OUTL(ctlr->r_mem, AHCI_CAP, ctlr->caps);
169280184Szbb	}
170280184Szbb
171271146Simp	return (0);
172195534Sscottl}
173195534Sscottl
174271146Simp
175271146Simpint
176195534Sscottlahci_attach(device_t dev)
177195534Sscottl{
178195534Sscottl	struct ahci_controller *ctlr = device_get_softc(dev);
179302402Smav	int error, i, speed, unit;
180302402Smav	uint32_t u, version;
181195534Sscottl	device_t child;
182195534Sscottl
183195534Sscottl	ctlr->dev = dev;
184271457Smav	ctlr->ccc = 0;
185196656Smav	resource_int_value(device_get_name(dev),
186196656Smav	    device_get_unit(dev), "ccc", &ctlr->ccc);
187350793Smav	mtx_init(&ctlr->ch_mtx, "AHCI channels lock", NULL, MTX_DEF);
188271146Simp
189195534Sscottl	/* Setup our own memory management for channels. */
190208414Smav	ctlr->sc_iomem.rm_start = rman_get_start(ctlr->r_mem);
191208414Smav	ctlr->sc_iomem.rm_end = rman_get_end(ctlr->r_mem);
192195534Sscottl	ctlr->sc_iomem.rm_type = RMAN_ARRAY;
193195534Sscottl	ctlr->sc_iomem.rm_descr = "I/O memory addresses";
194195534Sscottl	if ((error = rman_init(&ctlr->sc_iomem)) != 0) {
195285789Szbb		ahci_free_mem(dev);
196195534Sscottl		return (error);
197195534Sscottl	}
198195534Sscottl	if ((error = rman_manage_region(&ctlr->sc_iomem,
199195534Sscottl	    rman_get_start(ctlr->r_mem), rman_get_end(ctlr->r_mem))) != 0) {
200285789Szbb		ahci_free_mem(dev);
201195534Sscottl		rman_fini(&ctlr->sc_iomem);
202195534Sscottl		return (error);
203195534Sscottl	}
204199322Smav	/* Get the HW capabilities */
205199322Smav	version = ATA_INL(ctlr->r_mem, AHCI_VS);
206199322Smav	ctlr->caps = ATA_INL(ctlr->r_mem, AHCI_CAP);
207240383Smav	if (version >= 0x00010200)
208199322Smav		ctlr->caps2 = ATA_INL(ctlr->r_mem, AHCI_CAP2);
209203108Smav	if (ctlr->caps & AHCI_CAP_EMS)
210203108Smav		ctlr->capsem = ATA_INL(ctlr->r_mem, AHCI_EM_CTL);
211280184Szbb
212280184Szbb	if (ctlr->quirks & AHCI_Q_FORCE_PI) {
213280184Szbb		/*
214280184Szbb		 * Enable ports.
215280184Szbb		 * The spec says that BIOS sets up bits corresponding to
216280184Szbb		 * available ports. On platforms where this information
217280184Szbb		 * is missing, the driver can define available ports on its own.
218280184Szbb		 */
219280184Szbb		int nports = (ctlr->caps & AHCI_CAP_NPMASK) + 1;
220280184Szbb		int nmask = (1 << nports) - 1;
221280184Szbb
222280184Szbb		ATA_OUTL(ctlr->r_mem, AHCI_PI, nmask);
223280184Szbb		device_printf(dev, "Forcing PI to %d ports (mask = %x)\n",
224280184Szbb		    nports, nmask);
225280184Szbb	}
226280184Szbb
227195534Sscottl	ctlr->ichannels = ATA_INL(ctlr->r_mem, AHCI_PI);
228222304Smav
229222304Smav	/* Identify and set separate quirks for HBA and RAID f/w Marvells. */
230271163Smav	if ((ctlr->quirks & AHCI_Q_ALTSIG) &&
231222304Smav	    (ctlr->caps & AHCI_CAP_SPM) == 0)
232271163Smav		ctlr->quirks |= AHCI_Q_NOBSYRES;
233222304Smav
234199322Smav	if (ctlr->quirks & AHCI_Q_1CH) {
235199322Smav		ctlr->caps &= ~AHCI_CAP_NPMASK;
236199322Smav		ctlr->ichannels &= 0x01;
237199322Smav	}
238199322Smav	if (ctlr->quirks & AHCI_Q_2CH) {
239199322Smav		ctlr->caps &= ~AHCI_CAP_NPMASK;
240199322Smav		ctlr->caps |= 1;
241199322Smav		ctlr->ichannels &= 0x03;
242199322Smav	}
243199322Smav	if (ctlr->quirks & AHCI_Q_4CH) {
244199322Smav		ctlr->caps &= ~AHCI_CAP_NPMASK;
245199322Smav		ctlr->caps |= 3;
246199322Smav		ctlr->ichannels &= 0x0f;
247199322Smav	}
248195534Sscottl	ctlr->channels = MAX(flsl(ctlr->ichannels),
249199322Smav	    (ctlr->caps & AHCI_CAP_NPMASK) + 1);
250199322Smav	if (ctlr->quirks & AHCI_Q_NOPMP)
251199322Smav		ctlr->caps &= ~AHCI_CAP_SPM;
252199322Smav	if (ctlr->quirks & AHCI_Q_NONCQ)
253199322Smav		ctlr->caps &= ~AHCI_CAP_SNCQ;
254205422Smav	if ((ctlr->caps & AHCI_CAP_CCCS) == 0)
255205422Smav		ctlr->ccc = 0;
256222039Smav	ctlr->emloc = ATA_INL(ctlr->r_mem, AHCI_EM_LOC);
257249346Smav
258249346Smav	/* Create controller-wide DMA tag. */
259274189Sian	if (bus_dma_tag_create(bus_get_dma_tag(dev), 1, 0,
260249346Smav	    (ctlr->caps & AHCI_CAP_64BIT) ? BUS_SPACE_MAXADDR :
261249346Smav	    BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
262249346Smav	    BUS_SPACE_MAXSIZE, BUS_SPACE_UNRESTRICTED, BUS_SPACE_MAXSIZE,
263249346Smav	    0, NULL, NULL, &ctlr->dma_tag)) {
264285789Szbb		ahci_free_mem(dev);
265249346Smav		rman_fini(&ctlr->sc_iomem);
266276019Ssmh		return (ENXIO);
267249346Smav	}
268249346Smav
269205422Smav	ahci_ctlr_setup(dev);
270271146Simp
271271201Simp	/* Setup interrupts. */
272276016Ssmh	if ((error = ahci_setup_interrupt(dev)) != 0) {
273271201Simp		bus_dma_tag_destroy(ctlr->dma_tag);
274285789Szbb		ahci_free_mem(dev);
275271201Simp		rman_fini(&ctlr->sc_iomem);
276276019Ssmh		return (error);
277271201Simp	}
278271201Simp
279256843Smav	i = 0;
280256843Smav	for (u = ctlr->ichannels; u != 0; u >>= 1)
281256843Smav		i += (u & 1);
282256843Smav	ctlr->direct = (ctlr->msi && (ctlr->numirqs > 1 || i <= 3));
283256843Smav	resource_int_value(device_get_name(dev), device_get_unit(dev),
284256843Smav	    "direct", &ctlr->direct);
285195534Sscottl	/* Announce HW capabilities. */
286196656Smav	speed = (ctlr->caps & AHCI_CAP_ISS) >> AHCI_CAP_ISS_SHIFT;
287195534Sscottl	device_printf(dev,
288203123Smav		    "AHCI v%x.%02x with %d %sGbps ports, Port Multiplier %s%s\n",
289195534Sscottl		    ((version >> 20) & 0xf0) + ((version >> 16) & 0x0f),
290195534Sscottl		    ((version >> 4) & 0xf0) + (version & 0x0f),
291196656Smav		    (ctlr->caps & AHCI_CAP_NPMASK) + 1,
292195534Sscottl		    ((speed == 1) ? "1.5":((speed == 2) ? "3":
293195534Sscottl		    ((speed == 3) ? "6":"?"))),
294196656Smav		    (ctlr->caps & AHCI_CAP_SPM) ?
295203123Smav		    "supported" : "not supported",
296203123Smav		    (ctlr->caps & AHCI_CAP_FBSS) ?
297203123Smav		    " with FBS" : "");
298250792Ssmh	if (ctlr->quirks != 0) {
299250792Ssmh		device_printf(dev, "quirks=0x%b\n", ctlr->quirks,
300250792Ssmh		    AHCI_Q_BIT_STRING);
301250792Ssmh	}
302195534Sscottl	if (bootverbose) {
303195534Sscottl		device_printf(dev, "Caps:%s%s%s%s%s%s%s%s %sGbps",
304196656Smav		    (ctlr->caps & AHCI_CAP_64BIT) ? " 64bit":"",
305196656Smav		    (ctlr->caps & AHCI_CAP_SNCQ) ? " NCQ":"",
306196656Smav		    (ctlr->caps & AHCI_CAP_SSNTF) ? " SNTF":"",
307196656Smav		    (ctlr->caps & AHCI_CAP_SMPS) ? " MPS":"",
308196656Smav		    (ctlr->caps & AHCI_CAP_SSS) ? " SS":"",
309196656Smav		    (ctlr->caps & AHCI_CAP_SALP) ? " ALP":"",
310196656Smav		    (ctlr->caps & AHCI_CAP_SAL) ? " AL":"",
311196656Smav		    (ctlr->caps & AHCI_CAP_SCLO) ? " CLO":"",
312195534Sscottl		    ((speed == 1) ? "1.5":((speed == 2) ? "3":
313195534Sscottl		    ((speed == 3) ? "6":"?"))));
314195534Sscottl		printf("%s%s%s%s%s%s %dcmd%s%s%s %dports\n",
315196656Smav		    (ctlr->caps & AHCI_CAP_SAM) ? " AM":"",
316196656Smav		    (ctlr->caps & AHCI_CAP_SPM) ? " PM":"",
317196656Smav		    (ctlr->caps & AHCI_CAP_FBSS) ? " FBS":"",
318196656Smav		    (ctlr->caps & AHCI_CAP_PMD) ? " PMD":"",
319196656Smav		    (ctlr->caps & AHCI_CAP_SSC) ? " SSC":"",
320196656Smav		    (ctlr->caps & AHCI_CAP_PSC) ? " PSC":"",
321196656Smav		    ((ctlr->caps & AHCI_CAP_NCS) >> AHCI_CAP_NCS_SHIFT) + 1,
322196656Smav		    (ctlr->caps & AHCI_CAP_CCCS) ? " CCC":"",
323196656Smav		    (ctlr->caps & AHCI_CAP_EMS) ? " EM":"",
324196656Smav		    (ctlr->caps & AHCI_CAP_SXS) ? " eSATA":"",
325196656Smav		    (ctlr->caps & AHCI_CAP_NPMASK) + 1);
326195534Sscottl	}
327240383Smav	if (bootverbose && version >= 0x00010200) {
328253647Smav		device_printf(dev, "Caps2:%s%s%s%s%s%s\n",
329253647Smav		    (ctlr->caps2 & AHCI_CAP2_DESO) ? " DESO":"",
330253647Smav		    (ctlr->caps2 & AHCI_CAP2_SADM) ? " SADM":"",
331253647Smav		    (ctlr->caps2 & AHCI_CAP2_SDS) ? " SDS":"",
332196656Smav		    (ctlr->caps2 & AHCI_CAP2_APST) ? " APST":"",
333196656Smav		    (ctlr->caps2 & AHCI_CAP2_NVMP) ? " NVMP":"",
334196656Smav		    (ctlr->caps2 & AHCI_CAP2_BOH) ? " BOH":"");
335196656Smav	}
336195534Sscottl	/* Attach all channels on this controller */
337195534Sscottl	for (unit = 0; unit < ctlr->channels; unit++) {
338195534Sscottl		child = device_add_child(dev, "ahcich", -1);
339227635Smav		if (child == NULL) {
340195534Sscottl			device_printf(dev, "failed to add channel device\n");
341227635Smav			continue;
342227635Smav		}
343227635Smav		device_set_ivars(child, (void *)(intptr_t)unit);
344227635Smav		if ((ctlr->ichannels & (1 << unit)) == 0)
345227635Smav			device_disable(child);
346195534Sscottl	}
347238805Smav	if (ctlr->caps & AHCI_CAP_EMS) {
348238805Smav		child = device_add_child(dev, "ahciem", -1);
349238805Smav		if (child == NULL)
350238805Smav			device_printf(dev, "failed to add enclosure device\n");
351238805Smav		else
352238805Smav			device_set_ivars(child, (void *)(intptr_t)-1);
353238805Smav	}
354195534Sscottl	bus_generic_attach(dev);
355276019Ssmh	return (0);
356195534Sscottl}
357195534Sscottl
358271146Simpint
359195534Sscottlahci_detach(device_t dev)
360195534Sscottl{
361195534Sscottl	struct ahci_controller *ctlr = device_get_softc(dev);
362227701Shselasky	int i;
363195534Sscottl
364195534Sscottl	/* Detach & delete all children */
365227849Shselasky	device_delete_children(dev);
366227701Shselasky
367195534Sscottl	/* Free interrupts. */
368195534Sscottl	for (i = 0; i < ctlr->numirqs; i++) {
369195534Sscottl		if (ctlr->irqs[i].r_irq) {
370195534Sscottl			bus_teardown_intr(dev, ctlr->irqs[i].r_irq,
371195534Sscottl			    ctlr->irqs[i].handle);
372195534Sscottl			bus_release_resource(dev, SYS_RES_IRQ,
373195534Sscottl			    ctlr->irqs[i].r_irq_rid, ctlr->irqs[i].r_irq);
374195534Sscottl		}
375195534Sscottl	}
376249346Smav	bus_dma_tag_destroy(ctlr->dma_tag);
377195534Sscottl	/* Free memory. */
378195534Sscottl	rman_fini(&ctlr->sc_iomem);
379285789Szbb	ahci_free_mem(dev);
380350793Smav	mtx_destroy(&ctlr->ch_mtx);
381285789Szbb	return (0);
382285789Szbb}
383285789Szbb
384285789Szbbvoid
385285789Szbbahci_free_mem(device_t dev)
386285789Szbb{
387285789Szbb	struct ahci_controller *ctlr = device_get_softc(dev);
388285789Szbb
389285789Szbb	/* Release memory resources */
390195534Sscottl	if (ctlr->r_mem)
391195534Sscottl		bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_rid, ctlr->r_mem);
392285789Szbb	if (ctlr->r_msix_table)
393285789Szbb		bus_release_resource(dev, SYS_RES_MEMORY,
394285789Szbb		    ctlr->r_msix_tab_rid, ctlr->r_msix_table);
395285789Szbb	if (ctlr->r_msix_pba)
396285789Szbb		bus_release_resource(dev, SYS_RES_MEMORY,
397285789Szbb		    ctlr->r_msix_pba_rid, ctlr->r_msix_pba);
398285789Szbb
399285789Szbb	ctlr->r_msix_pba = ctlr->r_mem = ctlr->r_msix_table = NULL;
400195534Sscottl}
401195534Sscottl
402271146Simpint
403195534Sscottlahci_setup_interrupt(device_t dev)
404195534Sscottl{
405195534Sscottl	struct ahci_controller *ctlr = device_get_softc(dev);
406256843Smav	int i;
407195534Sscottl
408195534Sscottl	/* Check for single MSI vector fallback. */
409195534Sscottl	if (ctlr->numirqs > 1 &&
410195534Sscottl	    (ATA_INL(ctlr->r_mem, AHCI_GHC) & AHCI_GHC_MRSM) != 0) {
411195534Sscottl		device_printf(dev, "Falling back to one MSI\n");
412195534Sscottl		ctlr->numirqs = 1;
413195534Sscottl	}
414276013Ssmh
415276013Ssmh	/* Ensure we don't overrun irqs. */
416276013Ssmh	if (ctlr->numirqs > AHCI_MAX_IRQS) {
417276013Ssmh		device_printf(dev, "Too many irqs %d > %d (clamping)\n",
418276013Ssmh		    ctlr->numirqs, AHCI_MAX_IRQS);
419276013Ssmh		ctlr->numirqs = AHCI_MAX_IRQS;
420276013Ssmh	}
421276013Ssmh
422195534Sscottl	/* Allocate all IRQs. */
423195534Sscottl	for (i = 0; i < ctlr->numirqs; i++) {
424195534Sscottl		ctlr->irqs[i].ctlr = ctlr;
425256843Smav		ctlr->irqs[i].r_irq_rid = i + (ctlr->msi ? 1 : 0);
426272606Smav		if (ctlr->channels == 1 && !ctlr->ccc && ctlr->msi)
427271207Smav			ctlr->irqs[i].mode = AHCI_IRQ_MODE_ONE;
428271207Smav		else if (ctlr->numirqs == 1 || i >= ctlr->channels ||
429196656Smav		    (ctlr->ccc && i == ctlr->cccv))
430195534Sscottl			ctlr->irqs[i].mode = AHCI_IRQ_MODE_ALL;
431304411Smav		else if (ctlr->channels > ctlr->numirqs &&
432304411Smav		    i == ctlr->numirqs - 1)
433195534Sscottl			ctlr->irqs[i].mode = AHCI_IRQ_MODE_AFTER;
434195534Sscottl		else
435195534Sscottl			ctlr->irqs[i].mode = AHCI_IRQ_MODE_ONE;
436195534Sscottl		if (!(ctlr->irqs[i].r_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ,
437195534Sscottl		    &ctlr->irqs[i].r_irq_rid, RF_SHAREABLE | RF_ACTIVE))) {
438195534Sscottl			device_printf(dev, "unable to map interrupt\n");
439276019Ssmh			return (ENXIO);
440195534Sscottl		}
441195534Sscottl		if ((bus_setup_intr(dev, ctlr->irqs[i].r_irq, ATA_INTR_FLAGS, NULL,
442256843Smav		    (ctlr->irqs[i].mode != AHCI_IRQ_MODE_ONE) ? ahci_intr :
443256843Smav		     ((ctlr->quirks & AHCI_Q_EDGEIS) ? ahci_intr_one_edge :
444256843Smav		      ahci_intr_one),
445195534Sscottl		    &ctlr->irqs[i], &ctlr->irqs[i].handle))) {
446195534Sscottl			/* SOS XXX release r_irq */
447195534Sscottl			device_printf(dev, "unable to setup interrupt\n");
448276019Ssmh			return (ENXIO);
449195534Sscottl		}
450202011Smav		if (ctlr->numirqs > 1) {
451202011Smav			bus_describe_intr(dev, ctlr->irqs[i].r_irq,
452202011Smav			    ctlr->irqs[i].handle,
453202011Smav			    ctlr->irqs[i].mode == AHCI_IRQ_MODE_ONE ?
454202011Smav			    "ch%d" : "%d", i);
455202011Smav		}
456195534Sscottl	}
457195534Sscottl	return (0);
458195534Sscottl}
459195534Sscottl
460195534Sscottl/*
461195534Sscottl * Common case interrupt handler.
462195534Sscottl */
463195534Sscottlstatic void
464195534Sscottlahci_intr(void *data)
465195534Sscottl{
466195534Sscottl	struct ahci_controller_irq *irq = data;
467195534Sscottl	struct ahci_controller *ctlr = irq->ctlr;
468205422Smav	u_int32_t is, ise = 0;
469195534Sscottl	void *arg;
470195534Sscottl	int unit;
471195534Sscottl
472196656Smav	if (irq->mode == AHCI_IRQ_MODE_ALL) {
473195534Sscottl		unit = 0;
474196656Smav		if (ctlr->ccc)
475196656Smav			is = ctlr->ichannels;
476196656Smav		else
477196656Smav			is = ATA_INL(ctlr->r_mem, AHCI_IS);
478196656Smav	} else {	/* AHCI_IRQ_MODE_AFTER */
479195534Sscottl		unit = irq->r_irq_rid - 1;
480196656Smav		is = ATA_INL(ctlr->r_mem, AHCI_IS);
481304412Smav		is &= (0xffffffff << unit);
482196656Smav	}
483205422Smav	/* CCC interrupt is edge triggered. */
484205422Smav	if (ctlr->ccc)
485205422Smav		ise = 1 << ctlr->cccv;
486200814Smav	/* Some controllers have edge triggered IS. */
487200814Smav	if (ctlr->quirks & AHCI_Q_EDGEIS)
488205422Smav		ise |= is;
489205422Smav	if (ise != 0)
490205422Smav		ATA_OUTL(ctlr->r_mem, AHCI_IS, ise);
491195534Sscottl	for (; unit < ctlr->channels; unit++) {
492195534Sscottl		if ((is & (1 << unit)) != 0 &&
493195534Sscottl		    (arg = ctlr->interrupt[unit].argument)) {
494199322Smav				ctlr->interrupt[unit].function(arg);
495195534Sscottl		}
496195534Sscottl	}
497200814Smav	/* AHCI declares level triggered IS. */
498200814Smav	if (!(ctlr->quirks & AHCI_Q_EDGEIS))
499200814Smav		ATA_OUTL(ctlr->r_mem, AHCI_IS, is);
500291444Smmel	ATA_RBL(ctlr->r_mem, AHCI_IS);
501195534Sscottl}
502195534Sscottl
503195534Sscottl/*
504195534Sscottl * Simplified interrupt handler for multivector MSI mode.
505195534Sscottl */
506195534Sscottlstatic void
507195534Sscottlahci_intr_one(void *data)
508195534Sscottl{
509195534Sscottl	struct ahci_controller_irq *irq = data;
510195534Sscottl	struct ahci_controller *ctlr = irq->ctlr;
511195534Sscottl	void *arg;
512195534Sscottl	int unit;
513195534Sscottl
514195534Sscottl	unit = irq->r_irq_rid - 1;
515195534Sscottl	if ((arg = ctlr->interrupt[unit].argument))
516195534Sscottl	    ctlr->interrupt[unit].function(arg);
517202011Smav	/* AHCI declares level triggered IS. */
518256843Smav	ATA_OUTL(ctlr->r_mem, AHCI_IS, 1 << unit);
519291444Smmel	ATA_RBL(ctlr->r_mem, AHCI_IS);
520195534Sscottl}
521195534Sscottl
522256843Smavstatic void
523256843Smavahci_intr_one_edge(void *data)
524256843Smav{
525256843Smav	struct ahci_controller_irq *irq = data;
526256843Smav	struct ahci_controller *ctlr = irq->ctlr;
527256843Smav	void *arg;
528256843Smav	int unit;
529256843Smav
530256843Smav	unit = irq->r_irq_rid - 1;
531256843Smav	/* Some controllers have edge triggered IS. */
532256843Smav	ATA_OUTL(ctlr->r_mem, AHCI_IS, 1 << unit);
533256843Smav	if ((arg = ctlr->interrupt[unit].argument))
534256843Smav		ctlr->interrupt[unit].function(arg);
535291444Smmel	ATA_RBL(ctlr->r_mem, AHCI_IS);
536256843Smav}
537256843Smav
538271146Simpstruct resource *
539195534Sscottlahci_alloc_resource(device_t dev, device_t child, int type, int *rid,
540294883Sjhibbits    rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
541195534Sscottl{
542195534Sscottl	struct ahci_controller *ctlr = device_get_softc(dev);
543238805Smav	struct resource *res;
544297065Sjhibbits	rman_res_t st;
545238805Smav	int offset, size, unit;
546195534Sscottl
547238805Smav	unit = (intptr_t)device_get_ivars(child);
548238805Smav	res = NULL;
549195534Sscottl	switch (type) {
550195534Sscottl	case SYS_RES_MEMORY:
551238805Smav		if (unit >= 0) {
552238805Smav			offset = AHCI_OFFSET + (unit << 7);
553238805Smav			size = 128;
554238805Smav		} else if (*rid == 0) {
555238805Smav			offset = AHCI_EM_CTL;
556238805Smav			size = 4;
557238805Smav		} else {
558238805Smav			offset = (ctlr->emloc & 0xffff0000) >> 14;
559238805Smav			size = (ctlr->emloc & 0x0000ffff) << 2;
560238805Smav			if (*rid != 1) {
561238805Smav				if (*rid == 2 && (ctlr->capsem &
562238805Smav				    (AHCI_EM_XMT | AHCI_EM_SMB)) == 0)
563238805Smav					offset += size;
564238805Smav				else
565238805Smav					break;
566238805Smav			}
567238805Smav		}
568195534Sscottl		st = rman_get_start(ctlr->r_mem);
569195534Sscottl		res = rman_reserve_resource(&ctlr->sc_iomem, st + offset,
570238805Smav		    st + offset + size - 1, size, RF_ACTIVE, child);
571195534Sscottl		if (res) {
572195534Sscottl			bus_space_handle_t bsh;
573195534Sscottl			bus_space_tag_t bst;
574195534Sscottl			bsh = rman_get_bushandle(ctlr->r_mem);
575195534Sscottl			bst = rman_get_bustag(ctlr->r_mem);
576195534Sscottl			bus_space_subregion(bst, bsh, offset, 128, &bsh);
577195534Sscottl			rman_set_bushandle(res, bsh);
578195534Sscottl			rman_set_bustag(res, bst);
579195534Sscottl		}
580195534Sscottl		break;
581195534Sscottl	case SYS_RES_IRQ:
582195534Sscottl		if (*rid == ATA_IRQ_RID)
583195534Sscottl			res = ctlr->irqs[0].r_irq;
584195534Sscottl		break;
585195534Sscottl	}
586195534Sscottl	return (res);
587195534Sscottl}
588195534Sscottl
589271146Simpint
590195534Sscottlahci_release_resource(device_t dev, device_t child, int type, int rid,
591271146Simp    struct resource *r)
592195534Sscottl{
593195534Sscottl
594195534Sscottl	switch (type) {
595195534Sscottl	case SYS_RES_MEMORY:
596195534Sscottl		rman_release_resource(r);
597195534Sscottl		return (0);
598195534Sscottl	case SYS_RES_IRQ:
599195534Sscottl		if (rid != ATA_IRQ_RID)
600276019Ssmh			return (ENOENT);
601195534Sscottl		return (0);
602195534Sscottl	}
603195534Sscottl	return (EINVAL);
604195534Sscottl}
605195534Sscottl
606271146Simpint
607195534Sscottlahci_setup_intr(device_t dev, device_t child, struct resource *irq,
608271146Simp    int flags, driver_filter_t *filter, driver_intr_t *function,
609271146Simp    void *argument, void **cookiep)
610195534Sscottl{
611195534Sscottl	struct ahci_controller *ctlr = device_get_softc(dev);
612195534Sscottl	int unit = (intptr_t)device_get_ivars(child);
613195534Sscottl
614195534Sscottl	if (filter != NULL) {
615195534Sscottl		printf("ahci.c: we cannot use a filter here\n");
616195534Sscottl		return (EINVAL);
617195534Sscottl	}
618195534Sscottl	ctlr->interrupt[unit].function = function;
619195534Sscottl	ctlr->interrupt[unit].argument = argument;
620195534Sscottl	return (0);
621195534Sscottl}
622195534Sscottl
623271146Simpint
624195534Sscottlahci_teardown_intr(device_t dev, device_t child, struct resource *irq,
625271146Simp    void *cookie)
626195534Sscottl{
627195534Sscottl	struct ahci_controller *ctlr = device_get_softc(dev);
628195534Sscottl	int unit = (intptr_t)device_get_ivars(child);
629195534Sscottl
630195534Sscottl	ctlr->interrupt[unit].function = NULL;
631195534Sscottl	ctlr->interrupt[unit].argument = NULL;
632195534Sscottl	return (0);
633195534Sscottl}
634195534Sscottl
635271146Simpint
636195534Sscottlahci_print_child(device_t dev, device_t child)
637195534Sscottl{
638238805Smav	int retval, channel;
639195534Sscottl
640195534Sscottl	retval = bus_print_child_header(dev, child);
641238805Smav	channel = (int)(intptr_t)device_get_ivars(child);
642238805Smav	if (channel >= 0)
643238805Smav		retval += printf(" at channel %d", channel);
644195534Sscottl	retval += bus_print_child_footer(dev, child);
645195534Sscottl	return (retval);
646195534Sscottl}
647195534Sscottl
648271146Simpint
649208410Smavahci_child_location_str(device_t dev, device_t child, char *buf,
650208410Smav    size_t buflen)
651208410Smav{
652238805Smav	int channel;
653208410Smav
654238805Smav	channel = (int)(intptr_t)device_get_ivars(child);
655238805Smav	if (channel >= 0)
656238805Smav		snprintf(buf, buflen, "channel=%d", channel);
657208410Smav	return (0);
658208410Smav}
659208410Smav
660271146Simpbus_dma_tag_t
661249346Smavahci_get_dma_tag(device_t dev, device_t child)
662249346Smav{
663249346Smav	struct ahci_controller *ctlr = device_get_softc(dev);
664249346Smav
665249346Smav	return (ctlr->dma_tag);
666249346Smav}
667249346Smav
668350793Smavvoid
669350793Smavahci_attached(device_t dev, struct ahci_channel *ch)
670350793Smav{
671350793Smav	struct ahci_controller *ctlr = device_get_softc(dev);
672350793Smav
673350793Smav	mtx_lock(&ctlr->ch_mtx);
674350793Smav	ctlr->ch[ch->unit] = ch;
675350793Smav	mtx_unlock(&ctlr->ch_mtx);
676350793Smav}
677350793Smav
678350793Smavvoid
679350793Smavahci_detached(device_t dev, struct ahci_channel *ch)
680350793Smav{
681350793Smav	struct ahci_controller *ctlr = device_get_softc(dev);
682350793Smav
683350793Smav	mtx_lock(&ctlr->ch_mtx);
684350793Smav	mtx_lock(&ch->mtx);
685350793Smav	ctlr->ch[ch->unit] = NULL;
686350793Smav	mtx_unlock(&ch->mtx);
687350793Smav	mtx_unlock(&ctlr->ch_mtx);
688350793Smav}
689350793Smav
690350793Smavstruct ahci_channel *
691350793Smavahci_getch(device_t dev, int n)
692350793Smav{
693350793Smav	struct ahci_controller *ctlr = device_get_softc(dev);
694350793Smav	struct ahci_channel *ch;
695350793Smav
696350793Smav	KASSERT(n >= 0 && n < AHCI_MAX_PORTS, ("Bad channel number %d", n));
697350793Smav	mtx_lock(&ctlr->ch_mtx);
698350793Smav	ch = ctlr->ch[n];
699350793Smav	if (ch != NULL)
700350793Smav		mtx_lock(&ch->mtx);
701350793Smav	mtx_unlock(&ctlr->ch_mtx);
702350793Smav	return (ch);
703350793Smav}
704350793Smav
705350793Smavvoid
706350793Smavahci_putch(struct ahci_channel *ch)
707350793Smav{
708350793Smav
709350793Smav	mtx_unlock(&ch->mtx);
710350793Smav}
711350793Smav
712195534Sscottlstatic int
713195534Sscottlahci_ch_probe(device_t dev)
714195534Sscottl{
715195534Sscottl
716195534Sscottl	device_set_desc_copy(dev, "AHCI channel");
717280393Smav	return (BUS_PROBE_DEFAULT);
718195534Sscottl}
719195534Sscottl
720195534Sscottlstatic int
721350792Smavahci_ch_disablephy_proc(SYSCTL_HANDLER_ARGS)
722350792Smav{
723350792Smav	struct ahci_channel *ch;
724350792Smav	int error, value;
725350792Smav
726350792Smav	ch = arg1;
727350792Smav	value = ch->disablephy;
728350792Smav	error = sysctl_handle_int(oidp, &value, 0, req);
729350792Smav	if (error != 0 || req->newptr == NULL || (value != 0 && value != 1))
730350792Smav		return (error);
731350792Smav
732350792Smav	mtx_lock(&ch->mtx);
733350792Smav	ch->disablephy = value;
734350792Smav	if (value) {
735350792Smav		ahci_ch_deinit(ch->dev);
736350792Smav	} else {
737350792Smav		ahci_ch_init(ch->dev);
738350792Smav		ahci_phy_check_events(ch, ATA_SE_PHY_CHANGED | ATA_SE_EXCHANGED);
739350792Smav	}
740350792Smav	mtx_unlock(&ch->mtx);
741350792Smav
742350792Smav	return (0);
743350792Smav}
744350792Smav
745350792Smavstatic int
746195534Sscottlahci_ch_attach(device_t dev)
747195534Sscottl{
748195534Sscottl	struct ahci_controller *ctlr = device_get_softc(device_get_parent(dev));
749195534Sscottl	struct ahci_channel *ch = device_get_softc(dev);
750195534Sscottl	struct cam_devq *devq;
751350792Smav	struct sysctl_ctx_list *ctx;
752350792Smav	struct sysctl_oid *tree;
753199821Smav	int rid, error, i, sata_rev = 0;
754203123Smav	u_int32_t version;
755195534Sscottl
756195534Sscottl	ch->dev = dev;
757195534Sscottl	ch->unit = (intptr_t)device_get_ivars(dev);
758196656Smav	ch->caps = ctlr->caps;
759196656Smav	ch->caps2 = ctlr->caps2;
760285090Sloos	ch->start = ctlr->ch_start;
761199322Smav	ch->quirks = ctlr->quirks;
762271146Simp	ch->vendorid = ctlr->vendorid;
763271146Simp	ch->deviceid = ctlr->deviceid;
764271146Simp	ch->subvendorid = ctlr->subvendorid;
765271146Simp	ch->subdeviceid = ctlr->subdeviceid;
766215725Smav	ch->numslots = ((ch->caps & AHCI_CAP_NCS) >> AHCI_CAP_NCS_SHIFT) + 1;
767196656Smav	mtx_init(&ch->mtx, "AHCI channel lock", NULL, MTX_DEF);
768271457Smav	ch->pm_level = 0;
769195534Sscottl	resource_int_value(device_get_name(dev),
770195534Sscottl	    device_get_unit(dev), "pm_level", &ch->pm_level);
771256843Smav	STAILQ_INIT(&ch->doneq);
772196656Smav	if (ch->pm_level > 3)
773196656Smav		callout_init_mtx(&ch->pm_timer, &ch->mtx, 0);
774220576Smav	callout_init_mtx(&ch->reset_timer, &ch->mtx, 0);
775271146Simp	/* JMicron external ports (0) sometimes limited */
776271146Simp	if ((ctlr->quirks & AHCI_Q_SATA1_UNIT0) && ch->unit == 0)
777199821Smav		sata_rev = 1;
778203030Smav	if (ch->quirks & AHCI_Q_SATA2)
779203030Smav		sata_rev = 2;
780195534Sscottl	resource_int_value(device_get_name(dev),
781199821Smav	    device_get_unit(dev), "sata_rev", &sata_rev);
782199821Smav	for (i = 0; i < 16; i++) {
783199821Smav		ch->user[i].revision = sata_rev;
784199821Smav		ch->user[i].mode = 0;
785199821Smav		ch->user[i].bytecount = 8192;
786199821Smav		ch->user[i].tags = ch->numslots;
787207499Smav		ch->user[i].caps = 0;
788199821Smav		ch->curr[i] = ch->user[i];
789207499Smav		if (ch->pm_level) {
790207499Smav			ch->user[i].caps = CTS_SATA_CAPS_H_PMREQ |
791207499Smav			    CTS_SATA_CAPS_H_APST |
792207499Smav			    CTS_SATA_CAPS_D_PMREQ | CTS_SATA_CAPS_D_APST;
793207499Smav		}
794220602Smav		ch->user[i].caps |= CTS_SATA_CAPS_H_DMAAA |
795220602Smav		    CTS_SATA_CAPS_H_AN;
796199821Smav	}
797238805Smav	rid = 0;
798195534Sscottl	if (!(ch->r_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
799195534Sscottl	    &rid, RF_ACTIVE)))
800195534Sscottl		return (ENXIO);
801305797Smav	ch->chcaps = ATA_INL(ch->r_mem, AHCI_P_CMD);
802305797Smav	version = ATA_INL(ctlr->r_mem, AHCI_VS);
803305797Smav	if (version < 0x00010200 && (ctlr->caps & AHCI_CAP_FBSS))
804305797Smav		ch->chcaps |= AHCI_P_CMD_FBSCP;
805305797Smav	if (ch->caps2 & AHCI_CAP2_SDS)
806305797Smav		ch->chscaps = ATA_INL(ch->r_mem, AHCI_P_DEVSLP);
807305797Smav	if (bootverbose) {
808305797Smav		device_printf(dev, "Caps:%s%s%s%s%s%s\n",
809305797Smav		    (ch->chcaps & AHCI_P_CMD_HPCP) ? " HPCP":"",
810305797Smav		    (ch->chcaps & AHCI_P_CMD_MPSP) ? " MPSP":"",
811305797Smav		    (ch->chcaps & AHCI_P_CMD_CPD) ? " CPD":"",
812305797Smav		    (ch->chcaps & AHCI_P_CMD_ESP) ? " ESP":"",
813305797Smav		    (ch->chcaps & AHCI_P_CMD_FBSCP) ? " FBSCP":"",
814305797Smav		    (ch->chscaps & AHCI_P_DEVSLP_DSP) ? " DSP":"");
815305797Smav	}
816195534Sscottl	ahci_dmainit(dev);
817195534Sscottl	ahci_slotsalloc(dev);
818279320Smav	mtx_lock(&ch->mtx);
819208375Smav	ahci_ch_init(dev);
820195534Sscottl	rid = ATA_IRQ_RID;
821195534Sscottl	if (!(ch->r_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ,
822195534Sscottl	    &rid, RF_SHAREABLE | RF_ACTIVE))) {
823195534Sscottl		device_printf(dev, "Unable to map interrupt\n");
824208813Smav		error = ENXIO;
825208813Smav		goto err0;
826195534Sscottl	}
827195534Sscottl	if ((bus_setup_intr(dev, ch->r_irq, ATA_INTR_FLAGS, NULL,
828256843Smav	    ctlr->direct ? ahci_ch_intr_direct : ahci_ch_intr,
829271261Smav	    ch, &ch->ih))) {
830195534Sscottl		device_printf(dev, "Unable to setup interrupt\n");
831195534Sscottl		error = ENXIO;
832195534Sscottl		goto err1;
833195534Sscottl	}
834195534Sscottl	/* Create the device queue for our SIM. */
835195534Sscottl	devq = cam_simq_alloc(ch->numslots);
836195534Sscottl	if (devq == NULL) {
837195534Sscottl		device_printf(dev, "Unable to allocate simq\n");
838195534Sscottl		error = ENOMEM;
839195534Sscottl		goto err1;
840195534Sscottl	}
841195534Sscottl	/* Construct SIM entry */
842195534Sscottl	ch->sim = cam_sim_alloc(ahciaction, ahcipoll, "ahcich", ch,
843271261Smav	    device_get_unit(dev), (struct mtx *)&ch->mtx,
844313445Smav	    (ch->quirks & AHCI_Q_NOCCS) ? 1 : min(2, ch->numslots),
845199278Smav	    (ch->caps & AHCI_CAP_SNCQ) ? ch->numslots : 0,
846199278Smav	    devq);
847195534Sscottl	if (ch->sim == NULL) {
848208813Smav		cam_simq_free(devq);
849195534Sscottl		device_printf(dev, "unable to allocate sim\n");
850195534Sscottl		error = ENOMEM;
851208813Smav		goto err1;
852195534Sscottl	}
853195534Sscottl	if (xpt_bus_register(ch->sim, dev, 0) != CAM_SUCCESS) {
854195534Sscottl		device_printf(dev, "unable to register xpt bus\n");
855195534Sscottl		error = ENXIO;
856195534Sscottl		goto err2;
857195534Sscottl	}
858195534Sscottl	if (xpt_create_path(&ch->path, /*periph*/NULL, cam_sim_path(ch->sim),
859195534Sscottl	    CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
860195534Sscottl		device_printf(dev, "unable to create path\n");
861195534Sscottl		error = ENXIO;
862195534Sscottl		goto err3;
863195534Sscottl	}
864196656Smav	if (ch->pm_level > 3) {
865196656Smav		callout_reset(&ch->pm_timer,
866196656Smav		    (ch->pm_level == 4) ? hz / 1000 : hz / 8,
867271261Smav		    ahci_ch_pm, ch);
868196656Smav	}
869195534Sscottl	mtx_unlock(&ch->mtx);
870350793Smav	ahci_attached(device_get_parent(dev), ch);
871350792Smav	ctx = device_get_sysctl_ctx(dev);
872350792Smav	tree = device_get_sysctl_tree(dev);
873350792Smav	SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "disable_phy",
874350792Smav	    CTLFLAG_RW | CTLTYPE_UINT, ch, 0, ahci_ch_disablephy_proc, "IU",
875350792Smav	    "Disable PHY");
876195534Sscottl	return (0);
877195534Sscottl
878195534Sscottlerr3:
879195534Sscottl	xpt_bus_deregister(cam_sim_path(ch->sim));
880195534Sscottlerr2:
881195534Sscottl	cam_sim_free(ch->sim, /*free_devq*/TRUE);
882195534Sscottlerr1:
883195534Sscottl	bus_release_resource(dev, SYS_RES_IRQ, ATA_IRQ_RID, ch->r_irq);
884208813Smaverr0:
885195534Sscottl	bus_release_resource(dev, SYS_RES_MEMORY, ch->unit, ch->r_mem);
886195534Sscottl	mtx_unlock(&ch->mtx);
887214325Smav	mtx_destroy(&ch->mtx);
888195534Sscottl	return (error);
889195534Sscottl}
890195534Sscottl
891195534Sscottlstatic int
892195534Sscottlahci_ch_detach(device_t dev)
893195534Sscottl{
894195534Sscottl	struct ahci_channel *ch = device_get_softc(dev);
895195534Sscottl
896350793Smav	ahci_detached(device_get_parent(dev), ch);
897195534Sscottl	mtx_lock(&ch->mtx);
898195534Sscottl	xpt_async(AC_LOST_DEVICE, ch->path, NULL);
899220576Smav	/* Forget about reset. */
900220576Smav	if (ch->resetting) {
901220576Smav		ch->resetting = 0;
902220576Smav		xpt_release_simq(ch->sim, TRUE);
903220576Smav	}
904195534Sscottl	xpt_free_path(ch->path);
905195534Sscottl	xpt_bus_deregister(cam_sim_path(ch->sim));
906195534Sscottl	cam_sim_free(ch->sim, /*free_devq*/TRUE);
907195534Sscottl	mtx_unlock(&ch->mtx);
908195534Sscottl
909196656Smav	if (ch->pm_level > 3)
910196656Smav		callout_drain(&ch->pm_timer);
911220576Smav	callout_drain(&ch->reset_timer);
912195534Sscottl	bus_teardown_intr(dev, ch->r_irq, ch->ih);
913195534Sscottl	bus_release_resource(dev, SYS_RES_IRQ, ATA_IRQ_RID, ch->r_irq);
914195534Sscottl
915208375Smav	ahci_ch_deinit(dev);
916195534Sscottl	ahci_slotsfree(dev);
917195534Sscottl	ahci_dmafini(dev);
918195534Sscottl
919195534Sscottl	bus_release_resource(dev, SYS_RES_MEMORY, ch->unit, ch->r_mem);
920195534Sscottl	mtx_destroy(&ch->mtx);
921195534Sscottl	return (0);
922195534Sscottl}
923195534Sscottl
924195534Sscottlstatic int
925208375Smavahci_ch_init(device_t dev)
926195534Sscottl{
927195534Sscottl	struct ahci_channel *ch = device_get_softc(dev);
928208375Smav	uint64_t work;
929195534Sscottl
930208375Smav	/* Disable port interrupts */
931208375Smav	ATA_OUTL(ch->r_mem, AHCI_P_IE, 0);
932208375Smav	/* Setup work areas */
933208375Smav	work = ch->dma.work_bus + AHCI_CL_OFFSET;
934208375Smav	ATA_OUTL(ch->r_mem, AHCI_P_CLB, work & 0xffffffff);
935208375Smav	ATA_OUTL(ch->r_mem, AHCI_P_CLBU, work >> 32);
936208375Smav	work = ch->dma.rfis_bus;
937208375Smav	ATA_OUTL(ch->r_mem, AHCI_P_FB, work & 0xffffffff);
938208375Smav	ATA_OUTL(ch->r_mem, AHCI_P_FBU, work >> 32);
939208375Smav	/* Activate the channel and power/spin up device */
940208375Smav	ATA_OUTL(ch->r_mem, AHCI_P_CMD,
941208375Smav	     (AHCI_P_CMD_ACTIVE | AHCI_P_CMD_POD | AHCI_P_CMD_SUD |
942208375Smav	     ((ch->pm_level == 2 || ch->pm_level == 3) ? AHCI_P_CMD_ALPE : 0) |
943208375Smav	     ((ch->pm_level > 2) ? AHCI_P_CMD_ASP : 0 )));
944271261Smav	ahci_start_fr(ch);
945271261Smav	ahci_start(ch, 1);
946208375Smav	return (0);
947208375Smav}
948208375Smav
949208375Smavstatic int
950208375Smavahci_ch_deinit(device_t dev)
951208375Smav{
952208375Smav	struct ahci_channel *ch = device_get_softc(dev);
953208375Smav
954195534Sscottl	/* Disable port interrupts. */
955195534Sscottl	ATA_OUTL(ch->r_mem, AHCI_P_IE, 0);
956195534Sscottl	/* Reset command register. */
957271261Smav	ahci_stop(ch);
958271261Smav	ahci_stop_fr(ch);
959195534Sscottl	ATA_OUTL(ch->r_mem, AHCI_P_CMD, 0);
960195534Sscottl	/* Allow everything, including partial and slumber modes. */
961195534Sscottl	ATA_OUTL(ch->r_mem, AHCI_P_SCTL, 0);
962195534Sscottl	/* Request slumber mode transition and give some time to get there. */
963195534Sscottl	ATA_OUTL(ch->r_mem, AHCI_P_CMD, AHCI_P_CMD_SLUMBER);
964195534Sscottl	DELAY(100);
965195534Sscottl	/* Disable PHY. */
966195534Sscottl	ATA_OUTL(ch->r_mem, AHCI_P_SCTL, ATA_SC_DET_DISABLE);
967195534Sscottl	return (0);
968195534Sscottl}
969195534Sscottl
970195534Sscottlstatic int
971208375Smavahci_ch_suspend(device_t dev)
972208375Smav{
973208375Smav	struct ahci_channel *ch = device_get_softc(dev);
974208375Smav
975208375Smav	mtx_lock(&ch->mtx);
976208375Smav	xpt_freeze_simq(ch->sim, 1);
977220576Smav	/* Forget about reset. */
978220576Smav	if (ch->resetting) {
979220576Smav		ch->resetting = 0;
980220576Smav		callout_stop(&ch->reset_timer);
981220576Smav		xpt_release_simq(ch->sim, TRUE);
982220576Smav	}
983208375Smav	while (ch->oslots)
984208375Smav		msleep(ch, &ch->mtx, PRIBIO, "ahcisusp", hz/100);
985208375Smav	ahci_ch_deinit(dev);
986208375Smav	mtx_unlock(&ch->mtx);
987208375Smav	return (0);
988208375Smav}
989208375Smav
990208375Smavstatic int
991195534Sscottlahci_ch_resume(device_t dev)
992195534Sscottl{
993195534Sscottl	struct ahci_channel *ch = device_get_softc(dev);
994195534Sscottl
995208375Smav	mtx_lock(&ch->mtx);
996208375Smav	ahci_ch_init(dev);
997271261Smav	ahci_reset(ch);
998208375Smav	xpt_release_simq(ch->sim, TRUE);
999208375Smav	mtx_unlock(&ch->mtx);
1000195534Sscottl	return (0);
1001195534Sscottl}
1002195534Sscottl
1003195534Sscottldevclass_t ahcich_devclass;
1004195534Sscottlstatic device_method_t ahcich_methods[] = {
1005195534Sscottl	DEVMETHOD(device_probe,     ahci_ch_probe),
1006195534Sscottl	DEVMETHOD(device_attach,    ahci_ch_attach),
1007195534Sscottl	DEVMETHOD(device_detach,    ahci_ch_detach),
1008195534Sscottl	DEVMETHOD(device_suspend,   ahci_ch_suspend),
1009195534Sscottl	DEVMETHOD(device_resume,    ahci_ch_resume),
1010276344Smarius	DEVMETHOD_END
1011195534Sscottl};
1012195534Sscottlstatic driver_t ahcich_driver = {
1013195534Sscottl        "ahcich",
1014195534Sscottl        ahcich_methods,
1015195534Sscottl        sizeof(struct ahci_channel)
1016195534Sscottl};
1017276344SmariusDRIVER_MODULE(ahcich, ahci, ahcich_driver, ahcich_devclass, NULL, NULL);
1018195534Sscottl
1019195534Sscottlstruct ahci_dc_cb_args {
1020195534Sscottl	bus_addr_t maddr;
1021195534Sscottl	int error;
1022195534Sscottl};
1023195534Sscottl
1024195534Sscottlstatic void
1025195534Sscottlahci_dmainit(device_t dev)
1026195534Sscottl{
1027195534Sscottl	struct ahci_channel *ch = device_get_softc(dev);
1028195534Sscottl	struct ahci_dc_cb_args dcba;
1029203123Smav	size_t rfsize;
1030343014Skib	int error;
1031195534Sscottl
1032195534Sscottl	/* Command area. */
1033343014Skib	error = bus_dma_tag_create(bus_get_dma_tag(dev), 1024, 0,
1034249346Smav	    BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR,
1035195534Sscottl	    NULL, NULL, AHCI_WORK_SIZE, 1, AHCI_WORK_SIZE,
1036343014Skib	    0, NULL, NULL, &ch->dma.work_tag);
1037343014Skib	if (error != 0)
1038195534Sscottl		goto error;
1039343014Skib	error = bus_dmamem_alloc(ch->dma.work_tag, (void **)&ch->dma.work,
1040343014Skib	    BUS_DMA_ZERO, &ch->dma.work_map);
1041343014Skib	if (error != 0)
1042195534Sscottl		goto error;
1043343014Skib	error = bus_dmamap_load(ch->dma.work_tag, ch->dma.work_map, ch->dma.work,
1044343014Skib	    AHCI_WORK_SIZE, ahci_dmasetupc_cb, &dcba, BUS_DMA_NOWAIT);
1045343014Skib	if (error != 0 || (error = dcba.error) != 0) {
1046195534Sscottl		bus_dmamem_free(ch->dma.work_tag, ch->dma.work, ch->dma.work_map);
1047195534Sscottl		goto error;
1048195534Sscottl	}
1049195534Sscottl	ch->dma.work_bus = dcba.maddr;
1050195534Sscottl	/* FIS receive area. */
1051203123Smav	if (ch->chcaps & AHCI_P_CMD_FBSCP)
1052203123Smav	    rfsize = 4096;
1053203123Smav	else
1054203123Smav	    rfsize = 256;
1055343014Skib	error = bus_dma_tag_create(bus_get_dma_tag(dev), rfsize, 0,
1056249346Smav	    BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR,
1057203123Smav	    NULL, NULL, rfsize, 1, rfsize,
1058343014Skib	    0, NULL, NULL, &ch->dma.rfis_tag);
1059343014Skib	if (error != 0)
1060195534Sscottl		goto error;
1061343014Skib	error = bus_dmamem_alloc(ch->dma.rfis_tag, (void **)&ch->dma.rfis, 0,
1062343014Skib	    &ch->dma.rfis_map);
1063343014Skib	if (error != 0)
1064195534Sscottl		goto error;
1065343014Skib	error = bus_dmamap_load(ch->dma.rfis_tag, ch->dma.rfis_map, ch->dma.rfis,
1066343014Skib	    rfsize, ahci_dmasetupc_cb, &dcba, BUS_DMA_NOWAIT);
1067343014Skib	if (error != 0 || (error = dcba.error) != 0) {
1068195534Sscottl		bus_dmamem_free(ch->dma.rfis_tag, ch->dma.rfis, ch->dma.rfis_map);
1069195534Sscottl		goto error;
1070195534Sscottl	}
1071195534Sscottl	ch->dma.rfis_bus = dcba.maddr;
1072195534Sscottl	/* Data area. */
1073343014Skib	error = bus_dma_tag_create(bus_get_dma_tag(dev), 2, 0,
1074249346Smav	    BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR,
1075195534Sscottl	    NULL, NULL,
1076195534Sscottl	    AHCI_SG_ENTRIES * PAGE_SIZE * ch->numslots,
1077195534Sscottl	    AHCI_SG_ENTRIES, AHCI_PRD_MAX,
1078343014Skib	    0, busdma_lock_mutex, &ch->mtx, &ch->dma.data_tag);
1079343014Skib	if (error != 0)
1080195534Sscottl		goto error;
1081195534Sscottl	return;
1082195534Sscottl
1083195534Sscottlerror:
1084343014Skib	device_printf(dev, "WARNING - DMA initialization failed, error %d\n",
1085343014Skib	    error);
1086195534Sscottl	ahci_dmafini(dev);
1087195534Sscottl}
1088195534Sscottl
1089195534Sscottlstatic void
1090195534Sscottlahci_dmasetupc_cb(void *xsc, bus_dma_segment_t *segs, int nsegs, int error)
1091195534Sscottl{
1092195534Sscottl	struct ahci_dc_cb_args *dcba = (struct ahci_dc_cb_args *)xsc;
1093195534Sscottl
1094195534Sscottl	if (!(dcba->error = error))
1095195534Sscottl		dcba->maddr = segs[0].ds_addr;
1096195534Sscottl}
1097195534Sscottl
1098195534Sscottlstatic void
1099195534Sscottlahci_dmafini(device_t dev)
1100195534Sscottl{
1101195534Sscottl	struct ahci_channel *ch = device_get_softc(dev);
1102195534Sscottl
1103195534Sscottl	if (ch->dma.data_tag) {
1104195534Sscottl		bus_dma_tag_destroy(ch->dma.data_tag);
1105195534Sscottl		ch->dma.data_tag = NULL;
1106195534Sscottl	}
1107195534Sscottl	if (ch->dma.rfis_bus) {
1108195534Sscottl		bus_dmamap_unload(ch->dma.rfis_tag, ch->dma.rfis_map);
1109195534Sscottl		bus_dmamem_free(ch->dma.rfis_tag, ch->dma.rfis, ch->dma.rfis_map);
1110195534Sscottl		ch->dma.rfis_bus = 0;
1111195534Sscottl		ch->dma.rfis = NULL;
1112195534Sscottl	}
1113195534Sscottl	if (ch->dma.work_bus) {
1114195534Sscottl		bus_dmamap_unload(ch->dma.work_tag, ch->dma.work_map);
1115195534Sscottl		bus_dmamem_free(ch->dma.work_tag, ch->dma.work, ch->dma.work_map);
1116195534Sscottl		ch->dma.work_bus = 0;
1117195534Sscottl		ch->dma.work = NULL;
1118195534Sscottl	}
1119195534Sscottl	if (ch->dma.work_tag) {
1120195534Sscottl		bus_dma_tag_destroy(ch->dma.work_tag);
1121195534Sscottl		ch->dma.work_tag = NULL;
1122195534Sscottl	}
1123195534Sscottl}
1124195534Sscottl
1125195534Sscottlstatic void
1126195534Sscottlahci_slotsalloc(device_t dev)
1127195534Sscottl{
1128195534Sscottl	struct ahci_channel *ch = device_get_softc(dev);
1129195534Sscottl	int i;
1130195534Sscottl
1131195534Sscottl	/* Alloc and setup command/dma slots */
1132195534Sscottl	bzero(ch->slot, sizeof(ch->slot));
1133195534Sscottl	for (i = 0; i < ch->numslots; i++) {
1134195534Sscottl		struct ahci_slot *slot = &ch->slot[i];
1135195534Sscottl
1136271261Smav		slot->ch = ch;
1137195534Sscottl		slot->slot = i;
1138195534Sscottl		slot->state = AHCI_SLOT_EMPTY;
1139195534Sscottl		slot->ccb = NULL;
1140195534Sscottl		callout_init_mtx(&slot->timeout, &ch->mtx, 0);
1141195534Sscottl
1142195534Sscottl		if (bus_dmamap_create(ch->dma.data_tag, 0, &slot->dma.data_map))
1143195534Sscottl			device_printf(ch->dev, "FAILURE - create data_map\n");
1144195534Sscottl	}
1145195534Sscottl}
1146195534Sscottl
1147195534Sscottlstatic void
1148195534Sscottlahci_slotsfree(device_t dev)
1149195534Sscottl{
1150195534Sscottl	struct ahci_channel *ch = device_get_softc(dev);
1151195534Sscottl	int i;
1152195534Sscottl
1153195534Sscottl	/* Free all dma slots */
1154195534Sscottl	for (i = 0; i < ch->numslots; i++) {
1155195534Sscottl		struct ahci_slot *slot = &ch->slot[i];
1156195534Sscottl
1157196656Smav		callout_drain(&slot->timeout);
1158195534Sscottl		if (slot->dma.data_map) {
1159195534Sscottl			bus_dmamap_destroy(ch->dma.data_tag, slot->dma.data_map);
1160195534Sscottl			slot->dma.data_map = NULL;
1161195534Sscottl		}
1162195534Sscottl	}
1163195534Sscottl}
1164195534Sscottl
1165220657Smavstatic int
1166271261Smavahci_phy_check_events(struct ahci_channel *ch, u_int32_t serr)
1167195534Sscottl{
1168195534Sscottl
1169220657Smav	if (((ch->pm_level == 0) && (serr & ATA_SE_PHY_CHANGED)) ||
1170220657Smav	    ((ch->pm_level != 0 || ch->listening) && (serr & ATA_SE_EXCHANGED))) {
1171195534Sscottl		u_int32_t status = ATA_INL(ch->r_mem, AHCI_P_SSTS);
1172203108Smav		union ccb *ccb;
1173203108Smav
1174203165Smav		if (bootverbose) {
1175220657Smav			if ((status & ATA_SS_DET_MASK) != ATA_SS_DET_NO_DEVICE)
1176271261Smav				device_printf(ch->dev, "CONNECT requested\n");
1177220657Smav			else
1178271261Smav				device_printf(ch->dev, "DISCONNECT requested\n");
1179195534Sscottl		}
1180271261Smav		ahci_reset(ch);
1181203108Smav		if ((ccb = xpt_alloc_ccb_nowait()) == NULL)
1182220657Smav			return (0);
1183203108Smav		if (xpt_create_path(&ccb->ccb_h.path, NULL,
1184203108Smav		    cam_sim_path(ch->sim),
1185203108Smav		    CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
1186203108Smav			xpt_free_ccb(ccb);
1187220657Smav			return (0);
1188203108Smav		}
1189203108Smav		xpt_rescan(ccb);
1190220657Smav		return (1);
1191195534Sscottl	}
1192220657Smav	return (0);
1193195534Sscottl}
1194195534Sscottl
1195195534Sscottlstatic void
1196271261Smavahci_cpd_check_events(struct ahci_channel *ch)
1197220657Smav{
1198220657Smav	u_int32_t status;
1199220657Smav	union ccb *ccb;
1200271261Smav	device_t dev;
1201220657Smav
1202220657Smav	if (ch->pm_level == 0)
1203220657Smav		return;
1204220657Smav
1205220657Smav	status = ATA_INL(ch->r_mem, AHCI_P_CMD);
1206220657Smav	if ((status & AHCI_P_CMD_CPD) == 0)
1207220657Smav		return;
1208220657Smav
1209220657Smav	if (bootverbose) {
1210271261Smav		dev = ch->dev;
1211220657Smav		if (status & AHCI_P_CMD_CPS) {
1212220657Smav			device_printf(dev, "COLD CONNECT requested\n");
1213220657Smav		} else
1214220657Smav			device_printf(dev, "COLD DISCONNECT requested\n");
1215220657Smav	}
1216271261Smav	ahci_reset(ch);
1217220657Smav	if ((ccb = xpt_alloc_ccb_nowait()) == NULL)
1218220657Smav		return;
1219220657Smav	if (xpt_create_path(&ccb->ccb_h.path, NULL, cam_sim_path(ch->sim),
1220220657Smav	    CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
1221220657Smav		xpt_free_ccb(ccb);
1222220657Smav		return;
1223220657Smav	}
1224220657Smav	xpt_rescan(ccb);
1225220657Smav}
1226220657Smav
1227220657Smavstatic void
1228271261Smavahci_notify_events(struct ahci_channel *ch, u_int32_t status)
1229196656Smav{
1230196656Smav	struct cam_path *dpath;
1231196656Smav	int i;
1232196656Smav
1233200196Smav	if (ch->caps & AHCI_CAP_SSNTF)
1234200196Smav		ATA_OUTL(ch->r_mem, AHCI_P_SNTF, status);
1235196656Smav	if (bootverbose)
1236271261Smav		device_printf(ch->dev, "SNTF 0x%04x\n", status);
1237196656Smav	for (i = 0; i < 16; i++) {
1238196656Smav		if ((status & (1 << i)) == 0)
1239196656Smav			continue;
1240196656Smav		if (xpt_create_path(&dpath, NULL,
1241196656Smav		    xpt_path_path_id(ch->path), i, 0) == CAM_REQ_CMP) {
1242196656Smav			xpt_async(AC_SCSI_AEN, dpath, NULL);
1243196656Smav			xpt_free_path(dpath);
1244196656Smav		}
1245196656Smav	}
1246196656Smav}
1247196656Smav
1248196656Smavstatic void
1249256843Smavahci_done(struct ahci_channel *ch, union ccb *ccb)
1250195534Sscottl{
1251256843Smav
1252256843Smav	mtx_assert(&ch->mtx, MA_OWNED);
1253256843Smav	if ((ccb->ccb_h.func_code & XPT_FC_QUEUED) == 0 ||
1254256843Smav	    ch->batch == 0) {
1255256843Smav		xpt_done(ccb);
1256256843Smav		return;
1257256843Smav	}
1258256843Smav
1259256843Smav	STAILQ_INSERT_TAIL(&ch->doneq, &ccb->ccb_h, sim_links.stqe);
1260256843Smav}
1261256843Smav
1262256843Smavstatic void
1263256843Smavahci_ch_intr(void *arg)
1264256843Smav{
1265271261Smav	struct ahci_channel *ch = (struct ahci_channel *)arg;
1266256843Smav	uint32_t istatus;
1267195534Sscottl
1268256843Smav	/* Read interrupt statuses. */
1269256843Smav	istatus = ATA_INL(ch->r_mem, AHCI_P_IS);
1270256843Smav
1271195534Sscottl	mtx_lock(&ch->mtx);
1272256843Smav	ahci_ch_intr_main(ch, istatus);
1273195534Sscottl	mtx_unlock(&ch->mtx);
1274195534Sscottl}
1275195534Sscottl
1276195534Sscottlstatic void
1277256843Smavahci_ch_intr_direct(void *arg)
1278256843Smav{
1279271261Smav	struct ahci_channel *ch = (struct ahci_channel *)arg;
1280256843Smav	struct ccb_hdr *ccb_h;
1281256843Smav	uint32_t istatus;
1282272223Ssmh	STAILQ_HEAD(, ccb_hdr) tmp_doneq = STAILQ_HEAD_INITIALIZER(tmp_doneq);
1283256843Smav
1284256843Smav	/* Read interrupt statuses. */
1285256843Smav	istatus = ATA_INL(ch->r_mem, AHCI_P_IS);
1286256843Smav
1287256843Smav	mtx_lock(&ch->mtx);
1288256843Smav	ch->batch = 1;
1289256843Smav	ahci_ch_intr_main(ch, istatus);
1290256843Smav	ch->batch = 0;
1291272223Ssmh	/*
1292272223Ssmh	 * Prevent the possibility of issues caused by processing the queue
1293272223Ssmh	 * while unlocked below by moving the contents to a local queue.
1294272223Ssmh	 */
1295272223Ssmh	STAILQ_CONCAT(&tmp_doneq, &ch->doneq);
1296256843Smav	mtx_unlock(&ch->mtx);
1297272223Ssmh	while ((ccb_h = STAILQ_FIRST(&tmp_doneq)) != NULL) {
1298272223Ssmh		STAILQ_REMOVE_HEAD(&tmp_doneq, sim_links.stqe);
1299256843Smav		xpt_done_direct((union ccb *)ccb_h);
1300256843Smav	}
1301256843Smav}
1302256843Smav
1303256843Smavstatic void
1304196656Smavahci_ch_pm(void *arg)
1305196656Smav{
1306271261Smav	struct ahci_channel *ch = (struct ahci_channel *)arg;
1307196656Smav	uint32_t work;
1308196656Smav
1309196656Smav	if (ch->numrslots != 0)
1310196656Smav		return;
1311196656Smav	work = ATA_INL(ch->r_mem, AHCI_P_CMD);
1312196656Smav	if (ch->pm_level == 4)
1313196656Smav		work |= AHCI_P_CMD_PARTIAL;
1314196656Smav	else
1315196656Smav		work |= AHCI_P_CMD_SLUMBER;
1316196656Smav	ATA_OUTL(ch->r_mem, AHCI_P_CMD, work);
1317196656Smav}
1318196656Smav
1319196656Smavstatic void
1320256843Smavahci_ch_intr_main(struct ahci_channel *ch, uint32_t istatus)
1321195534Sscottl{
1322256843Smav	uint32_t cstatus, serr = 0, sntf = 0, ok, err;
1323195534Sscottl	enum ahci_err_type et;
1324220657Smav	int i, ccs, port, reset = 0;
1325195534Sscottl
1326256843Smav	/* Clear interrupt statuses. */
1327195534Sscottl	ATA_OUTL(ch->r_mem, AHCI_P_IS, istatus);
1328195534Sscottl	/* Read command statuses. */
1329248698Smav	if (ch->numtslots != 0)
1330248698Smav		cstatus = ATA_INL(ch->r_mem, AHCI_P_SACT);
1331248698Smav	else
1332248698Smav		cstatus = 0;
1333248698Smav	if (ch->numrslots != ch->numtslots)
1334248698Smav		cstatus |= ATA_INL(ch->r_mem, AHCI_P_CI);
1335248698Smav	/* Read SNTF in one of possible ways. */
1336248704Smav	if ((istatus & AHCI_P_IX_SDB) &&
1337248704Smav	    (ch->pm_present || ch->curr[0].atapi != 0)) {
1338200196Smav		if (ch->caps & AHCI_CAP_SSNTF)
1339200196Smav			sntf = ATA_INL(ch->r_mem, AHCI_P_SNTF);
1340203123Smav		else if (ch->fbs_enabled) {
1341200196Smav			u_int8_t *fis = ch->dma.rfis + 0x58;
1342200196Smav
1343203123Smav			for (i = 0; i < 16; i++) {
1344203123Smav				if (fis[1] & 0x80) {
1345203123Smav					fis[1] &= 0x7f;
1346203123Smav	    				sntf |= 1 << i;
1347203123Smav	    			}
1348203123Smav	    			fis += 256;
1349203123Smav	    		}
1350203123Smav		} else {
1351203123Smav			u_int8_t *fis = ch->dma.rfis + 0x58;
1352203123Smav
1353200196Smav			if (fis[1] & 0x80)
1354200196Smav				sntf = (1 << (fis[1] & 0x0f));
1355200196Smav		}
1356200196Smav	}
1357195534Sscottl	/* Process PHY events */
1358198319Smav	if (istatus & (AHCI_P_IX_PC | AHCI_P_IX_PRC | AHCI_P_IX_OF |
1359198319Smav	    AHCI_P_IX_IF | AHCI_P_IX_HBD | AHCI_P_IX_HBF | AHCI_P_IX_TFE)) {
1360198319Smav		serr = ATA_INL(ch->r_mem, AHCI_P_SERR);
1361198319Smav		if (serr) {
1362198319Smav			ATA_OUTL(ch->r_mem, AHCI_P_SERR, serr);
1363271261Smav			reset = ahci_phy_check_events(ch, serr);
1364198319Smav		}
1365198319Smav	}
1366220657Smav	/* Process cold presence detection events */
1367220657Smav	if ((istatus & AHCI_P_IX_CPD) && !reset)
1368271261Smav		ahci_cpd_check_events(ch);
1369195534Sscottl	/* Process command errors */
1370198319Smav	if (istatus & (AHCI_P_IX_OF | AHCI_P_IX_IF |
1371198319Smav	    AHCI_P_IX_HBD | AHCI_P_IX_HBF | AHCI_P_IX_TFE)) {
1372313445Smav		if (ch->quirks & AHCI_Q_NOCCS) {
1373313445Smav			/*
1374313445Smav			 * ASMedia chips sometimes report failed commands as
1375313445Smav			 * completed.  Count all running commands as failed.
1376313445Smav			 */
1377313445Smav			cstatus |= ch->rslots;
1378313445Smav
1379313445Smav			/* They also report wrong CCS, so try to guess one. */
1380313445Smav			ccs = powerof2(cstatus) ? ffs(cstatus) - 1 : -1;
1381313445Smav		} else {
1382313445Smav			ccs = (ATA_INL(ch->r_mem, AHCI_P_CMD) &
1383313445Smav			    AHCI_P_CMD_CCS_MASK) >> AHCI_P_CMD_CCS_SHIFT;
1384313445Smav		}
1385203123Smav//device_printf(dev, "%s ERROR is %08x cs %08x ss %08x rs %08x tfd %02x serr %08x fbs %08x ccs %d\n",
1386203123Smav//    __func__, istatus, cstatus, sstatus, ch->rslots, ATA_INL(ch->r_mem, AHCI_P_TFD),
1387203123Smav//    serr, ATA_INL(ch->r_mem, AHCI_P_FBS), ccs);
1388203123Smav		port = -1;
1389203123Smav		if (ch->fbs_enabled) {
1390203123Smav			uint32_t fbs = ATA_INL(ch->r_mem, AHCI_P_FBS);
1391203123Smav			if (fbs & AHCI_P_FBS_SDE) {
1392203123Smav				port = (fbs & AHCI_P_FBS_DWE)
1393203123Smav				    >> AHCI_P_FBS_DWE_SHIFT;
1394203123Smav			} else {
1395203123Smav				for (i = 0; i < 16; i++) {
1396203123Smav					if (ch->numrslotspd[i] == 0)
1397203123Smav						continue;
1398203123Smav					if (port == -1)
1399203123Smav						port = i;
1400203123Smav					else if (port != i) {
1401203123Smav						port = -2;
1402203123Smav						break;
1403203123Smav					}
1404203123Smav				}
1405203123Smav			}
1406203123Smav		}
1407248698Smav		err = ch->rslots & cstatus;
1408195534Sscottl	} else {
1409195534Sscottl		ccs = 0;
1410195534Sscottl		err = 0;
1411203123Smav		port = -1;
1412195534Sscottl	}
1413298955Spfg	/* Complete all successful commands. */
1414248698Smav	ok = ch->rslots & ~cstatus;
1415195534Sscottl	for (i = 0; i < ch->numslots; i++) {
1416195534Sscottl		if ((ok >> i) & 1)
1417195534Sscottl			ahci_end_transaction(&ch->slot[i], AHCI_ERR_NONE);
1418195534Sscottl	}
1419195534Sscottl	/* On error, complete the rest of commands with error statuses. */
1420195534Sscottl	if (err) {
1421195534Sscottl		if (ch->frozen) {
1422195534Sscottl			union ccb *fccb = ch->frozen;
1423195534Sscottl			ch->frozen = NULL;
1424195534Sscottl			fccb->ccb_h.status = CAM_REQUEUE_REQ | CAM_RELEASE_SIMQ;
1425198319Smav			if (!(fccb->ccb_h.status & CAM_DEV_QFRZN)) {
1426198319Smav				xpt_freeze_devq(fccb->ccb_h.path, 1);
1427198319Smav				fccb->ccb_h.status |= CAM_DEV_QFRZN;
1428198319Smav			}
1429256843Smav			ahci_done(ch, fccb);
1430195534Sscottl		}
1431195534Sscottl		for (i = 0; i < ch->numslots; i++) {
1432195534Sscottl			/* XXX: reqests in loading state. */
1433195534Sscottl			if (((err >> i) & 1) == 0)
1434195534Sscottl				continue;
1435203123Smav			if (port >= 0 &&
1436203123Smav			    ch->slot[i].ccb->ccb_h.target_id != port)
1437203123Smav				continue;
1438198390Smav			if (istatus & AHCI_P_IX_TFE) {
1439203123Smav			    if (port != -2) {
1440195534Sscottl				/* Task File Error */
1441203123Smav				if (ch->numtslotspd[
1442203123Smav				    ch->slot[i].ccb->ccb_h.target_id] == 0) {
1443195534Sscottl					/* Untagged operation. */
1444195534Sscottl					if (i == ccs)
1445195534Sscottl						et = AHCI_ERR_TFE;
1446195534Sscottl					else
1447195534Sscottl						et = AHCI_ERR_INNOCENT;
1448195534Sscottl				} else {
1449195534Sscottl					/* Tagged operation. */
1450195534Sscottl					et = AHCI_ERR_NCQ;
1451195534Sscottl				}
1452203123Smav			    } else {
1453203123Smav				et = AHCI_ERR_TFE;
1454203123Smav				ch->fatalerr = 1;
1455203123Smav			    }
1456198390Smav			} else if (istatus & AHCI_P_IX_IF) {
1457203123Smav				if (ch->numtslots == 0 && i != ccs && port != -2)
1458198390Smav					et = AHCI_ERR_INNOCENT;
1459198390Smav				else
1460198390Smav					et = AHCI_ERR_SATA;
1461195534Sscottl			} else
1462195534Sscottl				et = AHCI_ERR_INVALID;
1463195534Sscottl			ahci_end_transaction(&ch->slot[i], et);
1464195534Sscottl		}
1465203123Smav		/*
1466203123Smav		 * We can't reinit port if there are some other
1467203123Smav		 * commands active, use resume to complete them.
1468203123Smav		 */
1469220565Smav		if (ch->rslots != 0 && !ch->recoverycmd)
1470203123Smav			ATA_OUTL(ch->r_mem, AHCI_P_FBS, AHCI_P_FBS_EN | AHCI_P_FBS_DEC);
1471195534Sscottl	}
1472196656Smav	/* Process NOTIFY events */
1473196907Smav	if (sntf)
1474271261Smav		ahci_notify_events(ch, sntf);
1475195534Sscottl}
1476195534Sscottl
1477195534Sscottl/* Must be called with channel locked. */
1478195534Sscottlstatic int
1479271261Smavahci_check_collision(struct ahci_channel *ch, union ccb *ccb)
1480195534Sscottl{
1481203123Smav	int t = ccb->ccb_h.target_id;
1482195534Sscottl
1483195534Sscottl	if ((ccb->ccb_h.func_code == XPT_ATA_IO) &&
1484195534Sscottl	    (ccb->ataio.cmd.flags & CAM_ATAIO_FPDMA)) {
1485199747Smav		/* Tagged command while we have no supported tag free. */
1486199747Smav		if (((~ch->oslots) & (0xffffffff >> (32 -
1487203123Smav		    ch->curr[t].tags))) == 0)
1488199747Smav			return (1);
1489203123Smav		/* If we have FBS */
1490203123Smav		if (ch->fbs_enabled) {
1491203123Smav			/* Tagged command while untagged are active. */
1492203123Smav			if (ch->numrslotspd[t] != 0 && ch->numtslotspd[t] == 0)
1493203123Smav				return (1);
1494203123Smav		} else {
1495203123Smav			/* Tagged command while untagged are active. */
1496203123Smav			if (ch->numrslots != 0 && ch->numtslots == 0)
1497203123Smav				return (1);
1498203123Smav			/* Tagged command while tagged to other target is active. */
1499203123Smav			if (ch->numtslots != 0 &&
1500203123Smav			    ch->taggedtarget != ccb->ccb_h.target_id)
1501203123Smav				return (1);
1502203123Smav		}
1503195534Sscottl	} else {
1504203123Smav		/* If we have FBS */
1505203123Smav		if (ch->fbs_enabled) {
1506203123Smav			/* Untagged command while tagged are active. */
1507203123Smav			if (ch->numrslotspd[t] != 0 && ch->numtslotspd[t] != 0)
1508203123Smav				return (1);
1509203123Smav		} else {
1510203123Smav			/* Untagged command while tagged are active. */
1511203123Smav			if (ch->numrslots != 0 && ch->numtslots != 0)
1512203123Smav				return (1);
1513203123Smav		}
1514195534Sscottl	}
1515195534Sscottl	if ((ccb->ccb_h.func_code == XPT_ATA_IO) &&
1516195534Sscottl	    (ccb->ataio.cmd.flags & (CAM_ATAIO_CONTROL | CAM_ATAIO_NEEDRESULT))) {
1517195534Sscottl		/* Atomic command while anything active. */
1518195534Sscottl		if (ch->numrslots != 0)
1519195534Sscottl			return (1);
1520195534Sscottl	}
1521195534Sscottl       /* We have some atomic command running. */
1522195534Sscottl       if (ch->aslots != 0)
1523195534Sscottl               return (1);
1524195534Sscottl	return (0);
1525195534Sscottl}
1526195534Sscottl
1527195534Sscottl/* Must be called with channel locked. */
1528195534Sscottlstatic void
1529271261Smavahci_begin_transaction(struct ahci_channel *ch, union ccb *ccb)
1530195534Sscottl{
1531195534Sscottl	struct ahci_slot *slot;
1532199747Smav	int tag, tags;
1533195534Sscottl
1534195534Sscottl	/* Choose empty slot. */
1535199747Smav	tags = ch->numslots;
1536199747Smav	if ((ccb->ccb_h.func_code == XPT_ATA_IO) &&
1537199747Smav	    (ccb->ataio.cmd.flags & CAM_ATAIO_FPDMA))
1538199747Smav		tags = ch->curr[ccb->ccb_h.target_id].tags;
1539271261Smav	if (ch->lastslot + 1 < tags)
1540271261Smav		tag = ffs(~(ch->oslots >> (ch->lastslot + 1)));
1541271261Smav	else
1542271261Smav		tag = 0;
1543271261Smav	if (tag == 0 || tag + ch->lastslot >= tags)
1544271261Smav		tag = ffs(~ch->oslots) - 1;
1545271261Smav	else
1546271261Smav		tag += ch->lastslot;
1547195534Sscottl	ch->lastslot = tag;
1548195534Sscottl	/* Occupy chosen slot. */
1549195534Sscottl	slot = &ch->slot[tag];
1550195534Sscottl	slot->ccb = ccb;
1551196656Smav	/* Stop PM timer. */
1552196656Smav	if (ch->numrslots == 0 && ch->pm_level > 3)
1553196656Smav		callout_stop(&ch->pm_timer);
1554195534Sscottl	/* Update channel stats. */
1555271261Smav	ch->oslots |= (1 << tag);
1556195534Sscottl	ch->numrslots++;
1557203123Smav	ch->numrslotspd[ccb->ccb_h.target_id]++;
1558195534Sscottl	if ((ccb->ccb_h.func_code == XPT_ATA_IO) &&
1559195534Sscottl	    (ccb->ataio.cmd.flags & CAM_ATAIO_FPDMA)) {
1560195534Sscottl		ch->numtslots++;
1561203123Smav		ch->numtslotspd[ccb->ccb_h.target_id]++;
1562195534Sscottl		ch->taggedtarget = ccb->ccb_h.target_id;
1563195534Sscottl	}
1564195534Sscottl	if ((ccb->ccb_h.func_code == XPT_ATA_IO) &&
1565195534Sscottl	    (ccb->ataio.cmd.flags & (CAM_ATAIO_CONTROL | CAM_ATAIO_NEEDRESULT)))
1566271261Smav		ch->aslots |= (1 << tag);
1567195534Sscottl	if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
1568195534Sscottl		slot->state = AHCI_SLOT_LOADING;
1569246713Skib		bus_dmamap_load_ccb(ch->dma.data_tag, slot->dma.data_map, ccb,
1570246713Skib		    ahci_dmasetprd, slot, 0);
1571271261Smav	} else {
1572271261Smav		slot->dma.nsegs = 0;
1573195534Sscottl		ahci_execute_transaction(slot);
1574271261Smav	}
1575195534Sscottl}
1576195534Sscottl
1577195534Sscottl/* Locked by busdma engine. */
1578195534Sscottlstatic void
1579195534Sscottlahci_dmasetprd(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
1580195534Sscottl{
1581195534Sscottl	struct ahci_slot *slot = arg;
1582271261Smav	struct ahci_channel *ch = slot->ch;
1583195534Sscottl	struct ahci_cmd_tab *ctp;
1584195534Sscottl	struct ahci_dma_prd *prd;
1585195534Sscottl	int i;
1586195534Sscottl
1587195534Sscottl	if (error) {
1588271261Smav		device_printf(ch->dev, "DMA load error\n");
1589195534Sscottl		ahci_end_transaction(slot, AHCI_ERR_INVALID);
1590195534Sscottl		return;
1591195534Sscottl	}
1592195534Sscottl	KASSERT(nsegs <= AHCI_SG_ENTRIES, ("too many DMA segment entries\n"));
1593195534Sscottl	/* Get a piece of the workspace for this request */
1594195534Sscottl	ctp = (struct ahci_cmd_tab *)
1595195534Sscottl		(ch->dma.work + AHCI_CT_OFFSET + (AHCI_CT_SIZE * slot->slot));
1596195534Sscottl	/* Fill S/G table */
1597195534Sscottl	prd = &ctp->prd_tab[0];
1598195534Sscottl	for (i = 0; i < nsegs; i++) {
1599195534Sscottl		prd[i].dba = htole64(segs[i].ds_addr);
1600195534Sscottl		prd[i].dbc = htole32((segs[i].ds_len - 1) & AHCI_PRD_MASK);
1601195534Sscottl	}
1602195534Sscottl	slot->dma.nsegs = nsegs;
1603195534Sscottl	bus_dmamap_sync(ch->dma.data_tag, slot->dma.data_map,
1604195534Sscottl	    ((slot->ccb->ccb_h.flags & CAM_DIR_IN) ?
1605195534Sscottl	    BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE));
1606195534Sscottl	ahci_execute_transaction(slot);
1607195534Sscottl}
1608195534Sscottl
1609195534Sscottl/* Must be called with channel locked. */
1610195534Sscottlstatic void
1611195534Sscottlahci_execute_transaction(struct ahci_slot *slot)
1612195534Sscottl{
1613271261Smav	struct ahci_channel *ch = slot->ch;
1614195534Sscottl	struct ahci_cmd_tab *ctp;
1615195534Sscottl	struct ahci_cmd_list *clp;
1616195534Sscottl	union ccb *ccb = slot->ccb;
1617195534Sscottl	int port = ccb->ccb_h.target_id & 0x0f;
1618222304Smav	int fis_size, i, softreset;
1619203123Smav	uint8_t *fis = ch->dma.rfis + 0x40;
1620203123Smav	uint8_t val;
1621350791Smav	uint16_t cmd_flags;
1622195534Sscottl
1623195534Sscottl	/* Get a piece of the workspace for this request */
1624195534Sscottl	ctp = (struct ahci_cmd_tab *)
1625195534Sscottl		(ch->dma.work + AHCI_CT_OFFSET + (AHCI_CT_SIZE * slot->slot));
1626195534Sscottl	/* Setup the FIS for this request */
1627271261Smav	if (!(fis_size = ahci_setup_fis(ch, ctp, ccb, slot->slot))) {
1628195534Sscottl		device_printf(ch->dev, "Setting up SATA FIS failed\n");
1629195534Sscottl		ahci_end_transaction(slot, AHCI_ERR_INVALID);
1630195534Sscottl		return;
1631195534Sscottl	}
1632195534Sscottl	/* Setup the command list entry */
1633195534Sscottl	clp = (struct ahci_cmd_list *)
1634195534Sscottl	    (ch->dma.work + AHCI_CL_OFFSET + (AHCI_CL_SIZE * slot->slot));
1635350791Smav	cmd_flags =
1636214988Smav		    (ccb->ccb_h.flags & CAM_DIR_OUT ? AHCI_CMD_WRITE : 0) |
1637214988Smav		    (ccb->ccb_h.func_code == XPT_SCSI_IO ?
1638214988Smav		     (AHCI_CMD_ATAPI | AHCI_CMD_PREFETCH) : 0) |
1639214988Smav		    (fis_size / sizeof(u_int32_t)) |
1640350791Smav		    (port << 12);
1641214988Smav	clp->prd_length = htole16(slot->dma.nsegs);
1642195534Sscottl	/* Special handling for Soft Reset command. */
1643195534Sscottl	if ((ccb->ccb_h.func_code == XPT_ATA_IO) &&
1644203123Smav	    (ccb->ataio.cmd.flags & CAM_ATAIO_CONTROL)) {
1645203123Smav		if (ccb->ataio.cmd.control & ATA_A_RESET) {
1646222304Smav			softreset = 1;
1647203123Smav			/* Kick controller into sane state */
1648271261Smav			ahci_stop(ch);
1649271261Smav			ahci_clo(ch);
1650271261Smav			ahci_start(ch, 0);
1651350791Smav			cmd_flags |= AHCI_CMD_RESET | AHCI_CMD_CLR_BUSY;
1652203123Smav		} else {
1653222304Smav			softreset = 2;
1654203123Smav			/* Prepare FIS receive area for check. */
1655203123Smav			for (i = 0; i < 20; i++)
1656203123Smav				fis[i] = 0xff;
1657203123Smav		}
1658222304Smav	} else
1659222304Smav		softreset = 0;
1660195534Sscottl	clp->bytecount = 0;
1661350791Smav	clp->cmd_flags = htole16(cmd_flags);
1662195534Sscottl	clp->cmd_table_phys = htole64(ch->dma.work_bus + AHCI_CT_OFFSET +
1663195534Sscottl				  (AHCI_CT_SIZE * slot->slot));
1664195534Sscottl	bus_dmamap_sync(ch->dma.work_tag, ch->dma.work_map,
1665214988Smav	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1666195534Sscottl	bus_dmamap_sync(ch->dma.rfis_tag, ch->dma.rfis_map,
1667195534Sscottl	    BUS_DMASYNC_PREREAD);
1668195534Sscottl	/* Set ACTIVE bit for NCQ commands. */
1669195534Sscottl	if ((ccb->ccb_h.func_code == XPT_ATA_IO) &&
1670195534Sscottl	    (ccb->ataio.cmd.flags & CAM_ATAIO_FPDMA)) {
1671195534Sscottl		ATA_OUTL(ch->r_mem, AHCI_P_SACT, 1 << slot->slot);
1672195534Sscottl	}
1673203123Smav	/* If FBS is enabled, set PMP port. */
1674203123Smav	if (ch->fbs_enabled) {
1675203123Smav		ATA_OUTL(ch->r_mem, AHCI_P_FBS, AHCI_P_FBS_EN |
1676203123Smav		    (port << AHCI_P_FBS_DEV_SHIFT));
1677203123Smav	}
1678195534Sscottl	/* Issue command to the controller. */
1679195534Sscottl	slot->state = AHCI_SLOT_RUNNING;
1680195534Sscottl	ch->rslots |= (1 << slot->slot);
1681195534Sscottl	ATA_OUTL(ch->r_mem, AHCI_P_CI, (1 << slot->slot));
1682195534Sscottl	/* Device reset commands doesn't interrupt. Poll them. */
1683195534Sscottl	if (ccb->ccb_h.func_code == XPT_ATA_IO &&
1684222304Smav	    (ccb->ataio.cmd.command == ATA_DEVICE_RESET || softreset)) {
1685220777Smav		int count, timeout = ccb->ccb_h.timeout * 100;
1686195534Sscottl		enum ahci_err_type et = AHCI_ERR_NONE;
1687195534Sscottl
1688195534Sscottl		for (count = 0; count < timeout; count++) {
1689220777Smav			DELAY(10);
1690195534Sscottl			if (!(ATA_INL(ch->r_mem, AHCI_P_CI) & (1 << slot->slot)))
1691195534Sscottl				break;
1692222304Smav			if ((ATA_INL(ch->r_mem, AHCI_P_TFD) & ATA_S_ERROR) &&
1693222304Smav			    softreset != 1) {
1694222285Smav#if 0
1695195534Sscottl				device_printf(ch->dev,
1696195534Sscottl				    "Poll error on slot %d, TFD: %04x\n",
1697195534Sscottl				    slot->slot, ATA_INL(ch->r_mem, AHCI_P_TFD));
1698222285Smav#endif
1699195534Sscottl				et = AHCI_ERR_TFE;
1700195534Sscottl				break;
1701195534Sscottl			}
1702198851Smav			/* Workaround for ATI SB600/SB700 chipsets. */
1703198851Smav			if (ccb->ccb_h.target_id == 15 &&
1704271146Simp			    (ch->quirks & AHCI_Q_ATI_PMP_BUG) &&
1705198851Smav			    (ATA_INL(ch->r_mem, AHCI_P_IS) & AHCI_P_IX_IPM)) {
1706198851Smav				et = AHCI_ERR_TIMEOUT;
1707198851Smav				break;
1708198851Smav			}
1709195534Sscottl		}
1710222304Smav
1711271163Smav		/*
1712271163Smav		 * Marvell HBAs with non-RAID firmware do not wait for
1713271163Smav		 * readiness after soft reset, so we have to wait here.
1714271196Smav		 * Marvell RAIDs do not have this problem, but instead
1715271196Smav		 * sometimes forget to update FIS receive area, breaking
1716271196Smav		 * this wait.
1717271163Smav		 */
1718271163Smav		if ((ch->quirks & AHCI_Q_NOBSYRES) == 0 &&
1719271163Smav		    (ch->quirks & AHCI_Q_ATI_PMP_BUG) == 0 &&
1720271163Smav		    softreset == 2 && et == AHCI_ERR_NONE) {
1721291427Smmel			for ( ; count < timeout; count++) {
1722291427Smmel				bus_dmamap_sync(ch->dma.rfis_tag,
1723291427Smmel				    ch->dma.rfis_map, BUS_DMASYNC_POSTREAD);
1724291427Smmel				val = fis[2];
1725291427Smmel				bus_dmamap_sync(ch->dma.rfis_tag,
1726291427Smmel				    ch->dma.rfis_map, BUS_DMASYNC_PREREAD);
1727291427Smmel				if ((val & ATA_S_BUSY) == 0)
1728291427Smmel					break;
1729222304Smav				DELAY(10);
1730222304Smav			}
1731222304Smav		}
1732222304Smav
1733195534Sscottl		if (timeout && (count >= timeout)) {
1734271261Smav			device_printf(ch->dev, "Poll timeout on slot %d port %d\n",
1735222304Smav			    slot->slot, port);
1736271261Smav			device_printf(ch->dev, "is %08x cs %08x ss %08x "
1737224498Smav			    "rs %08x tfd %02x serr %08x cmd %08x\n",
1738203108Smav			    ATA_INL(ch->r_mem, AHCI_P_IS),
1739203108Smav			    ATA_INL(ch->r_mem, AHCI_P_CI),
1740203108Smav			    ATA_INL(ch->r_mem, AHCI_P_SACT), ch->rslots,
1741203108Smav			    ATA_INL(ch->r_mem, AHCI_P_TFD),
1742224498Smav			    ATA_INL(ch->r_mem, AHCI_P_SERR),
1743224498Smav			    ATA_INL(ch->r_mem, AHCI_P_CMD));
1744195534Sscottl			et = AHCI_ERR_TIMEOUT;
1745195534Sscottl		}
1746222304Smav
1747203123Smav		/* Kick controller into sane state and enable FBS. */
1748222304Smav		if (softreset == 2)
1749222285Smav			ch->eslots |= (1 << slot->slot);
1750222285Smav		ahci_end_transaction(slot, et);
1751195534Sscottl		return;
1752195534Sscottl	}
1753195534Sscottl	/* Start command execution timeout */
1754274819Ssmh	callout_reset_sbt(&slot->timeout, SBT_1MS * ccb->ccb_h.timeout / 2,
1755274819Ssmh	    0, (timeout_t*)ahci_timeout, slot, 0);
1756195534Sscottl	return;
1757195534Sscottl}
1758195534Sscottl
1759203873Smav/* Must be called with channel locked. */
1760203873Smavstatic void
1761271261Smavahci_process_timeout(struct ahci_channel *ch)
1762203873Smav{
1763203873Smav	int i;
1764203873Smav
1765203873Smav	mtx_assert(&ch->mtx, MA_OWNED);
1766203873Smav	/* Handle the rest of commands. */
1767203873Smav	for (i = 0; i < ch->numslots; i++) {
1768203873Smav		/* Do we have a running request on slot? */
1769203873Smav		if (ch->slot[i].state < AHCI_SLOT_RUNNING)
1770203873Smav			continue;
1771203873Smav		ahci_end_transaction(&ch->slot[i], AHCI_ERR_TIMEOUT);
1772203873Smav	}
1773203873Smav}
1774203873Smav
1775203873Smav/* Must be called with channel locked. */
1776203873Smavstatic void
1777271261Smavahci_rearm_timeout(struct ahci_channel *ch)
1778203873Smav{
1779203873Smav	int i;
1780203873Smav
1781203873Smav	mtx_assert(&ch->mtx, MA_OWNED);
1782203873Smav	for (i = 0; i < ch->numslots; i++) {
1783203873Smav		struct ahci_slot *slot = &ch->slot[i];
1784203873Smav
1785203873Smav		/* Do we have a running request on slot? */
1786203873Smav		if (slot->state < AHCI_SLOT_RUNNING)
1787203873Smav			continue;
1788203873Smav		if ((ch->toslots & (1 << i)) == 0)
1789203873Smav			continue;
1790274819Ssmh		callout_reset_sbt(&slot->timeout,
1791274819Ssmh    	    	    SBT_1MS * slot->ccb->ccb_h.timeout / 2, 0,
1792274819Ssmh		    (timeout_t*)ahci_timeout, slot, 0);
1793203873Smav	}
1794203873Smav}
1795203873Smav
1796195534Sscottl/* Locked by callout mechanism. */
1797195534Sscottlstatic void
1798195534Sscottlahci_timeout(struct ahci_slot *slot)
1799195534Sscottl{
1800271261Smav	struct ahci_channel *ch = slot->ch;
1801271261Smav	device_t dev = ch->dev;
1802198319Smav	uint32_t sstatus;
1803198319Smav	int ccs;
1804195534Sscottl	int i;
1805195534Sscottl
1806196656Smav	/* Check for stale timeout. */
1807198319Smav	if (slot->state < AHCI_SLOT_RUNNING)
1808196656Smav		return;
1809196656Smav
1810198319Smav	/* Check if slot was not being executed last time we checked. */
1811198319Smav	if (slot->state < AHCI_SLOT_EXECUTING) {
1812198319Smav		/* Check if slot started executing. */
1813198319Smav		sstatus = ATA_INL(ch->r_mem, AHCI_P_SACT);
1814198319Smav		ccs = (ATA_INL(ch->r_mem, AHCI_P_CMD) & AHCI_P_CMD_CCS_MASK)
1815198319Smav		    >> AHCI_P_CMD_CCS_SHIFT;
1816203123Smav		if ((sstatus & (1 << slot->slot)) != 0 || ccs == slot->slot ||
1817224498Smav		    ch->fbs_enabled || ch->wrongccs)
1818198319Smav			slot->state = AHCI_SLOT_EXECUTING;
1819224498Smav		else if ((ch->rslots & (1 << ccs)) == 0) {
1820224498Smav			ch->wrongccs = 1;
1821224498Smav			slot->state = AHCI_SLOT_EXECUTING;
1822224498Smav		}
1823198319Smav
1824274819Ssmh		callout_reset_sbt(&slot->timeout,
1825274819Ssmh	    	    SBT_1MS * slot->ccb->ccb_h.timeout / 2, 0,
1826274819Ssmh		    (timeout_t*)ahci_timeout, slot, 0);
1827198319Smav		return;
1828198319Smav	}
1829198319Smav
1830222304Smav	device_printf(dev, "Timeout on slot %d port %d\n",
1831222304Smav	    slot->slot, slot->ccb->ccb_h.target_id & 0x0f);
1832224498Smav	device_printf(dev, "is %08x cs %08x ss %08x rs %08x tfd %02x "
1833224498Smav	    "serr %08x cmd %08x\n",
1834198319Smav	    ATA_INL(ch->r_mem, AHCI_P_IS), ATA_INL(ch->r_mem, AHCI_P_CI),
1835198319Smav	    ATA_INL(ch->r_mem, AHCI_P_SACT), ch->rslots,
1836224498Smav	    ATA_INL(ch->r_mem, AHCI_P_TFD), ATA_INL(ch->r_mem, AHCI_P_SERR),
1837224498Smav	    ATA_INL(ch->r_mem, AHCI_P_CMD));
1838195534Sscottl
1839197838Smav	/* Handle frozen command. */
1840195534Sscottl	if (ch->frozen) {
1841195534Sscottl		union ccb *fccb = ch->frozen;
1842195534Sscottl		ch->frozen = NULL;
1843195534Sscottl		fccb->ccb_h.status = CAM_REQUEUE_REQ | CAM_RELEASE_SIMQ;
1844198319Smav		if (!(fccb->ccb_h.status & CAM_DEV_QFRZN)) {
1845198319Smav			xpt_freeze_devq(fccb->ccb_h.path, 1);
1846198319Smav			fccb->ccb_h.status |= CAM_DEV_QFRZN;
1847198319Smav		}
1848256843Smav		ahci_done(ch, fccb);
1849195534Sscottl	}
1850224498Smav	if (!ch->fbs_enabled && !ch->wrongccs) {
1851203873Smav		/* Without FBS we know real timeout source. */
1852203873Smav		ch->fatalerr = 1;
1853203873Smav		/* Handle command with timeout. */
1854203873Smav		ahci_end_transaction(&ch->slot[slot->slot], AHCI_ERR_TIMEOUT);
1855203873Smav		/* Handle the rest of commands. */
1856203873Smav		for (i = 0; i < ch->numslots; i++) {
1857203873Smav			/* Do we have a running request on slot? */
1858203873Smav			if (ch->slot[i].state < AHCI_SLOT_RUNNING)
1859203873Smav				continue;
1860203873Smav			ahci_end_transaction(&ch->slot[i], AHCI_ERR_INNOCENT);
1861203873Smav		}
1862203873Smav	} else {
1863203873Smav		/* With FBS we wait for other commands timeout and pray. */
1864203873Smav		if (ch->toslots == 0)
1865203873Smav			xpt_freeze_simq(ch->sim, 1);
1866203873Smav		ch->toslots |= (1 << slot->slot);
1867203873Smav		if ((ch->rslots & ~ch->toslots) == 0)
1868271261Smav			ahci_process_timeout(ch);
1869203873Smav		else
1870203873Smav			device_printf(dev, " ... waiting for slots %08x\n",
1871203873Smav			    ch->rslots & ~ch->toslots);
1872195534Sscottl	}
1873195534Sscottl}
1874195534Sscottl
1875195534Sscottl/* Must be called with channel locked. */
1876195534Sscottlstatic void
1877195534Sscottlahci_end_transaction(struct ahci_slot *slot, enum ahci_err_type et)
1878195534Sscottl{
1879271261Smav	struct ahci_channel *ch = slot->ch;
1880195534Sscottl	union ccb *ccb = slot->ccb;
1881214988Smav	struct ahci_cmd_list *clp;
1882212732Smav	int lastto;
1883222304Smav	uint32_t sig;
1884195534Sscottl
1885195534Sscottl	bus_dmamap_sync(ch->dma.work_tag, ch->dma.work_map,
1886214988Smav	    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
1887214988Smav	clp = (struct ahci_cmd_list *)
1888214988Smav	    (ch->dma.work + AHCI_CL_OFFSET + (AHCI_CL_SIZE * slot->slot));
1889195534Sscottl	/* Read result registers to the result struct
1890195534Sscottl	 * May be incorrect if several commands finished same time,
1891195534Sscottl	 * so read only when sure or have to.
1892195534Sscottl	 */
1893195534Sscottl	if (ccb->ccb_h.func_code == XPT_ATA_IO) {
1894195534Sscottl		struct ata_res *res = &ccb->ataio.res;
1895195534Sscottl
1896195534Sscottl		if ((et == AHCI_ERR_TFE) ||
1897195534Sscottl		    (ccb->ataio.cmd.flags & CAM_ATAIO_NEEDRESULT)) {
1898195534Sscottl			u_int8_t *fis = ch->dma.rfis + 0x40;
1899195534Sscottl
1900195534Sscottl			bus_dmamap_sync(ch->dma.rfis_tag, ch->dma.rfis_map,
1901195534Sscottl			    BUS_DMASYNC_POSTREAD);
1902203123Smav			if (ch->fbs_enabled) {
1903203123Smav				fis += ccb->ccb_h.target_id * 256;
1904203123Smav				res->status = fis[2];
1905203123Smav				res->error = fis[3];
1906203123Smav			} else {
1907203123Smav				uint16_t tfd = ATA_INL(ch->r_mem, AHCI_P_TFD);
1908203123Smav
1909203123Smav				res->status = tfd;
1910203123Smav				res->error = tfd >> 8;
1911203123Smav			}
1912195534Sscottl			res->lba_low = fis[4];
1913195534Sscottl			res->lba_mid = fis[5];
1914195534Sscottl			res->lba_high = fis[6];
1915195534Sscottl			res->device = fis[7];
1916195534Sscottl			res->lba_low_exp = fis[8];
1917195534Sscottl			res->lba_mid_exp = fis[9];
1918195534Sscottl			res->lba_high_exp = fis[10];
1919195534Sscottl			res->sector_count = fis[12];
1920195534Sscottl			res->sector_count_exp = fis[13];
1921222304Smav
1922222304Smav			/*
1923222304Smav			 * Some weird controllers do not return signature in
1924222304Smav			 * FIS receive area. Read it from PxSIG register.
1925222304Smav			 */
1926222304Smav			if ((ch->quirks & AHCI_Q_ALTSIG) &&
1927222304Smav			    (ccb->ataio.cmd.flags & CAM_ATAIO_CONTROL) &&
1928222304Smav			    (ccb->ataio.cmd.control & ATA_A_RESET) == 0) {
1929222304Smav				sig = ATA_INL(ch->r_mem,  AHCI_P_SIG);
1930222304Smav				res->lba_high = sig >> 24;
1931222304Smav				res->lba_mid = sig >> 16;
1932222304Smav				res->lba_low = sig >> 8;
1933222304Smav				res->sector_count = sig;
1934222304Smav			}
1935195534Sscottl		} else
1936195534Sscottl			bzero(res, sizeof(*res));
1937214988Smav		if ((ccb->ataio.cmd.flags & CAM_ATAIO_FPDMA) == 0 &&
1938218596Smav		    (ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE &&
1939218596Smav		    (ch->quirks & AHCI_Q_NOCOUNT) == 0) {
1940214988Smav			ccb->ataio.resid =
1941214988Smav			    ccb->ataio.dxfer_len - le32toh(clp->bytecount);
1942214988Smav		}
1943214988Smav	} else {
1944218596Smav		if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE &&
1945218596Smav		    (ch->quirks & AHCI_Q_NOCOUNT) == 0) {
1946214988Smav			ccb->csio.resid =
1947214988Smav			    ccb->csio.dxfer_len - le32toh(clp->bytecount);
1948214988Smav		}
1949195534Sscottl	}
1950195534Sscottl	if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
1951195534Sscottl		bus_dmamap_sync(ch->dma.data_tag, slot->dma.data_map,
1952195534Sscottl		    (ccb->ccb_h.flags & CAM_DIR_IN) ?
1953195534Sscottl		    BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
1954195534Sscottl		bus_dmamap_unload(ch->dma.data_tag, slot->dma.data_map);
1955195534Sscottl	}
1956203123Smav	if (et != AHCI_ERR_NONE)
1957203123Smav		ch->eslots |= (1 << slot->slot);
1958198319Smav	/* In case of error, freeze device for proper recovery. */
1959220565Smav	if ((et != AHCI_ERR_NONE) && (!ch->recoverycmd) &&
1960198319Smav	    !(ccb->ccb_h.status & CAM_DEV_QFRZN)) {
1961198319Smav		xpt_freeze_devq(ccb->ccb_h.path, 1);
1962198319Smav		ccb->ccb_h.status |= CAM_DEV_QFRZN;
1963198319Smav	}
1964195534Sscottl	/* Set proper result status. */
1965195534Sscottl	ccb->ccb_h.status &= ~CAM_STATUS_MASK;
1966195534Sscottl	switch (et) {
1967195534Sscottl	case AHCI_ERR_NONE:
1968195534Sscottl		ccb->ccb_h.status |= CAM_REQ_CMP;
1969195534Sscottl		if (ccb->ccb_h.func_code == XPT_SCSI_IO)
1970195534Sscottl			ccb->csio.scsi_status = SCSI_STATUS_OK;
1971195534Sscottl		break;
1972195534Sscottl	case AHCI_ERR_INVALID:
1973198851Smav		ch->fatalerr = 1;
1974195534Sscottl		ccb->ccb_h.status |= CAM_REQ_INVALID;
1975195534Sscottl		break;
1976195534Sscottl	case AHCI_ERR_INNOCENT:
1977195534Sscottl		ccb->ccb_h.status |= CAM_REQUEUE_REQ;
1978195534Sscottl		break;
1979195534Sscottl	case AHCI_ERR_TFE:
1980198319Smav	case AHCI_ERR_NCQ:
1981195534Sscottl		if (ccb->ccb_h.func_code == XPT_SCSI_IO) {
1982195534Sscottl			ccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR;
1983195534Sscottl			ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
1984195534Sscottl		} else {
1985195534Sscottl			ccb->ccb_h.status |= CAM_ATA_STATUS_ERROR;
1986195534Sscottl		}
1987195534Sscottl		break;
1988195534Sscottl	case AHCI_ERR_SATA:
1989198851Smav		ch->fatalerr = 1;
1990220565Smav		if (!ch->recoverycmd) {
1991198319Smav			xpt_freeze_simq(ch->sim, 1);
1992198319Smav			ccb->ccb_h.status &= ~CAM_STATUS_MASK;
1993198319Smav			ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
1994198319Smav		}
1995198319Smav		ccb->ccb_h.status |= CAM_UNCOR_PARITY;
1996195534Sscottl		break;
1997195534Sscottl	case AHCI_ERR_TIMEOUT:
1998220565Smav		if (!ch->recoverycmd) {
1999198319Smav			xpt_freeze_simq(ch->sim, 1);
2000198319Smav			ccb->ccb_h.status &= ~CAM_STATUS_MASK;
2001198319Smav			ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
2002198319Smav		}
2003195534Sscottl		ccb->ccb_h.status |= CAM_CMD_TIMEOUT;
2004195534Sscottl		break;
2005195534Sscottl	default:
2006198851Smav		ch->fatalerr = 1;
2007195534Sscottl		ccb->ccb_h.status |= CAM_REQ_CMP_ERR;
2008195534Sscottl	}
2009195534Sscottl	/* Free slot. */
2010199747Smav	ch->oslots &= ~(1 << slot->slot);
2011195534Sscottl	ch->rslots &= ~(1 << slot->slot);
2012195534Sscottl	ch->aslots &= ~(1 << slot->slot);
2013195534Sscottl	slot->state = AHCI_SLOT_EMPTY;
2014195534Sscottl	slot->ccb = NULL;
2015195534Sscottl	/* Update channel stats. */
2016195534Sscottl	ch->numrslots--;
2017203123Smav	ch->numrslotspd[ccb->ccb_h.target_id]--;
2018195534Sscottl	if ((ccb->ccb_h.func_code == XPT_ATA_IO) &&
2019195534Sscottl	    (ccb->ataio.cmd.flags & CAM_ATAIO_FPDMA)) {
2020195534Sscottl		ch->numtslots--;
2021203123Smav		ch->numtslotspd[ccb->ccb_h.target_id]--;
2022195534Sscottl	}
2023212732Smav	/* Cancel timeout state if request completed normally. */
2024212732Smav	if (et != AHCI_ERR_TIMEOUT) {
2025212732Smav		lastto = (ch->toslots == (1 << slot->slot));
2026212732Smav		ch->toslots &= ~(1 << slot->slot);
2027212732Smav		if (lastto)
2028212732Smav			xpt_release_simq(ch->sim, TRUE);
2029212732Smav	}
2030195534Sscottl	/* If it was first request of reset sequence and there is no error,
2031195534Sscottl	 * proceed to second request. */
2032195534Sscottl	if ((ccb->ccb_h.func_code == XPT_ATA_IO) &&
2033195534Sscottl	    (ccb->ataio.cmd.flags & CAM_ATAIO_CONTROL) &&
2034195534Sscottl	    (ccb->ataio.cmd.control & ATA_A_RESET) &&
2035195534Sscottl	    et == AHCI_ERR_NONE) {
2036195534Sscottl		ccb->ataio.cmd.control &= ~ATA_A_RESET;
2037271261Smav		ahci_begin_transaction(ch, ccb);
2038195534Sscottl		return;
2039195534Sscottl	}
2040198851Smav	/* If it was our READ LOG command - process it. */
2041220565Smav	if (ccb->ccb_h.recovery_type == RECOVERY_READ_LOG) {
2042271261Smav		ahci_process_read_log(ch, ccb);
2043220565Smav	/* If it was our REQUEST SENSE command - process it. */
2044220565Smav	} else if (ccb->ccb_h.recovery_type == RECOVERY_REQUEST_SENSE) {
2045271261Smav		ahci_process_request_sense(ch, ccb);
2046220565Smav	/* If it was NCQ or ATAPI command error, put result on hold. */
2047220565Smav	} else if (et == AHCI_ERR_NCQ ||
2048220565Smav	    ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_SCSI_STATUS_ERROR &&
2049220565Smav	     (ccb->ccb_h.flags & CAM_DIS_AUTOSENSE) == 0)) {
2050195534Sscottl		ch->hold[slot->slot] = ccb;
2051203123Smav		ch->numhslots++;
2052198851Smav	} else
2053256843Smav		ahci_done(ch, ccb);
2054198851Smav	/* If we have no other active commands, ... */
2055198851Smav	if (ch->rslots == 0) {
2056198851Smav		/* if there was fatal error - reset port. */
2057203873Smav		if (ch->toslots != 0 || ch->fatalerr) {
2058271261Smav			ahci_reset(ch);
2059203123Smav		} else {
2060203123Smav			/* if we have slots in error, we can reinit port. */
2061203123Smav			if (ch->eslots != 0) {
2062271261Smav				ahci_stop(ch);
2063271261Smav				ahci_clo(ch);
2064271261Smav				ahci_start(ch, 1);
2065203123Smav			}
2066203123Smav			/* if there commands on hold, we can do READ LOG. */
2067220565Smav			if (!ch->recoverycmd && ch->numhslots)
2068271261Smav				ahci_issue_recovery(ch);
2069198851Smav		}
2070203873Smav	/* If all the rest of commands are in timeout - give them chance. */
2071203873Smav	} else if ((ch->rslots & ~ch->toslots) == 0 &&
2072203873Smav	    et != AHCI_ERR_TIMEOUT)
2073271261Smav		ahci_rearm_timeout(ch);
2074222285Smav	/* Unfreeze frozen command. */
2075271261Smav	if (ch->frozen && !ahci_check_collision(ch, ch->frozen)) {
2076222285Smav		union ccb *fccb = ch->frozen;
2077222285Smav		ch->frozen = NULL;
2078271261Smav		ahci_begin_transaction(ch, fccb);
2079222285Smav		xpt_release_simq(ch->sim, TRUE);
2080222285Smav	}
2081196656Smav	/* Start PM timer. */
2082207499Smav	if (ch->numrslots == 0 && ch->pm_level > 3 &&
2083207499Smav	    (ch->curr[ch->pm_present ? 15 : 0].caps & CTS_SATA_CAPS_D_PMREQ)) {
2084196656Smav		callout_schedule(&ch->pm_timer,
2085196656Smav		    (ch->pm_level == 4) ? hz / 1000 : hz / 8);
2086196656Smav	}
2087195534Sscottl}
2088195534Sscottl
2089195534Sscottlstatic void
2090271261Smavahci_issue_recovery(struct ahci_channel *ch)
2091195534Sscottl{
2092195534Sscottl	union ccb *ccb;
2093195534Sscottl	struct ccb_ataio *ataio;
2094220565Smav	struct ccb_scsiio *csio;
2095195534Sscottl	int i;
2096195534Sscottl
2097220830Smav	/* Find some held command. */
2098195534Sscottl	for (i = 0; i < ch->numslots; i++) {
2099195534Sscottl		if (ch->hold[i])
2100195534Sscottl			break;
2101195534Sscottl	}
2102195534Sscottl	ccb = xpt_alloc_ccb_nowait();
2103195534Sscottl	if (ccb == NULL) {
2104271261Smav		device_printf(ch->dev, "Unable to allocate recovery command\n");
2105220822Smavcompleteall:
2106220830Smav		/* We can't do anything -- complete held commands. */
2107220822Smav		for (i = 0; i < ch->numslots; i++) {
2108220822Smav			if (ch->hold[i] == NULL)
2109220822Smav				continue;
2110220822Smav			ch->hold[i]->ccb_h.status &= ~CAM_STATUS_MASK;
2111220822Smav			ch->hold[i]->ccb_h.status |= CAM_RESRC_UNAVAIL;
2112256843Smav			ahci_done(ch, ch->hold[i]);
2113220822Smav			ch->hold[i] = NULL;
2114220822Smav			ch->numhslots--;
2115220822Smav		}
2116271261Smav		ahci_reset(ch);
2117220822Smav		return;
2118195534Sscottl	}
2119195534Sscottl	ccb->ccb_h = ch->hold[i]->ccb_h;	/* Reuse old header. */
2120220565Smav	if (ccb->ccb_h.func_code == XPT_ATA_IO) {
2121220565Smav		/* READ LOG */
2122220565Smav		ccb->ccb_h.recovery_type = RECOVERY_READ_LOG;
2123220565Smav		ccb->ccb_h.func_code = XPT_ATA_IO;
2124220565Smav		ccb->ccb_h.flags = CAM_DIR_IN;
2125220565Smav		ccb->ccb_h.timeout = 1000;	/* 1s should be enough. */
2126220565Smav		ataio = &ccb->ataio;
2127220565Smav		ataio->data_ptr = malloc(512, M_AHCI, M_NOWAIT);
2128220565Smav		if (ataio->data_ptr == NULL) {
2129220565Smav			xpt_free_ccb(ccb);
2130271261Smav			device_printf(ch->dev,
2131220830Smav			    "Unable to allocate memory for READ LOG command\n");
2132220822Smav			goto completeall;
2133220565Smav		}
2134220565Smav		ataio->dxfer_len = 512;
2135220565Smav		bzero(&ataio->cmd, sizeof(ataio->cmd));
2136220565Smav		ataio->cmd.flags = CAM_ATAIO_48BIT;
2137220565Smav		ataio->cmd.command = 0x2F;	/* READ LOG EXT */
2138220565Smav		ataio->cmd.sector_count = 1;
2139220565Smav		ataio->cmd.sector_count_exp = 0;
2140220565Smav		ataio->cmd.lba_low = 0x10;
2141220565Smav		ataio->cmd.lba_mid = 0;
2142220565Smav		ataio->cmd.lba_mid_exp = 0;
2143220565Smav	} else {
2144220565Smav		/* REQUEST SENSE */
2145220565Smav		ccb->ccb_h.recovery_type = RECOVERY_REQUEST_SENSE;
2146220565Smav		ccb->ccb_h.recovery_slot = i;
2147220565Smav		ccb->ccb_h.func_code = XPT_SCSI_IO;
2148220565Smav		ccb->ccb_h.flags = CAM_DIR_IN;
2149220565Smav		ccb->ccb_h.status = 0;
2150220565Smav		ccb->ccb_h.timeout = 1000;	/* 1s should be enough. */
2151220565Smav		csio = &ccb->csio;
2152220565Smav		csio->data_ptr = (void *)&ch->hold[i]->csio.sense_data;
2153220565Smav		csio->dxfer_len = ch->hold[i]->csio.sense_len;
2154220565Smav		csio->cdb_len = 6;
2155220565Smav		bzero(&csio->cdb_io, sizeof(csio->cdb_io));
2156220565Smav		csio->cdb_io.cdb_bytes[0] = 0x03;
2157220565Smav		csio->cdb_io.cdb_bytes[4] = csio->dxfer_len;
2158195534Sscottl	}
2159220565Smav	/* Freeze SIM while doing recovery. */
2160220822Smav	ch->recoverycmd = 1;
2161198319Smav	xpt_freeze_simq(ch->sim, 1);
2162271261Smav	ahci_begin_transaction(ch, ccb);
2163195534Sscottl}
2164195534Sscottl
2165195534Sscottlstatic void
2166271261Smavahci_process_read_log(struct ahci_channel *ch, union ccb *ccb)
2167195534Sscottl{
2168195534Sscottl	uint8_t *data;
2169195534Sscottl	struct ata_res *res;
2170195534Sscottl	int i;
2171195534Sscottl
2172220565Smav	ch->recoverycmd = 0;
2173195534Sscottl
2174195534Sscottl	data = ccb->ataio.data_ptr;
2175195534Sscottl	if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP &&
2176195534Sscottl	    (data[0] & 0x80) == 0) {
2177195534Sscottl		for (i = 0; i < ch->numslots; i++) {
2178195534Sscottl			if (!ch->hold[i])
2179195534Sscottl				continue;
2180220565Smav			if (ch->hold[i]->ccb_h.func_code != XPT_ATA_IO)
2181220565Smav				continue;
2182195534Sscottl			if ((data[0] & 0x1F) == i) {
2183195534Sscottl				res = &ch->hold[i]->ataio.res;
2184195534Sscottl				res->status = data[2];
2185195534Sscottl				res->error = data[3];
2186195534Sscottl				res->lba_low = data[4];
2187195534Sscottl				res->lba_mid = data[5];
2188195534Sscottl				res->lba_high = data[6];
2189195534Sscottl				res->device = data[7];
2190195534Sscottl				res->lba_low_exp = data[8];
2191195534Sscottl				res->lba_mid_exp = data[9];
2192195534Sscottl				res->lba_high_exp = data[10];
2193195534Sscottl				res->sector_count = data[12];
2194195534Sscottl				res->sector_count_exp = data[13];
2195195534Sscottl			} else {
2196195534Sscottl				ch->hold[i]->ccb_h.status &= ~CAM_STATUS_MASK;
2197195534Sscottl				ch->hold[i]->ccb_h.status |= CAM_REQUEUE_REQ;
2198195534Sscottl			}
2199256843Smav			ahci_done(ch, ch->hold[i]);
2200195534Sscottl			ch->hold[i] = NULL;
2201203123Smav			ch->numhslots--;
2202195534Sscottl		}
2203195534Sscottl	} else {
2204195534Sscottl		if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)
2205271261Smav			device_printf(ch->dev, "Error while READ LOG EXT\n");
2206195534Sscottl		else if ((data[0] & 0x80) == 0) {
2207271261Smav			device_printf(ch->dev, "Non-queued command error in READ LOG EXT\n");
2208195534Sscottl		}
2209195534Sscottl		for (i = 0; i < ch->numslots; i++) {
2210195534Sscottl			if (!ch->hold[i])
2211195534Sscottl				continue;
2212220565Smav			if (ch->hold[i]->ccb_h.func_code != XPT_ATA_IO)
2213220565Smav				continue;
2214256843Smav			ahci_done(ch, ch->hold[i]);
2215195534Sscottl			ch->hold[i] = NULL;
2216203123Smav			ch->numhslots--;
2217195534Sscottl		}
2218195534Sscottl	}
2219195534Sscottl	free(ccb->ataio.data_ptr, M_AHCI);
2220195534Sscottl	xpt_free_ccb(ccb);
2221198319Smav	xpt_release_simq(ch->sim, TRUE);
2222195534Sscottl}
2223195534Sscottl
2224195534Sscottlstatic void
2225271261Smavahci_process_request_sense(struct ahci_channel *ch, union ccb *ccb)
2226220565Smav{
2227220565Smav	int i;
2228220565Smav
2229220565Smav	ch->recoverycmd = 0;
2230220565Smav
2231220565Smav	i = ccb->ccb_h.recovery_slot;
2232220565Smav	if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
2233220565Smav		ch->hold[i]->ccb_h.status |= CAM_AUTOSNS_VALID;
2234220565Smav	} else {
2235220565Smav		ch->hold[i]->ccb_h.status &= ~CAM_STATUS_MASK;
2236220565Smav		ch->hold[i]->ccb_h.status |= CAM_AUTOSENSE_FAIL;
2237220565Smav	}
2238256843Smav	ahci_done(ch, ch->hold[i]);
2239220565Smav	ch->hold[i] = NULL;
2240220565Smav	ch->numhslots--;
2241220565Smav	xpt_free_ccb(ccb);
2242220565Smav	xpt_release_simq(ch->sim, TRUE);
2243220565Smav}
2244220565Smav
2245220565Smavstatic void
2246271261Smavahci_start(struct ahci_channel *ch, int fbs)
2247195534Sscottl{
2248195534Sscottl	u_int32_t cmd;
2249195534Sscottl
2250285090Sloos	/* Run the channel start callback, if any. */
2251285090Sloos	if (ch->start)
2252285090Sloos		ch->start(ch);
2253285090Sloos
2254195534Sscottl	/* Clear SATA error register */
2255195534Sscottl	ATA_OUTL(ch->r_mem, AHCI_P_SERR, 0xFFFFFFFF);
2256195534Sscottl	/* Clear any interrupts pending on this channel */
2257195534Sscottl	ATA_OUTL(ch->r_mem, AHCI_P_IS, 0xFFFFFFFF);
2258203123Smav	/* Configure FIS-based switching if supported. */
2259203123Smav	if (ch->chcaps & AHCI_P_CMD_FBSCP) {
2260203123Smav		ch->fbs_enabled = (fbs && ch->pm_present) ? 1 : 0;
2261203123Smav		ATA_OUTL(ch->r_mem, AHCI_P_FBS,
2262203123Smav		    ch->fbs_enabled ? AHCI_P_FBS_EN : 0);
2263203123Smav	}
2264195534Sscottl	/* Start operations on this channel */
2265195534Sscottl	cmd = ATA_INL(ch->r_mem, AHCI_P_CMD);
2266207430Smav	cmd &= ~AHCI_P_CMD_PMA;
2267195534Sscottl	ATA_OUTL(ch->r_mem, AHCI_P_CMD, cmd | AHCI_P_CMD_ST |
2268195534Sscottl	    (ch->pm_present ? AHCI_P_CMD_PMA : 0));
2269195534Sscottl}
2270195534Sscottl
2271195534Sscottlstatic void
2272271261Smavahci_stop(struct ahci_channel *ch)
2273195534Sscottl{
2274195534Sscottl	u_int32_t cmd;
2275195534Sscottl	int timeout;
2276195534Sscottl
2277195534Sscottl	/* Kill all activity on this channel */
2278195534Sscottl	cmd = ATA_INL(ch->r_mem, AHCI_P_CMD);
2279195534Sscottl	ATA_OUTL(ch->r_mem, AHCI_P_CMD, cmd & ~AHCI_P_CMD_ST);
2280195534Sscottl	/* Wait for activity stop. */
2281195534Sscottl	timeout = 0;
2282195534Sscottl	do {
2283220777Smav		DELAY(10);
2284220777Smav		if (timeout++ > 50000) {
2285271261Smav			device_printf(ch->dev, "stopping AHCI engine failed\n");
2286195534Sscottl			break;
2287195534Sscottl		}
2288195534Sscottl	} while (ATA_INL(ch->r_mem, AHCI_P_CMD) & AHCI_P_CMD_CR);
2289203123Smav	ch->eslots = 0;
2290195534Sscottl}
2291195534Sscottl
2292195534Sscottlstatic void
2293271261Smavahci_clo(struct ahci_channel *ch)
2294195534Sscottl{
2295195534Sscottl	u_int32_t cmd;
2296195534Sscottl	int timeout;
2297195534Sscottl
2298195534Sscottl	/* Issue Command List Override if supported */
2299195534Sscottl	if (ch->caps & AHCI_CAP_SCLO) {
2300195534Sscottl		cmd = ATA_INL(ch->r_mem, AHCI_P_CMD);
2301195534Sscottl		cmd |= AHCI_P_CMD_CLO;
2302195534Sscottl		ATA_OUTL(ch->r_mem, AHCI_P_CMD, cmd);
2303195534Sscottl		timeout = 0;
2304195534Sscottl		do {
2305220777Smav			DELAY(10);
2306220777Smav			if (timeout++ > 50000) {
2307271261Smav			    device_printf(ch->dev, "executing CLO failed\n");
2308195534Sscottl			    break;
2309195534Sscottl			}
2310195534Sscottl		} while (ATA_INL(ch->r_mem, AHCI_P_CMD) & AHCI_P_CMD_CLO);
2311195534Sscottl	}
2312195534Sscottl}
2313195534Sscottl
2314195534Sscottlstatic void
2315271261Smavahci_stop_fr(struct ahci_channel *ch)
2316195534Sscottl{
2317195534Sscottl	u_int32_t cmd;
2318195534Sscottl	int timeout;
2319195534Sscottl
2320195534Sscottl	/* Kill all FIS reception on this channel */
2321195534Sscottl	cmd = ATA_INL(ch->r_mem, AHCI_P_CMD);
2322195534Sscottl	ATA_OUTL(ch->r_mem, AHCI_P_CMD, cmd & ~AHCI_P_CMD_FRE);
2323195534Sscottl	/* Wait for FIS reception stop. */
2324195534Sscottl	timeout = 0;
2325195534Sscottl	do {
2326220777Smav		DELAY(10);
2327220777Smav		if (timeout++ > 50000) {
2328271261Smav			device_printf(ch->dev, "stopping AHCI FR engine failed\n");
2329195534Sscottl			break;
2330195534Sscottl		}
2331195534Sscottl	} while (ATA_INL(ch->r_mem, AHCI_P_CMD) & AHCI_P_CMD_FR);
2332195534Sscottl}
2333195534Sscottl
2334195534Sscottlstatic void
2335271261Smavahci_start_fr(struct ahci_channel *ch)
2336195534Sscottl{
2337195534Sscottl	u_int32_t cmd;
2338195534Sscottl
2339195534Sscottl	/* Start FIS reception on this channel */
2340195534Sscottl	cmd = ATA_INL(ch->r_mem, AHCI_P_CMD);
2341195534Sscottl	ATA_OUTL(ch->r_mem, AHCI_P_CMD, cmd | AHCI_P_CMD_FRE);
2342195534Sscottl}
2343195534Sscottl
2344195534Sscottlstatic int
2345271261Smavahci_wait_ready(struct ahci_channel *ch, int t, int t0)
2346195534Sscottl{
2347195534Sscottl	int timeout = 0;
2348195534Sscottl	uint32_t val;
2349195534Sscottl
2350195534Sscottl	while ((val = ATA_INL(ch->r_mem, AHCI_P_TFD)) &
2351195534Sscottl	    (ATA_S_BUSY | ATA_S_DRQ)) {
2352220576Smav		if (timeout > t) {
2353220576Smav			if (t != 0) {
2354271261Smav				device_printf(ch->dev,
2355220576Smav				    "AHCI reset: device not ready after %dms "
2356220576Smav				    "(tfd = %08x)\n",
2357220576Smav				    MAX(t, 0) + t0, val);
2358220576Smav			}
2359195534Sscottl			return (EBUSY);
2360195534Sscottl		}
2361220576Smav		DELAY(1000);
2362220576Smav		timeout++;
2363220576Smav	}
2364195534Sscottl	if (bootverbose)
2365271261Smav		device_printf(ch->dev, "AHCI reset: device ready after %dms\n",
2366220576Smav		    timeout + t0);
2367195534Sscottl	return (0);
2368195534Sscottl}
2369195534Sscottl
2370195534Sscottlstatic void
2371220576Smavahci_reset_to(void *arg)
2372220576Smav{
2373271261Smav	struct ahci_channel *ch = arg;
2374220576Smav
2375220576Smav	if (ch->resetting == 0)
2376220576Smav		return;
2377220576Smav	ch->resetting--;
2378271261Smav	if (ahci_wait_ready(ch, ch->resetting == 0 ? -1 : 0,
2379220576Smav	    (310 - ch->resetting) * 100) == 0) {
2380220576Smav		ch->resetting = 0;
2381271261Smav		ahci_start(ch, 1);
2382220576Smav		xpt_release_simq(ch->sim, TRUE);
2383220576Smav		return;
2384220576Smav	}
2385220576Smav	if (ch->resetting == 0) {
2386271261Smav		ahci_clo(ch);
2387271261Smav		ahci_start(ch, 1);
2388220576Smav		xpt_release_simq(ch->sim, TRUE);
2389220576Smav		return;
2390220576Smav	}
2391220576Smav	callout_schedule(&ch->reset_timer, hz / 10);
2392220576Smav}
2393220576Smav
2394220576Smavstatic void
2395271261Smavahci_reset(struct ahci_channel *ch)
2396195534Sscottl{
2397271261Smav	struct ahci_controller *ctlr = device_get_softc(device_get_parent(ch->dev));
2398195534Sscottl	int i;
2399195534Sscottl
2400203108Smav	xpt_freeze_simq(ch->sim, 1);
2401195534Sscottl	if (bootverbose)
2402271261Smav		device_printf(ch->dev, "AHCI reset...\n");
2403220576Smav	/* Forget about previous reset. */
2404220576Smav	if (ch->resetting) {
2405220576Smav		ch->resetting = 0;
2406220576Smav		callout_stop(&ch->reset_timer);
2407220576Smav		xpt_release_simq(ch->sim, TRUE);
2408220576Smav	}
2409195534Sscottl	/* Requeue freezed command. */
2410195534Sscottl	if (ch->frozen) {
2411195534Sscottl		union ccb *fccb = ch->frozen;
2412195534Sscottl		ch->frozen = NULL;
2413195534Sscottl		fccb->ccb_h.status = CAM_REQUEUE_REQ | CAM_RELEASE_SIMQ;
2414198319Smav		if (!(fccb->ccb_h.status & CAM_DEV_QFRZN)) {
2415198319Smav			xpt_freeze_devq(fccb->ccb_h.path, 1);
2416198319Smav			fccb->ccb_h.status |= CAM_DEV_QFRZN;
2417198319Smav		}
2418256843Smav		ahci_done(ch, fccb);
2419195534Sscottl	}
2420195534Sscottl	/* Kill the engine and requeue all running commands. */
2421271261Smav	ahci_stop(ch);
2422195534Sscottl	for (i = 0; i < ch->numslots; i++) {
2423195534Sscottl		/* Do we have a running request on slot? */
2424195534Sscottl		if (ch->slot[i].state < AHCI_SLOT_RUNNING)
2425195534Sscottl			continue;
2426195534Sscottl		/* XXX; Commands in loading state. */
2427195534Sscottl		ahci_end_transaction(&ch->slot[i], AHCI_ERR_INNOCENT);
2428195534Sscottl	}
2429198851Smav	for (i = 0; i < ch->numslots; i++) {
2430198851Smav		if (!ch->hold[i])
2431198851Smav			continue;
2432256843Smav		ahci_done(ch, ch->hold[i]);
2433198851Smav		ch->hold[i] = NULL;
2434203123Smav		ch->numhslots--;
2435198851Smav	}
2436203873Smav	if (ch->toslots != 0)
2437203873Smav		xpt_release_simq(ch->sim, TRUE);
2438203123Smav	ch->eslots = 0;
2439203873Smav	ch->toslots = 0;
2440224498Smav	ch->wrongccs = 0;
2441198851Smav	ch->fatalerr = 0;
2442198319Smav	/* Tell the XPT about the event */
2443198319Smav	xpt_async(AC_BUS_RESET, ch->path, NULL);
2444195534Sscottl	/* Disable port interrupts */
2445195534Sscottl	ATA_OUTL(ch->r_mem, AHCI_P_IE, 0);
2446195534Sscottl	/* Reset and reconnect PHY, */
2447271261Smav	if (!ahci_sata_phy_reset(ch)) {
2448195534Sscottl		if (bootverbose)
2449271261Smav			device_printf(ch->dev,
2450220576Smav			    "AHCI reset: device not found\n");
2451195534Sscottl		ch->devices = 0;
2452195534Sscottl		/* Enable wanted port interrupts */
2453195534Sscottl		ATA_OUTL(ch->r_mem, AHCI_P_IE,
2454220657Smav		    (((ch->pm_level != 0) ? AHCI_P_IX_CPD | AHCI_P_IX_MP : 0) |
2455220657Smav		     AHCI_P_IX_PRC | AHCI_P_IX_PC));
2456203108Smav		xpt_release_simq(ch->sim, TRUE);
2457195534Sscottl		return;
2458195534Sscottl	}
2459220576Smav	if (bootverbose)
2460271261Smav		device_printf(ch->dev, "AHCI reset: device found\n");
2461195534Sscottl	/* Wait for clearing busy status. */
2462271261Smav	if (ahci_wait_ready(ch, dumping ? 31000 : 0, 0)) {
2463220576Smav		if (dumping)
2464271261Smav			ahci_clo(ch);
2465220576Smav		else
2466220576Smav			ch->resetting = 310;
2467220576Smav	}
2468195534Sscottl	ch->devices = 1;
2469195534Sscottl	/* Enable wanted port interrupts */
2470195534Sscottl	ATA_OUTL(ch->r_mem, AHCI_P_IE,
2471220657Smav	     (((ch->pm_level != 0) ? AHCI_P_IX_CPD | AHCI_P_IX_MP : 0) |
2472220657Smav	      AHCI_P_IX_TFE | AHCI_P_IX_HBF |
2473195534Sscottl	      AHCI_P_IX_HBD | AHCI_P_IX_IF | AHCI_P_IX_OF |
2474220657Smav	      ((ch->pm_level == 0) ? AHCI_P_IX_PRC : 0) | AHCI_P_IX_PC |
2475196656Smav	      AHCI_P_IX_DP | AHCI_P_IX_UF | (ctlr->ccc ? 0 : AHCI_P_IX_SDB) |
2476196656Smav	      AHCI_P_IX_DS | AHCI_P_IX_PS | (ctlr->ccc ? 0 : AHCI_P_IX_DHR)));
2477220576Smav	if (ch->resetting)
2478271261Smav		callout_reset(&ch->reset_timer, hz / 10, ahci_reset_to, ch);
2479220777Smav	else {
2480271261Smav		ahci_start(ch, 1);
2481220576Smav		xpt_release_simq(ch->sim, TRUE);
2482220777Smav	}
2483195534Sscottl}
2484195534Sscottl
2485195534Sscottlstatic int
2486271261Smavahci_setup_fis(struct ahci_channel *ch, struct ahci_cmd_tab *ctp, union ccb *ccb, int tag)
2487195534Sscottl{
2488195534Sscottl	u_int8_t *fis = &ctp->cfis[0];
2489195534Sscottl
2490270833Simp	bzero(fis, 20);
2491195534Sscottl	fis[0] = 0x27;  		/* host to device */
2492195534Sscottl	fis[1] = (ccb->ccb_h.target_id & 0x0f);
2493195534Sscottl	if (ccb->ccb_h.func_code == XPT_SCSI_IO) {
2494195534Sscottl		fis[1] |= 0x80;
2495195534Sscottl		fis[2] = ATA_PACKET_CMD;
2496199821Smav		if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE &&
2497199821Smav		    ch->curr[ccb->ccb_h.target_id].mode >= ATA_DMA)
2498195534Sscottl			fis[3] = ATA_F_DMA;
2499195534Sscottl		else {
2500195534Sscottl			fis[5] = ccb->csio.dxfer_len;
2501195534Sscottl		        fis[6] = ccb->csio.dxfer_len >> 8;
2502195534Sscottl		}
2503195534Sscottl		fis[7] = ATA_D_LBA;
2504195534Sscottl		fis[15] = ATA_A_4BIT;
2505195534Sscottl		bcopy((ccb->ccb_h.flags & CAM_CDB_POINTER) ?
2506195534Sscottl		    ccb->csio.cdb_io.cdb_ptr : ccb->csio.cdb_io.cdb_bytes,
2507195534Sscottl		    ctp->acmd, ccb->csio.cdb_len);
2508248687Smav		bzero(ctp->acmd + ccb->csio.cdb_len, 32 - ccb->csio.cdb_len);
2509195534Sscottl	} else if ((ccb->ataio.cmd.flags & CAM_ATAIO_CONTROL) == 0) {
2510195534Sscottl		fis[1] |= 0x80;
2511195534Sscottl		fis[2] = ccb->ataio.cmd.command;
2512195534Sscottl		fis[3] = ccb->ataio.cmd.features;
2513195534Sscottl		fis[4] = ccb->ataio.cmd.lba_low;
2514195534Sscottl		fis[5] = ccb->ataio.cmd.lba_mid;
2515195534Sscottl		fis[6] = ccb->ataio.cmd.lba_high;
2516195534Sscottl		fis[7] = ccb->ataio.cmd.device;
2517195534Sscottl		fis[8] = ccb->ataio.cmd.lba_low_exp;
2518195534Sscottl		fis[9] = ccb->ataio.cmd.lba_mid_exp;
2519195534Sscottl		fis[10] = ccb->ataio.cmd.lba_high_exp;
2520195534Sscottl		fis[11] = ccb->ataio.cmd.features_exp;
2521195534Sscottl		if (ccb->ataio.cmd.flags & CAM_ATAIO_FPDMA) {
2522195534Sscottl			fis[12] = tag << 3;
2523195534Sscottl		} else {
2524195534Sscottl			fis[12] = ccb->ataio.cmd.sector_count;
2525195534Sscottl		}
2526300207Sken		fis[13] = ccb->ataio.cmd.sector_count_exp;
2527195534Sscottl		fis[15] = ATA_A_4BIT;
2528195534Sscottl	} else {
2529195534Sscottl		fis[15] = ccb->ataio.cmd.control;
2530195534Sscottl	}
2531298143Simp	if (ccb->ataio.ata_flags & ATA_FLAG_AUX) {
2532298143Simp		fis[16] =  ccb->ataio.aux        & 0xff;
2533298143Simp		fis[17] = (ccb->ataio.aux >>  8) & 0xff;
2534298143Simp		fis[18] = (ccb->ataio.aux >> 16) & 0xff;
2535298143Simp		fis[19] = (ccb->ataio.aux >> 24) & 0xff;
2536298143Simp	}
2537195534Sscottl	return (20);
2538195534Sscottl}
2539195534Sscottl
2540195534Sscottlstatic int
2541195534Sscottlahci_sata_connect(struct ahci_channel *ch)
2542195534Sscottl{
2543195534Sscottl	u_int32_t status;
2544220829Smav	int timeout, found = 0;
2545195534Sscottl
2546195534Sscottl	/* Wait up to 100ms for "connect well" */
2547220777Smav	for (timeout = 0; timeout < 1000 ; timeout++) {
2548195534Sscottl		status = ATA_INL(ch->r_mem, AHCI_P_SSTS);
2549220829Smav		if ((status & ATA_SS_DET_MASK) != ATA_SS_DET_NO_DEVICE)
2550220829Smav			found = 1;
2551195534Sscottl		if (((status & ATA_SS_DET_MASK) == ATA_SS_DET_PHY_ONLINE) &&
2552195534Sscottl		    ((status & ATA_SS_SPD_MASK) != ATA_SS_SPD_NO_SPEED) &&
2553195534Sscottl		    ((status & ATA_SS_IPM_MASK) == ATA_SS_IPM_ACTIVE))
2554195534Sscottl			break;
2555196656Smav		if ((status & ATA_SS_DET_MASK) == ATA_SS_DET_PHY_OFFLINE) {
2556196656Smav			if (bootverbose) {
2557196656Smav				device_printf(ch->dev, "SATA offline status=%08x\n",
2558196656Smav				    status);
2559196656Smav			}
2560196656Smav			return (0);
2561196656Smav		}
2562220829Smav		if (found == 0 && timeout >= 100)
2563220829Smav			break;
2564220777Smav		DELAY(100);
2565195534Sscottl	}
2566220829Smav	if (timeout >= 1000 || !found) {
2567195534Sscottl		if (bootverbose) {
2568220829Smav			device_printf(ch->dev,
2569220829Smav			    "SATA connect timeout time=%dus status=%08x\n",
2570220829Smav			    timeout * 100, status);
2571195534Sscottl		}
2572195534Sscottl		return (0);
2573195534Sscottl	}
2574195534Sscottl	if (bootverbose) {
2575220777Smav		device_printf(ch->dev, "SATA connect time=%dus status=%08x\n",
2576220777Smav		    timeout * 100, status);
2577195534Sscottl	}
2578195534Sscottl	/* Clear SATA error register */
2579195534Sscottl	ATA_OUTL(ch->r_mem, AHCI_P_SERR, 0xffffffff);
2580195534Sscottl	return (1);
2581195534Sscottl}
2582195534Sscottl
2583195534Sscottlstatic int
2584271261Smavahci_sata_phy_reset(struct ahci_channel *ch)
2585195534Sscottl{
2586199821Smav	int sata_rev;
2587350792Smav	uint32_t val, detval;
2588195534Sscottl
2589220657Smav	if (ch->listening) {
2590220657Smav		val = ATA_INL(ch->r_mem, AHCI_P_CMD);
2591220657Smav		val |= AHCI_P_CMD_SUD;
2592220657Smav		ATA_OUTL(ch->r_mem, AHCI_P_CMD, val);
2593220657Smav		ch->listening = 0;
2594220657Smav	}
2595199821Smav	sata_rev = ch->user[ch->pm_present ? 15 : 0].revision;
2596199821Smav	if (sata_rev == 1)
2597195534Sscottl		val = ATA_SC_SPD_SPEED_GEN1;
2598199821Smav	else if (sata_rev == 2)
2599195534Sscottl		val = ATA_SC_SPD_SPEED_GEN2;
2600199821Smav	else if (sata_rev == 3)
2601195534Sscottl		val = ATA_SC_SPD_SPEED_GEN3;
2602195534Sscottl	else
2603195534Sscottl		val = 0;
2604350792Smav	detval = ahci_ch_detval(ch, ATA_SC_DET_RESET);
2605195534Sscottl	ATA_OUTL(ch->r_mem, AHCI_P_SCTL,
2606350792Smav	    detval | val |
2607196656Smav	    ATA_SC_IPM_DIS_PARTIAL | ATA_SC_IPM_DIS_SLUMBER);
2608220777Smav	DELAY(1000);
2609350792Smav	detval = ahci_ch_detval(ch, ATA_SC_DET_IDLE);
2610196656Smav	ATA_OUTL(ch->r_mem, AHCI_P_SCTL,
2611350792Smav	    detval | val | ((ch->pm_level > 0) ? 0 :
2612195534Sscottl	    (ATA_SC_IPM_DIS_PARTIAL | ATA_SC_IPM_DIS_SLUMBER)));
2613203426Smav	if (!ahci_sata_connect(ch)) {
2614220657Smav		if (ch->caps & AHCI_CAP_SSS) {
2615220657Smav			val = ATA_INL(ch->r_mem, AHCI_P_CMD);
2616220657Smav			val &= ~AHCI_P_CMD_SUD;
2617220657Smav			ATA_OUTL(ch->r_mem, AHCI_P_CMD, val);
2618220657Smav			ch->listening = 1;
2619220657Smav		} else if (ch->pm_level > 0)
2620203426Smav			ATA_OUTL(ch->r_mem, AHCI_P_SCTL, ATA_SC_DET_DISABLE);
2621203426Smav		return (0);
2622203426Smav	}
2623203426Smav	return (1);
2624195534Sscottl}
2625195534Sscottl
2626207430Smavstatic int
2627271261Smavahci_check_ids(struct ahci_channel *ch, union ccb *ccb)
2628207430Smav{
2629207430Smav
2630207430Smav	if (ccb->ccb_h.target_id > ((ch->caps & AHCI_CAP_SPM) ? 15 : 0)) {
2631207430Smav		ccb->ccb_h.status = CAM_TID_INVALID;
2632256843Smav		ahci_done(ch, ccb);
2633207430Smav		return (-1);
2634207430Smav	}
2635207430Smav	if (ccb->ccb_h.target_lun != 0) {
2636207430Smav		ccb->ccb_h.status = CAM_LUN_INVALID;
2637256843Smav		ahci_done(ch, ccb);
2638207430Smav		return (-1);
2639207430Smav	}
2640207430Smav	return (0);
2641207430Smav}
2642207430Smav
2643195534Sscottlstatic void
2644195534Sscottlahciaction(struct cam_sim *sim, union ccb *ccb)
2645195534Sscottl{
2646195534Sscottl	struct ahci_channel *ch;
2647195534Sscottl
2648195534Sscottl	CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("ahciaction func_code=%x\n",
2649195534Sscottl	    ccb->ccb_h.func_code));
2650195534Sscottl
2651195534Sscottl	ch = (struct ahci_channel *)cam_sim_softc(sim);
2652195534Sscottl	switch (ccb->ccb_h.func_code) {
2653195534Sscottl	/* Common cases first */
2654195534Sscottl	case XPT_ATA_IO:	/* Execute the requested I/O operation */
2655195534Sscottl	case XPT_SCSI_IO:
2656271261Smav		if (ahci_check_ids(ch, ccb))
2657207430Smav			return;
2658207430Smav		if (ch->devices == 0 ||
2659207430Smav		    (ch->pm_present == 0 &&
2660207430Smav		     ccb->ccb_h.target_id > 0 && ccb->ccb_h.target_id < 15)) {
2661195534Sscottl			ccb->ccb_h.status = CAM_SEL_TIMEOUT;
2662195534Sscottl			break;
2663195534Sscottl		}
2664220565Smav		ccb->ccb_h.recovery_type = RECOVERY_NONE;
2665195534Sscottl		/* Check for command collision. */
2666271261Smav		if (ahci_check_collision(ch, ccb)) {
2667195534Sscottl			/* Freeze command. */
2668195534Sscottl			ch->frozen = ccb;
2669195534Sscottl			/* We have only one frozen slot, so freeze simq also. */
2670195534Sscottl			xpt_freeze_simq(ch->sim, 1);
2671195534Sscottl			return;
2672195534Sscottl		}
2673271261Smav		ahci_begin_transaction(ch, ccb);
2674207430Smav		return;
2675195534Sscottl	case XPT_ABORT:			/* Abort the specified CCB */
2676195534Sscottl		/* XXX Implement */
2677195534Sscottl		ccb->ccb_h.status = CAM_REQ_INVALID;
2678195534Sscottl		break;
2679195534Sscottl	case XPT_SET_TRAN_SETTINGS:
2680195534Sscottl	{
2681195534Sscottl		struct	ccb_trans_settings *cts = &ccb->cts;
2682199747Smav		struct	ahci_device *d;
2683195534Sscottl
2684271261Smav		if (ahci_check_ids(ch, ccb))
2685207430Smav			return;
2686199747Smav		if (cts->type == CTS_TYPE_CURRENT_SETTINGS)
2687199747Smav			d = &ch->curr[ccb->ccb_h.target_id];
2688199747Smav		else
2689199747Smav			d = &ch->user[ccb->ccb_h.target_id];
2690199747Smav		if (cts->xport_specific.sata.valid & CTS_SATA_VALID_REVISION)
2691199747Smav			d->revision = cts->xport_specific.sata.revision;
2692199747Smav		if (cts->xport_specific.sata.valid & CTS_SATA_VALID_MODE)
2693199747Smav			d->mode = cts->xport_specific.sata.mode;
2694199747Smav		if (cts->xport_specific.sata.valid & CTS_SATA_VALID_BYTECOUNT)
2695199747Smav			d->bytecount = min(8192, cts->xport_specific.sata.bytecount);
2696199747Smav		if (cts->xport_specific.sata.valid & CTS_SATA_VALID_TAGS)
2697199747Smav			d->tags = min(ch->numslots, cts->xport_specific.sata.tags);
2698199747Smav		if (cts->xport_specific.sata.valid & CTS_SATA_VALID_PM)
2699195534Sscottl			ch->pm_present = cts->xport_specific.sata.pm_present;
2700203376Smav		if (cts->xport_specific.sata.valid & CTS_SATA_VALID_ATAPI)
2701203376Smav			d->atapi = cts->xport_specific.sata.atapi;
2702207499Smav		if (cts->xport_specific.sata.valid & CTS_SATA_VALID_CAPS)
2703207499Smav			d->caps = cts->xport_specific.sata.caps;
2704195534Sscottl		ccb->ccb_h.status = CAM_REQ_CMP;
2705195534Sscottl		break;
2706195534Sscottl	}
2707195534Sscottl	case XPT_GET_TRAN_SETTINGS:
2708195534Sscottl	/* Get default/user set transfer settings for the target */
2709195534Sscottl	{
2710195534Sscottl		struct	ccb_trans_settings *cts = &ccb->cts;
2711199747Smav		struct  ahci_device *d;
2712195534Sscottl		uint32_t status;
2713195534Sscottl
2714271261Smav		if (ahci_check_ids(ch, ccb))
2715207430Smav			return;
2716199747Smav		if (cts->type == CTS_TYPE_CURRENT_SETTINGS)
2717199747Smav			d = &ch->curr[ccb->ccb_h.target_id];
2718199747Smav		else
2719199747Smav			d = &ch->user[ccb->ccb_h.target_id];
2720236666Smav		cts->protocol = PROTO_UNSPECIFIED;
2721196656Smav		cts->protocol_version = PROTO_VERSION_UNSPECIFIED;
2722195534Sscottl		cts->transport = XPORT_SATA;
2723196656Smav		cts->transport_version = XPORT_VERSION_UNSPECIFIED;
2724195534Sscottl		cts->proto_specific.valid = 0;
2725195534Sscottl		cts->xport_specific.sata.valid = 0;
2726199747Smav		if (cts->type == CTS_TYPE_CURRENT_SETTINGS &&
2727199747Smav		    (ccb->ccb_h.target_id == 15 ||
2728199747Smav		    (ccb->ccb_h.target_id == 0 && !ch->pm_present))) {
2729195534Sscottl			status = ATA_INL(ch->r_mem, AHCI_P_SSTS) & ATA_SS_SPD_MASK;
2730199747Smav			if (status & 0x0f0) {
2731199747Smav				cts->xport_specific.sata.revision =
2732199747Smav				    (status & 0x0f0) >> 4;
2733199747Smav				cts->xport_specific.sata.valid |=
2734199747Smav				    CTS_SATA_VALID_REVISION;
2735199747Smav			}
2736207499Smav			cts->xport_specific.sata.caps = d->caps & CTS_SATA_CAPS_D;
2737207499Smav			if (ch->pm_level) {
2738207499Smav				if (ch->caps & (AHCI_CAP_PSC | AHCI_CAP_SSC))
2739207499Smav					cts->xport_specific.sata.caps |= CTS_SATA_CAPS_H_PMREQ;
2740207499Smav				if (ch->caps2 & AHCI_CAP2_APST)
2741207499Smav					cts->xport_specific.sata.caps |= CTS_SATA_CAPS_H_APST;
2742207499Smav			}
2743207499Smav			if ((ch->caps & AHCI_CAP_SNCQ) &&
2744207499Smav			    (ch->quirks & AHCI_Q_NOAA) == 0)
2745207499Smav				cts->xport_specific.sata.caps |= CTS_SATA_CAPS_H_DMAAA;
2746220602Smav			cts->xport_specific.sata.caps |= CTS_SATA_CAPS_H_AN;
2747207499Smav			cts->xport_specific.sata.caps &=
2748207499Smav			    ch->user[ccb->ccb_h.target_id].caps;
2749207499Smav			cts->xport_specific.sata.valid |= CTS_SATA_VALID_CAPS;
2750195534Sscottl		} else {
2751199747Smav			cts->xport_specific.sata.revision = d->revision;
2752199747Smav			cts->xport_specific.sata.valid |= CTS_SATA_VALID_REVISION;
2753207499Smav			cts->xport_specific.sata.caps = d->caps;
2754207499Smav			cts->xport_specific.sata.valid |= CTS_SATA_VALID_CAPS;
2755195534Sscottl		}
2756199747Smav		cts->xport_specific.sata.mode = d->mode;
2757199747Smav		cts->xport_specific.sata.valid |= CTS_SATA_VALID_MODE;
2758199747Smav		cts->xport_specific.sata.bytecount = d->bytecount;
2759199747Smav		cts->xport_specific.sata.valid |= CTS_SATA_VALID_BYTECOUNT;
2760199747Smav		cts->xport_specific.sata.pm_present = ch->pm_present;
2761195534Sscottl		cts->xport_specific.sata.valid |= CTS_SATA_VALID_PM;
2762199747Smav		cts->xport_specific.sata.tags = d->tags;
2763199747Smav		cts->xport_specific.sata.valid |= CTS_SATA_VALID_TAGS;
2764203376Smav		cts->xport_specific.sata.atapi = d->atapi;
2765203376Smav		cts->xport_specific.sata.valid |= CTS_SATA_VALID_ATAPI;
2766195534Sscottl		ccb->ccb_h.status = CAM_REQ_CMP;
2767195534Sscottl		break;
2768195534Sscottl	}
2769195534Sscottl	case XPT_RESET_BUS:		/* Reset the specified SCSI bus */
2770195534Sscottl	case XPT_RESET_DEV:	/* Bus Device Reset the specified SCSI device */
2771271261Smav		ahci_reset(ch);
2772195534Sscottl		ccb->ccb_h.status = CAM_REQ_CMP;
2773195534Sscottl		break;
2774195534Sscottl	case XPT_TERM_IO:		/* Terminate the I/O process */
2775195534Sscottl		/* XXX Implement */
2776195534Sscottl		ccb->ccb_h.status = CAM_REQ_INVALID;
2777195534Sscottl		break;
2778195534Sscottl	case XPT_PATH_INQ:		/* Path routing inquiry */
2779195534Sscottl	{
2780195534Sscottl		struct ccb_pathinq *cpi = &ccb->cpi;
2781195534Sscottl
2782195534Sscottl		cpi->version_num = 1; /* XXX??? */
2783199278Smav		cpi->hba_inquiry = PI_SDTR_ABLE;
2784199278Smav		if (ch->caps & AHCI_CAP_SNCQ)
2785199278Smav			cpi->hba_inquiry |= PI_TAG_ABLE;
2786195534Sscottl		if (ch->caps & AHCI_CAP_SPM)
2787195534Sscottl			cpi->hba_inquiry |= PI_SATAPM;
2788195534Sscottl		cpi->target_sprt = 0;
2789317673Smav		cpi->hba_misc = PIM_SEQSCAN | PIM_UNMAPPED;
2790317673Smav		if ((ch->quirks & AHCI_Q_NOAUX) == 0)
2791317673Smav			cpi->hba_misc |= PIM_ATA_EXT;
2792195534Sscottl		cpi->hba_eng_cnt = 0;
2793195534Sscottl		if (ch->caps & AHCI_CAP_SPM)
2794198322Smav			cpi->max_target = 15;
2795195534Sscottl		else
2796195534Sscottl			cpi->max_target = 0;
2797195534Sscottl		cpi->max_lun = 0;
2798195534Sscottl		cpi->initiator_id = 0;
2799195534Sscottl		cpi->bus_id = cam_sim_bus(sim);
2800195534Sscottl		cpi->base_transfer_speed = 150000;
2801315812Smav		strlcpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
2802315812Smav		strlcpy(cpi->hba_vid, "AHCI", HBA_IDLEN);
2803315812Smav		strlcpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
2804195534Sscottl		cpi->unit_number = cam_sim_unit(sim);
2805195534Sscottl		cpi->transport = XPORT_SATA;
2806196656Smav		cpi->transport_version = XPORT_VERSION_UNSPECIFIED;
2807236847Smav		cpi->protocol = PROTO_ATA;
2808196656Smav		cpi->protocol_version = PROTO_VERSION_UNSPECIFIED;
2809195534Sscottl		cpi->maxio = MAXPHYS;
2810196777Smav		/* ATI SB600 can't handle 256 sectors with FPDMA (NCQ). */
2811271146Simp		if (ch->quirks & AHCI_Q_MAXIO_64K)
2812196796Smav			cpi->maxio = min(cpi->maxio, 128 * 512);
2813271146Simp		cpi->hba_vendor = ch->vendorid;
2814271146Simp		cpi->hba_device = ch->deviceid;
2815271146Simp		cpi->hba_subvendor = ch->subvendorid;
2816271146Simp		cpi->hba_subdevice = ch->subdeviceid;
2817195534Sscottl		cpi->ccb_h.status = CAM_REQ_CMP;
2818195534Sscottl		break;
2819195534Sscottl	}
2820195534Sscottl	default:
2821195534Sscottl		ccb->ccb_h.status = CAM_REQ_INVALID;
2822195534Sscottl		break;
2823195534Sscottl	}
2824256843Smav	ahci_done(ch, ccb);
2825195534Sscottl}
2826195534Sscottl
2827195534Sscottlstatic void
2828195534Sscottlahcipoll(struct cam_sim *sim)
2829195534Sscottl{
2830195534Sscottl	struct ahci_channel *ch = (struct ahci_channel *)cam_sim_softc(sim);
2831256843Smav	uint32_t istatus;
2832195534Sscottl
2833256843Smav	/* Read interrupt statuses and process if any. */
2834256843Smav	istatus = ATA_INL(ch->r_mem, AHCI_P_IS);
2835256843Smav	if (istatus != 0)
2836256843Smav		ahci_ch_intr_main(ch, istatus);
2837220789Smav	if (ch->resetting != 0 &&
2838220789Smav	    (--ch->resetpolldiv <= 0 || !callout_pending(&ch->reset_timer))) {
2839220789Smav		ch->resetpolldiv = 1000;
2840271261Smav		ahci_reset_to(ch);
2841220789Smav	}
2842195534Sscottl}
2843331493Sian
2844331493Siandevclass_t ahci_devclass;
2845331493Sian
2846271146SimpMODULE_VERSION(ahci, 1);
2847271146SimpMODULE_DEPEND(ahci, cam, 1, 1, 1);
2848