blob: 811fc26bb643202806dac1e0d7edc26082f84ecc [file] [log] [blame]
yt1605232fcbc372006-12-23 23:16:13 -08001/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22/*
Xiao-Yu Zhangb22851f2010-06-04 15:30:45 +080023 * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
Joyce McIntoshd8873b32018-08-07 12:13:16 +030024 * Copyright 2018 Nexenta Systems, Inc. All rights reserved.
Andy Fiddaman44a84c12018-08-27 15:22:08 +000025 * Copyright 2018 OmniOS Community Edition (OmniOSce) Association.
yt1605232fcbc372006-12-23 23:16:13 -080026 */
27
yt1605232fcbc372006-12-23 23:16:13 -080028/*
29 * AHCI (Advanced Host Controller Interface) SATA HBA Driver
yt16052313bcbb72008-03-13 21:51:45 -070030 *
31 * Power Management Support
32 * ------------------------
33 *
34 * At the moment, the ahci driver only implements suspend/resume to
35 * support Suspend to RAM on X86 feature. Device power management isn't
36 * implemented, link power management is disabled, and hot plug isn't
37 * allowed during the period from suspend to resume.
38 *
39 * For s/r support, the ahci driver only need to implement DDI_SUSPEND
40 * and DDI_RESUME entries, and don't need to take care of new requests
41 * sent down after suspend because the target driver (sd) has already
42 * handled these conditions, and blocked these requests. For the detailed
43 * information, please check with sdopen, sdclose and sdioctl routines.
44 *
yt1605232fcbc372006-12-23 23:16:13 -080045 */
46
yt160523689d74b2008-07-28 21:02:33 -070047#include <sys/note.h>
yt1605232fcbc372006-12-23 23:16:13 -080048#include <sys/scsi/scsi.h>
49#include <sys/pci.h>
ying tian - Beijing Chinab2e36452008-09-17 12:12:16 +080050#include <sys/disp.h>
yt1605232fcbc372006-12-23 23:16:13 -080051#include <sys/sata/sata_hba.h>
52#include <sys/sata/adapters/ahci/ahcireg.h>
53#include <sys/sata/adapters/ahci/ahcivar.h>
54
55/*
Xiao-Yu Zhangb22851f2010-06-04 15:30:45 +080056 * FMA header files
57 */
58#include <sys/ddifm.h>
59#include <sys/fm/protocol.h>
60#include <sys/fm/util.h>
61#include <sys/fm/io/ddi.h>
62
63/*
Sherry Moore19397402008-09-22 16:30:26 -070064 * This is the string displayed by modinfo, etc.
Sherry Moore19397402008-09-22 16:30:26 -070065 */
66static char ahci_ident[] = "ahci driver";
67
68/*
yt1605232fcbc372006-12-23 23:16:13 -080069 * Function prototypes for driver entry points
70 */
71static int ahci_attach(dev_info_t *, ddi_attach_cmd_t);
72static int ahci_detach(dev_info_t *, ddi_detach_cmd_t);
73static int ahci_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
Sherry Moore19397402008-09-22 16:30:26 -070074static int ahci_quiesce(dev_info_t *);
yt1605232fcbc372006-12-23 23:16:13 -080075
76/*
77 * Function prototypes for SATA Framework interfaces
78 */
79static int ahci_register_sata_hba_tran(ahci_ctl_t *, uint32_t);
80static int ahci_unregister_sata_hba_tran(ahci_ctl_t *);
81
82static int ahci_tran_probe_port(dev_info_t *, sata_device_t *);
83static int ahci_tran_start(dev_info_t *, sata_pkt_t *spkt);
84static int ahci_tran_abort(dev_info_t *, sata_pkt_t *, int);
85static int ahci_tran_reset_dport(dev_info_t *, sata_device_t *);
86static int ahci_tran_hotplug_port_activate(dev_info_t *, sata_device_t *);
87static int ahci_tran_hotplug_port_deactivate(dev_info_t *, sata_device_t *);
88#if defined(__lock_lint)
89static int ahci_selftest(dev_info_t *, sata_device_t *);
90#endif
91
92/*
Xiao-Yu Zhangb22851f2010-06-04 15:30:45 +080093 * FMA Prototypes
94 */
95static void ahci_fm_init(ahci_ctl_t *);
96static void ahci_fm_fini(ahci_ctl_t *);
97static int ahci_fm_error_cb(dev_info_t *, ddi_fm_error_t *, const void*);
98int ahci_check_acc_handle(ddi_acc_handle_t);
99int ahci_check_dma_handle(ddi_dma_handle_t);
100void ahci_fm_ereport(ahci_ctl_t *, char *);
101static int ahci_check_all_handle(ahci_ctl_t *);
102static int ahci_check_ctl_handle(ahci_ctl_t *);
103static int ahci_check_port_handle(ahci_ctl_t *, int);
104static int ahci_check_slot_handle(ahci_port_t *, int);
105
106/*
yt1605232fcbc372006-12-23 23:16:13 -0800107 * Local function prototypes
108 */
Marcel Telka2ac30282013-06-08 23:24:29 +0200109static int ahci_setup_port_base_addresses(ahci_ctl_t *, ahci_port_t *);
yt16052368d33a22007-08-16 18:51:39 -0700110static int ahci_alloc_ports_state(ahci_ctl_t *);
111static void ahci_dealloc_ports_state(ahci_ctl_t *);
yt1605232fcbc372006-12-23 23:16:13 -0800112static int ahci_alloc_port_state(ahci_ctl_t *, uint8_t);
113static void ahci_dealloc_port_state(ahci_ctl_t *, uint8_t);
Marcel Telka2ac30282013-06-08 23:24:29 +0200114static int ahci_alloc_rcvd_fis(ahci_ctl_t *, ahci_port_t *);
yt160523689d74b2008-07-28 21:02:33 -0700115static void ahci_dealloc_rcvd_fis(ahci_port_t *);
Marcel Telka2ac30282013-06-08 23:24:29 +0200116static int ahci_alloc_cmd_list(ahci_ctl_t *, ahci_port_t *);
yt1605232fcbc372006-12-23 23:16:13 -0800117static void ahci_dealloc_cmd_list(ahci_ctl_t *, ahci_port_t *);
118static int ahci_alloc_cmd_tables(ahci_ctl_t *, ahci_port_t *);
119static void ahci_dealloc_cmd_tables(ahci_ctl_t *, ahci_port_t *);
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +0800120static void ahci_alloc_pmult(ahci_ctl_t *, ahci_port_t *);
121static void ahci_dealloc_pmult(ahci_ctl_t *, ahci_port_t *);
yt1605232fcbc372006-12-23 23:16:13 -0800122
yt16052368d33a22007-08-16 18:51:39 -0700123static int ahci_initialize_controller(ahci_ctl_t *);
124static void ahci_uninitialize_controller(ahci_ctl_t *);
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +0800125static int ahci_initialize_port(ahci_ctl_t *, ahci_port_t *, ahci_addr_t *);
yt16052313bcbb72008-03-13 21:51:45 -0700126static int ahci_config_space_init(ahci_ctl_t *);
Marcel Telka2ac30282013-06-08 23:24:29 +0200127static void ahci_staggered_spin_up(ahci_ctl_t *, uint8_t);
yt16052368d33a22007-08-16 18:51:39 -0700128
ying tian - Beijing Chinaf8a673a2008-12-09 11:24:13 +0800129static void ahci_drain_ports_taskq(ahci_ctl_t *);
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +0800130static int ahci_rdwr_pmult(ahci_ctl_t *, ahci_addr_t *, uint8_t, uint32_t *,
131 uint8_t);
132static int ahci_read_pmult(ahci_ctl_t *, ahci_addr_t *, uint8_t, uint32_t *);
133static int ahci_write_pmult(ahci_ctl_t *, ahci_addr_t *, uint8_t, uint32_t);
134static int ahci_update_pmult_pscr(ahci_ctl_t *, ahci_addr_t *,
135 sata_device_t *);
136static int ahci_update_pmult_gscr(ahci_ctl_t *, ahci_addr_t *,
Xiao-Yu Zhang918304a2009-09-28 14:30:40 +0800137 sata_pmult_gscr_t *);
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +0800138static int ahci_initialize_pmult(ahci_ctl_t *, ahci_port_t *, ahci_addr_t *,
139 sata_device_t *);
140static int ahci_initialize_pmport(ahci_ctl_t *, ahci_port_t *, ahci_addr_t *);
141static int ahci_probe_pmult(ahci_ctl_t *, ahci_port_t *, ahci_addr_t *);
142static int ahci_probe_pmport(ahci_ctl_t *, ahci_port_t *, ahci_addr_t *,
143 sata_device_t *);
144
yt16052313bcbb72008-03-13 21:51:45 -0700145static void ahci_disable_interface_pm(ahci_ctl_t *, uint8_t);
yt16052368d33a22007-08-16 18:51:39 -0700146static int ahci_start_port(ahci_ctl_t *, ahci_port_t *, uint8_t);
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +0800147static void ahci_find_dev_signature(ahci_ctl_t *, ahci_port_t *,
148 ahci_addr_t *);
yt1605232fcbc372006-12-23 23:16:13 -0800149static void ahci_update_sata_registers(ahci_ctl_t *, uint8_t, sata_device_t *);
150static int ahci_deliver_satapkt(ahci_ctl_t *, ahci_port_t *,
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +0800151 ahci_addr_t *, sata_pkt_t *);
yt16052368d33a22007-08-16 18:51:39 -0700152static int ahci_do_sync_start(ahci_ctl_t *, ahci_port_t *,
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +0800153 ahci_addr_t *, sata_pkt_t *);
154static int ahci_claim_free_slot(ahci_ctl_t *, ahci_port_t *,
155 ahci_addr_t *, int);
yt16052368d33a22007-08-16 18:51:39 -0700156static void ahci_copy_err_cnxt(sata_cmd_t *, ahci_fis_d2h_register_t *);
yt16052382263d522007-10-10 19:54:28 -0700157static void ahci_copy_ncq_err_page(sata_cmd_t *,
158 struct sata_ncq_error_recovery_page *);
yt1605232fcbc372006-12-23 23:16:13 -0800159static void ahci_copy_out_regs(sata_cmd_t *, ahci_fis_d2h_register_t *);
ying tian - Beijing China6b62a232010-06-11 10:44:25 +0800160static void ahci_add_doneq(ahci_port_t *, sata_pkt_t *, int);
161static void ahci_flush_doneq(ahci_port_t *);
yt1605232fcbc372006-12-23 23:16:13 -0800162
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +0800163static int ahci_software_reset(ahci_ctl_t *, ahci_port_t *, ahci_addr_t *);
yt1605232fcbc372006-12-23 23:16:13 -0800164static int ahci_hba_reset(ahci_ctl_t *);
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +0800165static int ahci_port_reset(ahci_ctl_t *, ahci_port_t *, ahci_addr_t *);
166static int ahci_pmport_reset(ahci_ctl_t *, ahci_port_t *, ahci_addr_t *);
yt1605232fcbc372006-12-23 23:16:13 -0800167static void ahci_reject_all_abort_pkts(ahci_ctl_t *, ahci_port_t *, uint8_t);
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +0800168static int ahci_reset_device_reject_pkts(ahci_ctl_t *, ahci_port_t *,
169 ahci_addr_t *);
170static int ahci_reset_pmdevice_reject_pkts(ahci_ctl_t *, ahci_port_t *,
171 ahci_addr_t *);
172static int ahci_reset_port_reject_pkts(ahci_ctl_t *, ahci_port_t *,
173 ahci_addr_t *);
yt1605232fcbc372006-12-23 23:16:13 -0800174static int ahci_reset_hba_reject_pkts(ahci_ctl_t *);
yt16052368d33a22007-08-16 18:51:39 -0700175static int ahci_put_port_into_notrunning_state(ahci_ctl_t *, ahci_port_t *,
yt1605232fcbc372006-12-23 23:16:13 -0800176 uint8_t);
177static int ahci_restart_port_wait_till_ready(ahci_ctl_t *, ahci_port_t *,
yt16052368d33a22007-08-16 18:51:39 -0700178 uint8_t, int, int *);
yt160523689d74b2008-07-28 21:02:33 -0700179static void ahci_mop_commands(ahci_ctl_t *, ahci_port_t *, uint32_t,
180 uint32_t, uint32_t, uint32_t, uint32_t);
yt16052382263d522007-10-10 19:54:28 -0700181static uint32_t ahci_get_rdlogext_data(ahci_ctl_t *, ahci_port_t *, uint8_t);
yt16052368d33a22007-08-16 18:51:39 -0700182static void ahci_get_rqsense_data(ahci_ctl_t *, ahci_port_t *,
183 uint8_t, sata_pkt_t *);
184static void ahci_fatal_error_recovery_handler(ahci_ctl_t *, ahci_port_t *,
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +0800185 ahci_addr_t *, uint32_t);
186static void ahci_pmult_error_recovery_handler(ahci_ctl_t *, ahci_port_t *,
yt16052382263d522007-10-10 19:54:28 -0700187 uint8_t, uint32_t);
yt16052368d33a22007-08-16 18:51:39 -0700188static void ahci_timeout_pkts(ahci_ctl_t *, ahci_port_t *,
yt16052382263d522007-10-10 19:54:28 -0700189 uint8_t, uint32_t);
yt16052368d33a22007-08-16 18:51:39 -0700190static void ahci_events_handler(void *);
yt1605232fcbc372006-12-23 23:16:13 -0800191static void ahci_watchdog_handler(ahci_ctl_t *);
192
193static uint_t ahci_intr(caddr_t, caddr_t);
yt16052382263d522007-10-10 19:54:28 -0700194static void ahci_port_intr(ahci_ctl_t *, ahci_port_t *, uint8_t);
ying tian - Beijing China2c742e12009-02-06 10:25:09 +0800195static int ahci_add_intrs(ahci_ctl_t *, int);
yt1605232fcbc372006-12-23 23:16:13 -0800196static void ahci_rem_intrs(ahci_ctl_t *);
197static void ahci_enable_all_intrs(ahci_ctl_t *);
198static void ahci_disable_all_intrs(ahci_ctl_t *);
yt160523689d74b2008-07-28 21:02:33 -0700199static void ahci_enable_port_intrs(ahci_ctl_t *, uint8_t);
200static void ahci_disable_port_intrs(ahci_ctl_t *, uint8_t);
yt1605232fcbc372006-12-23 23:16:13 -0800201
yt160523689d74b2008-07-28 21:02:33 -0700202static int ahci_intr_cmd_cmplt(ahci_ctl_t *, ahci_port_t *, uint8_t);
yt16052368d33a22007-08-16 18:51:39 -0700203static int ahci_intr_set_device_bits(ahci_ctl_t *, ahci_port_t *, uint8_t);
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +0800204static int ahci_intr_ncq_events(ahci_ctl_t *, ahci_port_t *, ahci_addr_t *);
205static int ahci_intr_pmult_sntf_events(ahci_ctl_t *, ahci_port_t *, uint8_t);
yt1605232fcbc372006-12-23 23:16:13 -0800206static int ahci_intr_port_connect_change(ahci_ctl_t *, ahci_port_t *, uint8_t);
207static int ahci_intr_device_mechanical_presence_status(ahci_ctl_t *,
208 ahci_port_t *, uint8_t);
209static int ahci_intr_phyrdy_change(ahci_ctl_t *, ahci_port_t *, uint8_t);
yt16052368d33a22007-08-16 18:51:39 -0700210static int ahci_intr_non_fatal_error(ahci_ctl_t *, ahci_port_t *,
211 uint8_t, uint32_t);
212static int ahci_intr_fatal_error(ahci_ctl_t *, ahci_port_t *,
yt16052382263d522007-10-10 19:54:28 -0700213 uint8_t, uint32_t);
yt1605232fcbc372006-12-23 23:16:13 -0800214static int ahci_intr_cold_port_detect(ahci_ctl_t *, ahci_port_t *, uint8_t);
215
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +0800216static void ahci_get_ahci_addr(ahci_ctl_t *, sata_device_t *, ahci_addr_t *);
yt1605232fcbc372006-12-23 23:16:13 -0800217static int ahci_get_num_implemented_ports(uint32_t);
ying tian - Beijing China3f022902010-07-01 11:13:23 +0800218static void ahci_log_fatal_error_message(ahci_ctl_t *, uint8_t, uint32_t);
219static void ahci_dump_commands(ahci_ctl_t *, uint8_t, uint32_t);
yt160523a9440e82008-06-11 22:25:05 -0700220static void ahci_log_serror_message(ahci_ctl_t *, uint8_t, uint32_t, int);
yt160523689d74b2008-07-28 21:02:33 -0700221#if AHCI_DEBUG
yt1605232fcbc372006-12-23 23:16:13 -0800222static void ahci_log(ahci_ctl_t *, uint_t, char *, ...);
yt160523689d74b2008-07-28 21:02:33 -0700223#endif
yt1605232fcbc372006-12-23 23:16:13 -0800224
225
226/*
227 * DMA attributes for the data buffer
228 *
229 * dma_attr_addr_hi will be changed to 0xffffffffull if the HBA
230 * does not support 64-bit addressing
231 */
232static ddi_dma_attr_t buffer_dma_attr = {
233 DMA_ATTR_V0, /* dma_attr_version */
yt16052368d33a22007-08-16 18:51:39 -0700234 0x0ull, /* dma_attr_addr_lo: lowest bus address */
yt1605232fcbc372006-12-23 23:16:13 -0800235 0xffffffffffffffffull, /* dma_attr_addr_hi: highest bus address */
236 0x3fffffull, /* dma_attr_count_max i.e. for one cookie */
yt16052368d33a22007-08-16 18:51:39 -0700237 0x2ull, /* dma_attr_align: word aligned */
yt1605232fcbc372006-12-23 23:16:13 -0800238 1, /* dma_attr_burstsizes */
239 1, /* dma_attr_minxfer */
240 0xffffffffull, /* dma_attr_maxxfer i.e. includes all cookies */
241 0xffffffffull, /* dma_attr_seg */
242 AHCI_PRDT_NUMBER, /* dma_attr_sgllen */
243 512, /* dma_attr_granular */
244 0, /* dma_attr_flags */
245};
246
247/*
248 * DMA attributes for the rcvd FIS
249 *
250 * dma_attr_addr_hi will be changed to 0xffffffffull if the HBA
251 * does not support 64-bit addressing
252 */
253static ddi_dma_attr_t rcvd_fis_dma_attr = {
254 DMA_ATTR_V0, /* dma_attr_version */
yt16052368d33a22007-08-16 18:51:39 -0700255 0x0ull, /* dma_attr_addr_lo: lowest bus address */
yt1605232fcbc372006-12-23 23:16:13 -0800256 0xffffffffffffffffull, /* dma_attr_addr_hi: highest bus address */
257 0xffffffffull, /* dma_attr_count_max i.e. for one cookie */
yt16052368d33a22007-08-16 18:51:39 -0700258 0x100ull, /* dma_attr_align: 256-byte aligned */
yt1605232fcbc372006-12-23 23:16:13 -0800259 1, /* dma_attr_burstsizes */
260 1, /* dma_attr_minxfer */
261 0xffffffffull, /* dma_attr_maxxfer i.e. includes all cookies */
262 0xffffffffull, /* dma_attr_seg */
263 1, /* dma_attr_sgllen */
264 1, /* dma_attr_granular */
265 0, /* dma_attr_flags */
266};
267
268/*
269 * DMA attributes for the command list
270 *
271 * dma_attr_addr_hi will be changed to 0xffffffffull if the HBA
272 * does not support 64-bit addressing
273 */
274static ddi_dma_attr_t cmd_list_dma_attr = {
275 DMA_ATTR_V0, /* dma_attr_version */
yt16052368d33a22007-08-16 18:51:39 -0700276 0x0ull, /* dma_attr_addr_lo: lowest bus address */
yt1605232fcbc372006-12-23 23:16:13 -0800277 0xffffffffffffffffull, /* dma_attr_addr_hi: highest bus address */
278 0xffffffffull, /* dma_attr_count_max i.e. for one cookie */
yt16052368d33a22007-08-16 18:51:39 -0700279 0x400ull, /* dma_attr_align: 1K-byte aligned */
yt1605232fcbc372006-12-23 23:16:13 -0800280 1, /* dma_attr_burstsizes */
281 1, /* dma_attr_minxfer */
282 0xffffffffull, /* dma_attr_maxxfer i.e. includes all cookies */
283 0xffffffffull, /* dma_attr_seg */
284 1, /* dma_attr_sgllen */
285 1, /* dma_attr_granular */
286 0, /* dma_attr_flags */
287};
288
289/*
290 * DMA attributes for cmd tables
291 *
292 * dma_attr_addr_hi will be changed to 0xffffffffull if the HBA
293 * does not support 64-bit addressing
294 */
295static ddi_dma_attr_t cmd_table_dma_attr = {
296 DMA_ATTR_V0, /* dma_attr_version */
yt16052368d33a22007-08-16 18:51:39 -0700297 0x0ull, /* dma_attr_addr_lo: lowest bus address */
yt1605232fcbc372006-12-23 23:16:13 -0800298 0xffffffffffffffffull, /* dma_attr_addr_hi: highest bus address */
299 0xffffffffull, /* dma_attr_count_max i.e. for one cookie */
yt16052368d33a22007-08-16 18:51:39 -0700300 0x80ull, /* dma_attr_align: 128-byte aligned */
yt1605232fcbc372006-12-23 23:16:13 -0800301 1, /* dma_attr_burstsizes */
302 1, /* dma_attr_minxfer */
303 0xffffffffull, /* dma_attr_maxxfer i.e. includes all cookies */
304 0xffffffffull, /* dma_attr_seg */
305 1, /* dma_attr_sgllen */
306 1, /* dma_attr_granular */
307 0, /* dma_attr_flags */
308};
309
310
311/* Device access attributes */
312static ddi_device_acc_attr_t accattr = {
Xiao-Yu Zhangb22851f2010-06-04 15:30:45 +0800313 DDI_DEVICE_ATTR_V1,
yt1605232fcbc372006-12-23 23:16:13 -0800314 DDI_STRUCTURE_LE_ACC,
Xiao-Yu Zhangb22851f2010-06-04 15:30:45 +0800315 DDI_STRICTORDER_ACC,
316 DDI_DEFAULT_ACC
yt1605232fcbc372006-12-23 23:16:13 -0800317};
318
319
320static struct dev_ops ahcictl_dev_ops = {
321 DEVO_REV, /* devo_rev */
322 0, /* refcnt */
323 ahci_getinfo, /* info */
324 nulldev, /* identify */
325 nulldev, /* probe */
326 ahci_attach, /* attach */
327 ahci_detach, /* detach */
328 nodev, /* no reset */
329 (struct cb_ops *)0, /* driver operations */
330 NULL, /* bus operations */
Sherry Moore19397402008-09-22 16:30:26 -0700331 NULL, /* power */
332 ahci_quiesce, /* quiesce */
yt1605232fcbc372006-12-23 23:16:13 -0800333};
334
335static sata_tran_hotplug_ops_t ahci_tran_hotplug_ops = {
336 SATA_TRAN_HOTPLUG_OPS_REV_1,
337 ahci_tran_hotplug_port_activate,
338 ahci_tran_hotplug_port_deactivate
339};
340
341extern struct mod_ops mod_driverops;
342
343static struct modldrv modldrv = {
344 &mod_driverops, /* driverops */
Sherry Moore19397402008-09-22 16:30:26 -0700345 ahci_ident, /* short description */
yt1605232fcbc372006-12-23 23:16:13 -0800346 &ahcictl_dev_ops, /* driver ops */
347};
348
349static struct modlinkage modlinkage = {
350 MODREV_1,
351 &modldrv,
352 NULL
353};
354
ying tian - Beijing Chinadb2cce02008-11-14 12:04:32 +0800355/* The following variables are watchdog handler related */
ying tian - Beijing China6b62a232010-06-11 10:44:25 +0800356static clock_t ahci_watchdog_timeout = 5; /* 5 seconds */
357static clock_t ahci_watchdog_tick;
yt1605232fcbc372006-12-23 23:16:13 -0800358
ying tian - Beijing Chinadb2cce02008-11-14 12:04:32 +0800359/*
360 * This static variable indicates the size of command table,
361 * and it's changeable with prdt number, which ahci_dma_prdt_number
362 * indicates.
363 */
yt1605232fcbc372006-12-23 23:16:13 -0800364static size_t ahci_cmd_table_size;
365
ying tian - Beijing Chinadb2cce02008-11-14 12:04:32 +0800366/*
ying tian - Beijing China259105b2009-05-22 12:06:06 +0800367 * The below global variables are tunable via /etc/system
368 *
369 * ahci_dma_prdt_number
370 * ahci_msi_enabled
371 * ahci_buf_64bit_dma
372 * ahci_commu_64bit_dma
ying tian - Beijing Chinadb2cce02008-11-14 12:04:32 +0800373 */
374
yt1605232fcbc372006-12-23 23:16:13 -0800375/* The number of Physical Region Descriptor Table(PRDT) in Command Table */
376int ahci_dma_prdt_number = AHCI_PRDT_NUMBER;
377
ying tian - Beijing Chinadb2cce02008-11-14 12:04:32 +0800378/* AHCI MSI is tunable */
ying tian - Beijing China2c742e12009-02-06 10:25:09 +0800379boolean_t ahci_msi_enabled = B_TRUE;
yt1605232fcbc372006-12-23 23:16:13 -0800380
ying tian - Beijing China259105b2009-05-22 12:06:06 +0800381/*
382 * 64-bit dma addressing for data buffer is tunable
383 *
384 * The variable controls only the below value:
385 * DBAU (upper 32-bits physical address of data block)
386 */
387boolean_t ahci_buf_64bit_dma = B_TRUE;
388
389/*
390 * 64-bit dma addressing for communication system descriptors is tunable
391 *
392 * The variable controls the below three values:
393 *
394 * PxCLBU (upper 32-bits for the command list base physical address)
395 * PxFBU (upper 32-bits for the received FIS base physical address)
396 * CTBAU (upper 32-bits of command table base)
397 */
398boolean_t ahci_commu_64bit_dma = B_TRUE;
399
400/*
ying tian - Beijing China17ac46b2009-10-27 10:21:22 +0800401 * By default, 64-bit dma for data buffer will be disabled for AMD/ATI SB600
402 * chipset. If the users want to have a try with 64-bit dma, please change
403 * the below variable value to enable it.
404 */
405boolean_t sb600_buf_64bit_dma_disable = B_TRUE;
406
407/*
408 * By default, 64-bit dma for command buffer will be disabled for AMD/ATI
409 * SB600/700/710/750/800. If the users want to have a try with 64-bit dma,
410 * please change the below value to enable it.
411 */
412boolean_t sbxxx_commu_64bit_dma_disable = B_TRUE;
413
414
415/*
ying tian - Beijing China259105b2009-05-22 12:06:06 +0800416 * End of global tunable variable definition
417 */
ying tian - Beijing Chinadb2cce02008-11-14 12:04:32 +0800418
Fred Herard1fdcc912009-07-20 18:43:26 -0400419#if AHCI_DEBUG
420uint32_t ahci_debug_flags = 0;
421#else
Fred Herardf5f2d262009-07-14 16:27:17 -0400422uint32_t ahci_debug_flags = (AHCIDBG_ERRS|AHCIDBG_TIMEOUT);
Fred Herard1fdcc912009-07-20 18:43:26 -0400423#endif
424
yt160523689d74b2008-07-28 21:02:33 -0700425
Fred Herardf5f2d262009-07-14 16:27:17 -0400426#if AHCI_DEBUG
yt160523689d74b2008-07-28 21:02:33 -0700427/* The following is needed for ahci_log() */
428static kmutex_t ahci_log_mutex;
429static char ahci_log_buf[512];
yt1605232fcbc372006-12-23 23:16:13 -0800430#endif
431
432/* Opaque state pointer initialized by ddi_soft_state_init() */
433static void *ahci_statep = NULL;
434
435/*
436 * ahci module initialization.
437 */
438int
439_init(void)
440{
441 int ret;
442
443 ret = ddi_soft_state_init(&ahci_statep, sizeof (ahci_ctl_t), 0);
444 if (ret != 0) {
445 goto err_out;
446 }
447
yt160523689d74b2008-07-28 21:02:33 -0700448#if AHCI_DEBUG
yt1605232fcbc372006-12-23 23:16:13 -0800449 mutex_init(&ahci_log_mutex, NULL, MUTEX_DRIVER, NULL);
yt160523689d74b2008-07-28 21:02:33 -0700450#endif
yt1605232fcbc372006-12-23 23:16:13 -0800451
452 if ((ret = sata_hba_init(&modlinkage)) != 0) {
yt160523689d74b2008-07-28 21:02:33 -0700453#if AHCI_DEBUG
yt1605232fcbc372006-12-23 23:16:13 -0800454 mutex_destroy(&ahci_log_mutex);
yt160523689d74b2008-07-28 21:02:33 -0700455#endif
yt1605232fcbc372006-12-23 23:16:13 -0800456 ddi_soft_state_fini(&ahci_statep);
457 goto err_out;
458 }
459
Marcel Telka2ac30282013-06-08 23:24:29 +0200460 /* watchdog tick */
461 ahci_watchdog_tick = drv_usectohz(
462 (clock_t)ahci_watchdog_timeout * 1000000);
463
yt1605232fcbc372006-12-23 23:16:13 -0800464 ret = mod_install(&modlinkage);
465 if (ret != 0) {
466 sata_hba_fini(&modlinkage);
yt160523689d74b2008-07-28 21:02:33 -0700467#if AHCI_DEBUG
yt1605232fcbc372006-12-23 23:16:13 -0800468 mutex_destroy(&ahci_log_mutex);
yt160523689d74b2008-07-28 21:02:33 -0700469#endif
yt1605232fcbc372006-12-23 23:16:13 -0800470 ddi_soft_state_fini(&ahci_statep);
471 goto err_out;
472 }
473
yt1605232fcbc372006-12-23 23:16:13 -0800474 return (ret);
475
476err_out:
yt160523a9440e82008-06-11 22:25:05 -0700477 cmn_err(CE_WARN, "!ahci: Module init failed");
yt1605232fcbc372006-12-23 23:16:13 -0800478 return (ret);
479}
480
481/*
482 * ahci module uninitialize.
483 */
484int
485_fini(void)
486{
487 int ret;
488
489 ret = mod_remove(&modlinkage);
490 if (ret != 0) {
491 return (ret);
492 }
493
494 /* Remove the resources allocated in _init(). */
495 sata_hba_fini(&modlinkage);
yt160523689d74b2008-07-28 21:02:33 -0700496#if AHCI_DEBUG
yt1605232fcbc372006-12-23 23:16:13 -0800497 mutex_destroy(&ahci_log_mutex);
yt160523689d74b2008-07-28 21:02:33 -0700498#endif
yt1605232fcbc372006-12-23 23:16:13 -0800499 ddi_soft_state_fini(&ahci_statep);
500
501 return (ret);
502}
503
504/*
505 * _info entry point
506 */
507int
508_info(struct modinfo *modinfop)
509{
510 return (mod_info(&modlinkage, modinfop));
511}
512
513/*
514 * The attach entry point for dev_ops.
515 */
516static int
517ahci_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
518{
Fred Herardf5f2d262009-07-14 16:27:17 -0400519 ahci_ctl_t *ahci_ctlp = NULL;
yt1605232fcbc372006-12-23 23:16:13 -0800520 int instance = ddi_get_instance(dip);
521 int status;
522 int attach_state;
523 uint32_t cap_status, ahci_version;
Marcel Telka2ac30282013-06-08 23:24:29 +0200524 uint32_t ghc_control;
yt1605232fcbc372006-12-23 23:16:13 -0800525 int intr_types;
yt16052368d33a22007-08-16 18:51:39 -0700526 int i;
yt16052395c11c12008-01-22 18:56:00 -0800527 pci_regspec_t *regs;
528 int regs_length;
529 int rnumber;
yt16052368d33a22007-08-16 18:51:39 -0700530#if AHCI_DEBUG
531 int speed;
532#endif
yt1605232fcbc372006-12-23 23:16:13 -0800533
Fred Herardf5f2d262009-07-14 16:27:17 -0400534 AHCIDBG(AHCIDBG_INIT|AHCIDBG_ENTRY, ahci_ctlp, "ahci_attach enter",
535 NULL);
yt1605232fcbc372006-12-23 23:16:13 -0800536
537 switch (cmd) {
538 case DDI_ATTACH:
539 break;
540
541 case DDI_RESUME:
yt16052313bcbb72008-03-13 21:51:45 -0700542
543 /*
544 * During DDI_RESUME, the hardware state of the device
545 * (power may have been removed from the device) must be
546 * restored, allow pending requests to continue, and
547 * service new requests.
548 */
549 ahci_ctlp = ddi_get_soft_state(ahci_statep, instance);
550 mutex_enter(&ahci_ctlp->ahcictl_mutex);
551
Marcel Telka2ac30282013-06-08 23:24:29 +0200552 /*
553 * GHC.AE must be set to 1 before any other AHCI register
554 * is accessed
555 */
556 ghc_control = ddi_get32(ahci_ctlp->ahcictl_ahci_acc_handle,
557 (uint32_t *)AHCI_GLOBAL_GHC(ahci_ctlp));
558 ghc_control |= AHCI_HBA_GHC_AE;
559 ddi_put32(ahci_ctlp->ahcictl_ahci_acc_handle,
560 (uint32_t *)AHCI_GLOBAL_GHC(ahci_ctlp), ghc_control);
561
yt16052313bcbb72008-03-13 21:51:45 -0700562 /* Restart watch thread */
563 if (ahci_ctlp->ahcictl_timeout_id == 0)
564 ahci_ctlp->ahcictl_timeout_id = timeout(
565 (void (*)(void *))ahci_watchdog_handler,
566 (caddr_t)ahci_ctlp, ahci_watchdog_tick);
567
568 mutex_exit(&ahci_ctlp->ahcictl_mutex);
569
570 /*
571 * Re-initialize the controller and enable the interrupts and
572 * restart all the ports.
573 *
574 * Note that so far we don't support hot-plug during
575 * suspend/resume.
576 */
577 if (ahci_initialize_controller(ahci_ctlp) != AHCI_SUCCESS) {
Fred Herardf5f2d262009-07-14 16:27:17 -0400578 AHCIDBG(AHCIDBG_ERRS|AHCIDBG_PM, ahci_ctlp,
yt160523a9440e82008-06-11 22:25:05 -0700579 "Failed to initialize the controller "
Fred Herardf5f2d262009-07-14 16:27:17 -0400580 "during DDI_RESUME", NULL);
yt16052313bcbb72008-03-13 21:51:45 -0700581 return (DDI_FAILURE);
582 }
583
584 mutex_enter(&ahci_ctlp->ahcictl_mutex);
Marcel Telka265b5a42013-07-01 22:48:16 +0200585 ahci_ctlp->ahcictl_flags &= ~AHCI_SUSPEND;
yt16052313bcbb72008-03-13 21:51:45 -0700586 mutex_exit(&ahci_ctlp->ahcictl_mutex);
587
588 return (DDI_SUCCESS);
yt1605232fcbc372006-12-23 23:16:13 -0800589
590 default:
591 return (DDI_FAILURE);
592 }
593
yt1605232fcbc372006-12-23 23:16:13 -0800594 attach_state = AHCI_ATTACH_STATE_NONE;
595
596 /* Allocate soft state */
597 status = ddi_soft_state_zalloc(ahci_statep, instance);
598 if (status != DDI_SUCCESS) {
yt160523a9440e82008-06-11 22:25:05 -0700599 cmn_err(CE_WARN, "!ahci%d: Cannot allocate soft state",
600 instance);
yt1605232fcbc372006-12-23 23:16:13 -0800601 goto err_out;
602 }
603
604 ahci_ctlp = ddi_get_soft_state(ahci_statep, instance);
yt16052313bcbb72008-03-13 21:51:45 -0700605 ahci_ctlp->ahcictl_flags |= AHCI_ATTACH;
yt1605232fcbc372006-12-23 23:16:13 -0800606 ahci_ctlp->ahcictl_dip = dip;
607
yt16052368d33a22007-08-16 18:51:39 -0700608 /* Initialize the cport/port mapping */
609 for (i = 0; i < AHCI_MAX_PORTS; i++) {
610 ahci_ctlp->ahcictl_port_to_cport[i] = 0xff;
611 ahci_ctlp->ahcictl_cport_to_port[i] = 0xff;
612 }
613
yt1605232fcbc372006-12-23 23:16:13 -0800614 attach_state |= AHCI_ATTACH_STATE_STATEP_ALLOC;
615
Xiao-Yu Zhangb22851f2010-06-04 15:30:45 +0800616 /* Initialize FMA properties */
617 ahci_fm_init(ahci_ctlp);
618
619 attach_state |= AHCI_ATTACH_STATE_FMA;
620
yt1605232fcbc372006-12-23 23:16:13 -0800621 /*
622 * Now map the AHCI base address; which includes global
623 * registers and port control registers
yt16052395c11c12008-01-22 18:56:00 -0800624 *
625 * According to the spec, the AHCI Base Address is BAR5,
yt16052313bcbb72008-03-13 21:51:45 -0700626 * but BAR0-BAR4 are optional, so we need to check which
627 * rnumber is used for BAR5.
yt1605232fcbc372006-12-23 23:16:13 -0800628 */
yt16052395c11c12008-01-22 18:56:00 -0800629
630 /*
631 * search through DDI "reg" property for the AHCI register set
632 */
633 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip,
634 DDI_PROP_DONTPASS, "reg", (int **)&regs,
635 (uint_t *)&regs_length) != DDI_PROP_SUCCESS) {
yt160523a9440e82008-06-11 22:25:05 -0700636 cmn_err(CE_WARN, "!ahci%d: Cannot lookup reg property",
637 instance);
yt16052395c11c12008-01-22 18:56:00 -0800638 goto err_out;
639 }
640
641 /* AHCI Base Address is located at 0x24 offset */
642 for (rnumber = 0; rnumber < regs_length; ++rnumber) {
643 if ((regs[rnumber].pci_phys_hi & PCI_REG_REG_M)
644 == AHCI_PCI_RNUM)
645 break;
646 }
647
648 ddi_prop_free(regs);
649
650 if (rnumber == regs_length) {
yt160523a9440e82008-06-11 22:25:05 -0700651 cmn_err(CE_WARN, "!ahci%d: Cannot find AHCI register set",
652 instance);
yt16052395c11c12008-01-22 18:56:00 -0800653 goto err_out;
654 }
655
Fred Herardf5f2d262009-07-14 16:27:17 -0400656 AHCIDBG(AHCIDBG_INIT, ahci_ctlp, "rnumber = %d", rnumber);
yt16052395c11c12008-01-22 18:56:00 -0800657
yt1605232fcbc372006-12-23 23:16:13 -0800658 status = ddi_regs_map_setup(dip,
yt16052395c11c12008-01-22 18:56:00 -0800659 rnumber,
yt1605232fcbc372006-12-23 23:16:13 -0800660 (caddr_t *)&ahci_ctlp->ahcictl_ahci_addr,
661 0,
662 0,
663 &accattr,
664 &ahci_ctlp->ahcictl_ahci_acc_handle);
665 if (status != DDI_SUCCESS) {
yt160523a9440e82008-06-11 22:25:05 -0700666 cmn_err(CE_WARN, "!ahci%d: Cannot map register space",
667 instance);
yt1605232fcbc372006-12-23 23:16:13 -0800668 goto err_out;
669 }
670
671 attach_state |= AHCI_ATTACH_STATE_REG_MAP;
672
Marcel Telka2ac30282013-06-08 23:24:29 +0200673 /*
674 * GHC.AE must be set to 1 before any other AHCI register
675 * is accessed
676 */
677 ghc_control = ddi_get32(ahci_ctlp->ahcictl_ahci_acc_handle,
678 (uint32_t *)AHCI_GLOBAL_GHC(ahci_ctlp));
679 ghc_control |= AHCI_HBA_GHC_AE;
680 ddi_put32(ahci_ctlp->ahcictl_ahci_acc_handle,
681 (uint32_t *)AHCI_GLOBAL_GHC(ahci_ctlp), ghc_control);
682
yt1605232fcbc372006-12-23 23:16:13 -0800683 /* Get the AHCI version information */
684 ahci_version = ddi_get32(ahci_ctlp->ahcictl_ahci_acc_handle,
685 (uint32_t *)AHCI_GLOBAL_VS(ahci_ctlp));
686
yt160523a9440e82008-06-11 22:25:05 -0700687 cmn_err(CE_NOTE, "!ahci%d: hba AHCI version = %x.%x", instance,
yt1605232fcbc372006-12-23 23:16:13 -0800688 (ahci_version & 0xffff0000) >> 16,
689 ((ahci_version & 0x0000ff00) >> 4 |
690 (ahci_version & 0x000000ff)));
691
692 /* We don't support controllers whose versions are lower than 1.0 */
693 if (!(ahci_version & 0xffff0000)) {
yt160523a9440e82008-06-11 22:25:05 -0700694 cmn_err(CE_WARN, "ahci%d: Don't support AHCI HBA with lower "
695 "than version 1.0", instance);
yt1605232fcbc372006-12-23 23:16:13 -0800696 goto err_out;
697 }
698
699 /* Get the HBA capabilities information */
700 cap_status = ddi_get32(ahci_ctlp->ahcictl_ahci_acc_handle,
701 (uint32_t *)AHCI_GLOBAL_CAP(ahci_ctlp));
702
ying tian - Beijing China356f6262010-01-15 13:21:04 +0800703 AHCIDBG(AHCIDBG_INIT, ahci_ctlp, "hba capabilities = 0x%x",
yt1605232fcbc372006-12-23 23:16:13 -0800704 cap_status);
705
Marcel Telka2ac30282013-06-08 23:24:29 +0200706 /* CAP2 (HBA Capabilities Extended) is available since AHCI spec 1.2 */
707 if (ahci_version >= 0x00010200) {
708 uint32_t cap2_status;
709
710 /* Get the HBA capabilities extended information */
711 cap2_status = ddi_get32(ahci_ctlp->ahcictl_ahci_acc_handle,
712 (uint32_t *)AHCI_GLOBAL_CAP2(ahci_ctlp));
713
714 AHCIDBG(AHCIDBG_INIT, ahci_ctlp,
715 "hba capabilities extended = 0x%x", cap2_status);
716 }
717
yt16052368d33a22007-08-16 18:51:39 -0700718#if AHCI_DEBUG
719 /* Get the interface speed supported by the HBA */
720 speed = (cap_status & AHCI_HBA_CAP_ISS) >> AHCI_HBA_CAP_ISS_SHIFT;
721 if (speed == 0x01) {
Fred Herardf5f2d262009-07-14 16:27:17 -0400722 AHCIDBG(AHCIDBG_INIT, ahci_ctlp,
723 "hba interface speed support: Gen 1 (1.5Gbps)", NULL);
yt16052368d33a22007-08-16 18:51:39 -0700724 } else if (speed == 0x10) {
Fred Herardf5f2d262009-07-14 16:27:17 -0400725 AHCIDBG(AHCIDBG_INIT, ahci_ctlp,
726 "hba interface speed support: Gen 2 (3 Gbps)", NULL);
yt16052368d33a22007-08-16 18:51:39 -0700727 } else if (speed == 0x11) {
Fred Herardf5f2d262009-07-14 16:27:17 -0400728 AHCIDBG(AHCIDBG_INIT, ahci_ctlp,
729 "hba interface speed support: Gen 3 (6 Gbps)", NULL);
yt16052368d33a22007-08-16 18:51:39 -0700730 }
731#endif
732
yt1605232fcbc372006-12-23 23:16:13 -0800733 /* Get the number of command slots supported by the HBA */
734 ahci_ctlp->ahcictl_num_cmd_slots =
735 ((cap_status & AHCI_HBA_CAP_NCS) >>
736 AHCI_HBA_CAP_NCS_SHIFT) + 1;
737
Fred Herardf5f2d262009-07-14 16:27:17 -0400738 AHCIDBG(AHCIDBG_INIT, ahci_ctlp, "hba number of cmd slots: %d",
yt1605232fcbc372006-12-23 23:16:13 -0800739 ahci_ctlp->ahcictl_num_cmd_slots);
740
741 /* Get the bit map which indicates ports implemented by the HBA */
742 ahci_ctlp->ahcictl_ports_implemented =
743 ddi_get32(ahci_ctlp->ahcictl_ahci_acc_handle,
744 (uint32_t *)AHCI_GLOBAL_PI(ahci_ctlp));
745
Fred Herardf5f2d262009-07-14 16:27:17 -0400746 AHCIDBG(AHCIDBG_INIT, ahci_ctlp, "hba implementation of ports: 0x%x",
yt1605232fcbc372006-12-23 23:16:13 -0800747 ahci_ctlp->ahcictl_ports_implemented);
748
Marcel Telka2ac30282013-06-08 23:24:29 +0200749 /* Max port number implemented */
750 ahci_ctlp->ahcictl_num_ports =
751 ddi_fls(ahci_ctlp->ahcictl_ports_implemented);
yt16052309121342007-05-20 19:46:13 -0700752
Fred Herardf5f2d262009-07-14 16:27:17 -0400753 AHCIDBG(AHCIDBG_INIT, ahci_ctlp, "hba number of ports: %d",
Marcel Telka2ac30282013-06-08 23:24:29 +0200754 (cap_status & AHCI_HBA_CAP_NP) + 1);
yt16052309121342007-05-20 19:46:13 -0700755
yt1605232fcbc372006-12-23 23:16:13 -0800756 /* Get the number of implemented ports by the HBA */
757 ahci_ctlp->ahcictl_num_implemented_ports =
758 ahci_get_num_implemented_ports(
759 ahci_ctlp->ahcictl_ports_implemented);
760
Fred Herardf5f2d262009-07-14 16:27:17 -0400761 AHCIDBG(AHCIDBG_INIT, ahci_ctlp,
yt16052368d33a22007-08-16 18:51:39 -0700762 "hba number of implemented ports: %d",
yt1605232fcbc372006-12-23 23:16:13 -0800763 ahci_ctlp->ahcictl_num_implemented_ports);
764
yt160523a9440e82008-06-11 22:25:05 -0700765 /* Check whether HBA supports 64bit DMA addressing */
yt1605232fcbc372006-12-23 23:16:13 -0800766 if (!(cap_status & AHCI_HBA_CAP_S64A)) {
ying tian - Beijing China259105b2009-05-22 12:06:06 +0800767 ahci_ctlp->ahcictl_cap |= AHCI_CAP_BUF_32BIT_DMA;
768 ahci_ctlp->ahcictl_cap |= AHCI_CAP_COMMU_32BIT_DMA;
Fred Herardf5f2d262009-07-14 16:27:17 -0400769 AHCIDBG(AHCIDBG_INIT, ahci_ctlp,
770 "hba does not support 64-bit addressing", NULL);
yt1605232fcbc372006-12-23 23:16:13 -0800771 }
772
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +0800773 /* Checking for the support of Port Multiplier */
774 if (cap_status & AHCI_HBA_CAP_SPM) {
775 ahci_ctlp->ahcictl_cap |= AHCI_CAP_PMULT_CBSS;
776 AHCIDBG(AHCIDBG_INIT|AHCIDBG_PMULT, ahci_ctlp,
777 "hba supports port multiplier (CBSS)", NULL);
778
779 /* Support FIS-based switching ? */
780 if (cap_status & AHCI_HBA_CAP_FBSS) {
781 ahci_ctlp->ahcictl_cap |= AHCI_CAP_PMULT_FBSS;
782 AHCIDBG(AHCIDBG_INIT|AHCIDBG_PMULT, ahci_ctlp,
783 "hba supports FIS-based switching (FBSS)", NULL);
784 }
785 }
786
Xiao-Yu Zhang0a4c4ce2009-03-28 15:28:14 +0800787 /* Checking for Support Command List Override */
788 if (cap_status & AHCI_HBA_CAP_SCLO) {
789 ahci_ctlp->ahcictl_cap |= AHCI_CAP_SCLO;
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +0800790 AHCIDBG(AHCIDBG_INIT|AHCIDBG_PMULT, ahci_ctlp,
Fred Herardf5f2d262009-07-14 16:27:17 -0400791 "hba supports command list override.", NULL);
Xiao-Yu Zhang0a4c4ce2009-03-28 15:28:14 +0800792 }
793
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +0800794 /* Checking for Asynchronous Notification */
795 if (cap_status & AHCI_HBA_CAP_SSNTF) {
796 ahci_ctlp->ahcictl_cap |= AHCI_CAP_SNTF;
797 AHCIDBG(AHCIDBG_INIT|AHCIDBG_PMULT, ahci_ctlp,
798 "hba supports asynchronous notification.", NULL);
799 }
800
yt16052368d33a22007-08-16 18:51:39 -0700801 if (pci_config_setup(dip, &ahci_ctlp->ahcictl_pci_conf_handle)
802 != DDI_SUCCESS) {
yt160523a9440e82008-06-11 22:25:05 -0700803 cmn_err(CE_WARN, "!ahci%d: Cannot set up pci configure space",
804 instance);
yt16052368d33a22007-08-16 18:51:39 -0700805 goto err_out;
806 }
807
808 attach_state |= AHCI_ATTACH_STATE_PCICFG_SETUP;
809
ying tian - Beijing Chinadb2cce02008-11-14 12:04:32 +0800810 /*
811 * Check the pci configuration space, and set caps. We also
812 * handle the hardware defect in this function.
813 *
ying tian - Beijing China259105b2009-05-22 12:06:06 +0800814 * For example, force ATI SB600 to use 32-bit dma addressing
815 * since it doesn't support 64-bit dma though its CAP register
816 * declares it support.
ying tian - Beijing Chinadb2cce02008-11-14 12:04:32 +0800817 */
yt16052313bcbb72008-03-13 21:51:45 -0700818 if (ahci_config_space_init(ahci_ctlp) == AHCI_FAILURE) {
yt160523a9440e82008-06-11 22:25:05 -0700819 cmn_err(CE_WARN, "!ahci%d: ahci_config_space_init failed",
820 instance);
yt16052313bcbb72008-03-13 21:51:45 -0700821 goto err_out;
yt16052368d33a22007-08-16 18:51:39 -0700822 }
yt1605232fcbc372006-12-23 23:16:13 -0800823
824 /*
825 * Disable the whole controller interrupts before adding
826 * interrupt handlers(s).
827 */
828 ahci_disable_all_intrs(ahci_ctlp);
829
830 /* Get supported interrupt types */
831 if (ddi_intr_get_supported_types(dip, &intr_types) != DDI_SUCCESS) {
yt160523a9440e82008-06-11 22:25:05 -0700832 cmn_err(CE_WARN, "!ahci%d: ddi_intr_get_supported_types failed",
833 instance);
yt1605232fcbc372006-12-23 23:16:13 -0800834 goto err_out;
835 }
836
Fred Herardf5f2d262009-07-14 16:27:17 -0400837 AHCIDBG(AHCIDBG_INIT|AHCIDBG_INTR, ahci_ctlp,
yt1605232fcbc372006-12-23 23:16:13 -0800838 "ddi_intr_get_supported_types() returned: 0x%x",
839 intr_types);
840
841 if (ahci_msi_enabled && (intr_types & DDI_INTR_TYPE_MSI)) {
842 /*
843 * Try MSI first, but fall back to FIXED if failed
844 */
ying tian - Beijing China2c742e12009-02-06 10:25:09 +0800845 if (ahci_add_intrs(ahci_ctlp, DDI_INTR_TYPE_MSI) ==
846 DDI_SUCCESS) {
yt1605232fcbc372006-12-23 23:16:13 -0800847 ahci_ctlp->ahcictl_intr_type = DDI_INTR_TYPE_MSI;
Fred Herardf5f2d262009-07-14 16:27:17 -0400848 AHCIDBG(AHCIDBG_INIT|AHCIDBG_INTR, ahci_ctlp,
849 "Using MSI interrupt type", NULL);
yt1605232fcbc372006-12-23 23:16:13 -0800850 goto intr_done;
851 }
852
Fred Herardf5f2d262009-07-14 16:27:17 -0400853 AHCIDBG(AHCIDBG_INIT|AHCIDBG_INTR, ahci_ctlp,
yt1605232fcbc372006-12-23 23:16:13 -0800854 "MSI registration failed, "
Fred Herardf5f2d262009-07-14 16:27:17 -0400855 "trying FIXED interrupts", NULL);
yt1605232fcbc372006-12-23 23:16:13 -0800856 }
857
858 if (intr_types & DDI_INTR_TYPE_FIXED) {
ying tian - Beijing China2c742e12009-02-06 10:25:09 +0800859 if (ahci_add_intrs(ahci_ctlp, DDI_INTR_TYPE_FIXED) ==
860 DDI_SUCCESS) {
yt1605232fcbc372006-12-23 23:16:13 -0800861 ahci_ctlp->ahcictl_intr_type = DDI_INTR_TYPE_FIXED;
Fred Herardf5f2d262009-07-14 16:27:17 -0400862 AHCIDBG(AHCIDBG_INIT|AHCIDBG_INTR, ahci_ctlp,
863 "Using FIXED interrupt type", NULL);
yt1605232fcbc372006-12-23 23:16:13 -0800864 goto intr_done;
865 }
866
Fred Herardf5f2d262009-07-14 16:27:17 -0400867 AHCIDBG(AHCIDBG_INIT|AHCIDBG_INTR, ahci_ctlp,
868 "FIXED interrupt registration failed", NULL);
yt1605232fcbc372006-12-23 23:16:13 -0800869 }
870
yt160523a9440e82008-06-11 22:25:05 -0700871 cmn_err(CE_WARN, "!ahci%d: Interrupt registration failed", instance);
yt1605232fcbc372006-12-23 23:16:13 -0800872
873 goto err_out;
874
875intr_done:
876
877 attach_state |= AHCI_ATTACH_STATE_INTR_ADDED;
878
879 /* Initialize the controller mutex */
880 mutex_init(&ahci_ctlp->ahcictl_mutex, NULL, MUTEX_DRIVER,
881 (void *)(uintptr_t)ahci_ctlp->ahcictl_intr_pri);
882
883 attach_state |= AHCI_ATTACH_STATE_MUTEX_INIT;
884
885 if (ahci_dma_prdt_number < AHCI_MIN_PRDT_NUMBER) {
886 ahci_dma_prdt_number = AHCI_MIN_PRDT_NUMBER;
887 } else if (ahci_dma_prdt_number > AHCI_MAX_PRDT_NUMBER) {
888 ahci_dma_prdt_number = AHCI_MAX_PRDT_NUMBER;
889 }
890
891 ahci_cmd_table_size = (sizeof (ahci_cmd_table_t) +
892 (ahci_dma_prdt_number - AHCI_PRDT_NUMBER) *
893 sizeof (ahci_prdt_item_t));
894
Fred Herardf5f2d262009-07-14 16:27:17 -0400895 AHCIDBG(AHCIDBG_INIT, ahci_ctlp,
yt1605232fcbc372006-12-23 23:16:13 -0800896 "ahci_attach: ahci_dma_prdt_number set by user is 0x%x,"
897 " ahci_cmd_table_size is 0x%x",
898 ahci_dma_prdt_number, ahci_cmd_table_size);
899
900 if (ahci_dma_prdt_number != AHCI_PRDT_NUMBER)
901 ahci_ctlp->ahcictl_buffer_dma_attr.dma_attr_sgllen =
902 ahci_dma_prdt_number;
903
yt160523a9440e82008-06-11 22:25:05 -0700904 ahci_ctlp->ahcictl_buffer_dma_attr = buffer_dma_attr;
905 ahci_ctlp->ahcictl_rcvd_fis_dma_attr = rcvd_fis_dma_attr;
906 ahci_ctlp->ahcictl_cmd_list_dma_attr = cmd_list_dma_attr;
907 ahci_ctlp->ahcictl_cmd_table_dma_attr = cmd_table_dma_attr;
908
ying tian - Beijing China17ac46b2009-10-27 10:21:22 +0800909 /*
910 * enable 64bit dma for data buffer for SB600 if
911 * sb600_buf_64bit_dma_disable is B_FALSE
912 */
ying tian - Beijing China259105b2009-05-22 12:06:06 +0800913 if ((ahci_buf_64bit_dma == B_FALSE) ||
ying tian - Beijing China17ac46b2009-10-27 10:21:22 +0800914 ((ahci_ctlp->ahcictl_cap & AHCI_CAP_BUF_32BIT_DMA) &&
915 !(sb600_buf_64bit_dma_disable == B_FALSE &&
916 ahci_ctlp->ahcictl_venid == 0x1002 &&
917 ahci_ctlp->ahcictl_devid == 0x4380))) {
yt160523a9440e82008-06-11 22:25:05 -0700918 ahci_ctlp->ahcictl_buffer_dma_attr.dma_attr_addr_hi =
919 0xffffffffull;
ying tian - Beijing China259105b2009-05-22 12:06:06 +0800920 }
921
ying tian - Beijing China17ac46b2009-10-27 10:21:22 +0800922 /*
923 * enable 64bit dma for command buffer for SB600/700/710/800
924 * if sbxxx_commu_64bit_dma_disable is B_FALSE
925 */
ying tian - Beijing China259105b2009-05-22 12:06:06 +0800926 if ((ahci_commu_64bit_dma == B_FALSE) ||
ying tian - Beijing China17ac46b2009-10-27 10:21:22 +0800927 ((ahci_ctlp->ahcictl_cap & AHCI_CAP_COMMU_32BIT_DMA) &&
928 !(sbxxx_commu_64bit_dma_disable == B_FALSE &&
929 ahci_ctlp->ahcictl_venid == 0x1002 &&
930 (ahci_ctlp->ahcictl_devid == 0x4380 ||
931 ahci_ctlp->ahcictl_devid == 0x4391)))) {
yt160523a9440e82008-06-11 22:25:05 -0700932 ahci_ctlp->ahcictl_rcvd_fis_dma_attr.dma_attr_addr_hi =
933 0xffffffffull;
934 ahci_ctlp->ahcictl_cmd_list_dma_attr.dma_attr_addr_hi =
935 0xffffffffull;
936 ahci_ctlp->ahcictl_cmd_table_dma_attr.dma_attr_addr_hi =
937 0xffffffffull;
938 }
939
yt16052368d33a22007-08-16 18:51:39 -0700940 /* Allocate the ports structure */
941 status = ahci_alloc_ports_state(ahci_ctlp);
942 if (status != AHCI_SUCCESS) {
yt160523a9440e82008-06-11 22:25:05 -0700943 cmn_err(CE_WARN, "!ahci%d: Cannot allocate ports structure",
944 instance);
yt16052368d33a22007-08-16 18:51:39 -0700945 goto err_out;
946 }
947
948 attach_state |= AHCI_ATTACH_STATE_PORT_ALLOC;
949
yt1605232fcbc372006-12-23 23:16:13 -0800950 /*
yt16052368d33a22007-08-16 18:51:39 -0700951 * Initialize the controller and ports.
yt1605232fcbc372006-12-23 23:16:13 -0800952 */
yt1605232fcbc372006-12-23 23:16:13 -0800953 status = ahci_initialize_controller(ahci_ctlp);
yt1605232fcbc372006-12-23 23:16:13 -0800954 if (status != AHCI_SUCCESS) {
yt160523a9440e82008-06-11 22:25:05 -0700955 cmn_err(CE_WARN, "!ahci%d: HBA initialization failed",
956 instance);
yt1605232fcbc372006-12-23 23:16:13 -0800957 goto err_out;
958 }
959
960 attach_state |= AHCI_ATTACH_STATE_HW_INIT;
961
962 /* Start one thread to check packet timeouts */
963 ahci_ctlp->ahcictl_timeout_id = timeout(
964 (void (*)(void *))ahci_watchdog_handler,
965 (caddr_t)ahci_ctlp, ahci_watchdog_tick);
966
967 attach_state |= AHCI_ATTACH_STATE_TIMEOUT_ENABLED;
968
969 if (ahci_register_sata_hba_tran(ahci_ctlp, cap_status)) {
yt160523a9440e82008-06-11 22:25:05 -0700970 cmn_err(CE_WARN, "!ahci%d: sata hba tran registration failed",
971 instance);
yt1605232fcbc372006-12-23 23:16:13 -0800972 goto err_out;
973 }
974
Xiao-Yu Zhangb22851f2010-06-04 15:30:45 +0800975 /* Check all handles at the end of the attach operation. */
976 if (ahci_check_all_handle(ahci_ctlp) != DDI_SUCCESS) {
977 cmn_err(CE_WARN, "!ahci%d: invalid dma/acc handles",
978 instance);
979 goto err_out;
980 }
981
yt16052313bcbb72008-03-13 21:51:45 -0700982 ahci_ctlp->ahcictl_flags &= ~AHCI_ATTACH;
983
Fred Herardf5f2d262009-07-14 16:27:17 -0400984 AHCIDBG(AHCIDBG_INIT, ahci_ctlp, "ahci_attach success!", NULL);
yt1605232fcbc372006-12-23 23:16:13 -0800985
986 return (DDI_SUCCESS);
987
988err_out:
Xiao-Yu Zhangb22851f2010-06-04 15:30:45 +0800989 /* FMA message */
990 ahci_fm_ereport(ahci_ctlp, DDI_FM_DEVICE_NO_RESPONSE);
991 ddi_fm_service_impact(ahci_ctlp->ahcictl_dip, DDI_SERVICE_LOST);
992
yt1605232fcbc372006-12-23 23:16:13 -0800993 if (attach_state & AHCI_ATTACH_STATE_TIMEOUT_ENABLED) {
994 mutex_enter(&ahci_ctlp->ahcictl_mutex);
995 (void) untimeout(ahci_ctlp->ahcictl_timeout_id);
996 ahci_ctlp->ahcictl_timeout_id = 0;
997 mutex_exit(&ahci_ctlp->ahcictl_mutex);
998 }
999
1000 if (attach_state & AHCI_ATTACH_STATE_HW_INIT) {
yt16052368d33a22007-08-16 18:51:39 -07001001 ahci_uninitialize_controller(ahci_ctlp);
yt1605232fcbc372006-12-23 23:16:13 -08001002 }
1003
yt16052368d33a22007-08-16 18:51:39 -07001004 if (attach_state & AHCI_ATTACH_STATE_PORT_ALLOC) {
1005 ahci_dealloc_ports_state(ahci_ctlp);
1006 }
1007
yt1605232fcbc372006-12-23 23:16:13 -08001008 if (attach_state & AHCI_ATTACH_STATE_MUTEX_INIT) {
1009 mutex_destroy(&ahci_ctlp->ahcictl_mutex);
1010 }
1011
1012 if (attach_state & AHCI_ATTACH_STATE_INTR_ADDED) {
1013 ahci_rem_intrs(ahci_ctlp);
1014 }
1015
yt16052368d33a22007-08-16 18:51:39 -07001016 if (attach_state & AHCI_ATTACH_STATE_PCICFG_SETUP) {
1017 pci_config_teardown(&ahci_ctlp->ahcictl_pci_conf_handle);
1018 }
1019
yt1605232fcbc372006-12-23 23:16:13 -08001020 if (attach_state & AHCI_ATTACH_STATE_REG_MAP) {
1021 ddi_regs_map_free(&ahci_ctlp->ahcictl_ahci_acc_handle);
1022 }
1023
Xiao-Yu Zhangb22851f2010-06-04 15:30:45 +08001024 if (attach_state & AHCI_ATTACH_STATE_FMA) {
1025 ahci_fm_fini(ahci_ctlp);
1026 }
1027
yt1605232fcbc372006-12-23 23:16:13 -08001028 if (attach_state & AHCI_ATTACH_STATE_STATEP_ALLOC) {
1029 ddi_soft_state_free(ahci_statep, instance);
1030 }
1031
1032 return (DDI_FAILURE);
1033}
1034
1035/*
1036 * The detach entry point for dev_ops.
1037 */
1038static int
1039ahci_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
1040{
1041 ahci_ctl_t *ahci_ctlp;
1042 int instance;
1043 int ret;
1044
1045 instance = ddi_get_instance(dip);
1046 ahci_ctlp = ddi_get_soft_state(ahci_statep, instance);
1047
Fred Herardf5f2d262009-07-14 16:27:17 -04001048 AHCIDBG(AHCIDBG_ENTRY, ahci_ctlp, "ahci_detach enter", NULL);
yt1605232fcbc372006-12-23 23:16:13 -08001049
1050 switch (cmd) {
1051 case DDI_DETACH:
yt16052313bcbb72008-03-13 21:51:45 -07001052
yt1605232fcbc372006-12-23 23:16:13 -08001053 /* disable the interrupts for an uninterrupted detach */
1054 mutex_enter(&ahci_ctlp->ahcictl_mutex);
1055 ahci_disable_all_intrs(ahci_ctlp);
1056 mutex_exit(&ahci_ctlp->ahcictl_mutex);
1057
1058 /* unregister from the sata framework. */
1059 ret = ahci_unregister_sata_hba_tran(ahci_ctlp);
1060 if (ret != AHCI_SUCCESS) {
1061 mutex_enter(&ahci_ctlp->ahcictl_mutex);
1062 ahci_enable_all_intrs(ahci_ctlp);
1063 mutex_exit(&ahci_ctlp->ahcictl_mutex);
1064 return (DDI_FAILURE);
1065 }
1066
1067 mutex_enter(&ahci_ctlp->ahcictl_mutex);
1068
1069 /* stop the watchdog handler */
1070 (void) untimeout(ahci_ctlp->ahcictl_timeout_id);
1071 ahci_ctlp->ahcictl_timeout_id = 0;
1072
yt1605232fcbc372006-12-23 23:16:13 -08001073 mutex_exit(&ahci_ctlp->ahcictl_mutex);
1074
yt16052368d33a22007-08-16 18:51:39 -07001075 /* uninitialize the controller */
yt16052368d33a22007-08-16 18:51:39 -07001076 ahci_uninitialize_controller(ahci_ctlp);
yt1605232fcbc372006-12-23 23:16:13 -08001077
1078 /* remove the interrupts */
1079 ahci_rem_intrs(ahci_ctlp);
1080
yt16052368d33a22007-08-16 18:51:39 -07001081 /* deallocate the ports structures */
1082 ahci_dealloc_ports_state(ahci_ctlp);
1083
1084 /* destroy mutex */
1085 mutex_destroy(&ahci_ctlp->ahcictl_mutex);
1086
1087 /* teardown the pci config */
1088 pci_config_teardown(&ahci_ctlp->ahcictl_pci_conf_handle);
1089
yt1605232fcbc372006-12-23 23:16:13 -08001090 /* remove the reg maps. */
1091 ddi_regs_map_free(&ahci_ctlp->ahcictl_ahci_acc_handle);
1092
Xiao-Yu Zhangb22851f2010-06-04 15:30:45 +08001093 /* release fma resource */
1094 ahci_fm_fini(ahci_ctlp);
1095
yt1605232fcbc372006-12-23 23:16:13 -08001096 /* free the soft state. */
1097 ddi_soft_state_free(ahci_statep, instance);
1098
1099 return (DDI_SUCCESS);
1100
1101 case DDI_SUSPEND:
yt16052313bcbb72008-03-13 21:51:45 -07001102
1103 /*
1104 * The steps associated with suspension must include putting
1105 * the underlying device into a quiescent state so that it
1106 * will not generate interrupts or modify or access memory.
1107 */
1108 mutex_enter(&ahci_ctlp->ahcictl_mutex);
1109 if (ahci_ctlp->ahcictl_flags & AHCI_SUSPEND) {
1110 mutex_exit(&ahci_ctlp->ahcictl_mutex);
1111 return (DDI_SUCCESS);
1112 }
1113
1114 ahci_ctlp->ahcictl_flags |= AHCI_SUSPEND;
1115
1116 /* stop the watchdog handler */
1117 if (ahci_ctlp->ahcictl_timeout_id) {
1118 (void) untimeout(ahci_ctlp->ahcictl_timeout_id);
1119 ahci_ctlp->ahcictl_timeout_id = 0;
1120 }
1121
1122 mutex_exit(&ahci_ctlp->ahcictl_mutex);
1123
1124 /*
1125 * drain the taskq
1126 */
ying tian - Beijing Chinaf8a673a2008-12-09 11:24:13 +08001127 ahci_drain_ports_taskq(ahci_ctlp);
yt16052313bcbb72008-03-13 21:51:45 -07001128
1129 /*
1130 * Disable the interrupts and stop all the ports.
1131 */
1132 ahci_uninitialize_controller(ahci_ctlp);
1133
1134 return (DDI_SUCCESS);
yt1605232fcbc372006-12-23 23:16:13 -08001135
1136 default:
1137 return (DDI_FAILURE);
1138 }
1139}
1140
1141/*
1142 * The info entry point for dev_ops.
1143 *
1144 */
1145static int
1146ahci_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd,
Joyce McIntoshd8873b32018-08-07 12:13:16 +03001147 void *arg, void **result)
yt1605232fcbc372006-12-23 23:16:13 -08001148{
1149#ifndef __lock_lint
1150 _NOTE(ARGUNUSED(dip))
1151#endif /* __lock_lint */
1152
1153 ahci_ctl_t *ahci_ctlp;
1154 int instance;
1155 dev_t dev;
1156
1157 dev = (dev_t)arg;
1158 instance = getminor(dev);
1159
1160 switch (infocmd) {
1161 case DDI_INFO_DEVT2DEVINFO:
1162 ahci_ctlp = ddi_get_soft_state(ahci_statep, instance);
1163 if (ahci_ctlp != NULL) {
1164 *result = ahci_ctlp->ahcictl_dip;
1165 return (DDI_SUCCESS);
1166 } else {
1167 *result = NULL;
1168 return (DDI_FAILURE);
1169 }
1170 case DDI_INFO_DEVT2INSTANCE:
1171 *(int *)result = instance;
1172 break;
1173 default:
1174 break;
1175 }
1176
1177 return (DDI_SUCCESS);
1178}
1179
1180/*
1181 * Registers the ahci with sata framework.
1182 */
1183static int
1184ahci_register_sata_hba_tran(ahci_ctl_t *ahci_ctlp, uint32_t cap_status)
1185{
Andy Fiddaman44a84c12018-08-27 15:22:08 +00001186 struct sata_hba_tran *sata_hba_tran;
yt1605232fcbc372006-12-23 23:16:13 -08001187
Fred Herardf5f2d262009-07-14 16:27:17 -04001188 AHCIDBG(AHCIDBG_INIT|AHCIDBG_ENTRY, ahci_ctlp,
1189 "ahci_register_sata_hba_tran enter", NULL);
yt1605232fcbc372006-12-23 23:16:13 -08001190
1191 mutex_enter(&ahci_ctlp->ahcictl_mutex);
1192
1193 /* Allocate memory for the sata_hba_tran */
1194 sata_hba_tran = kmem_zalloc(sizeof (sata_hba_tran_t), KM_SLEEP);
1195
Xiao-Yu Zhang918304a2009-09-28 14:30:40 +08001196 sata_hba_tran->sata_tran_hba_rev = SATA_TRAN_HBA_REV;
yt1605232fcbc372006-12-23 23:16:13 -08001197 sata_hba_tran->sata_tran_hba_dip = ahci_ctlp->ahcictl_dip;
1198 sata_hba_tran->sata_tran_hba_dma_attr =
1199 &ahci_ctlp->ahcictl_buffer_dma_attr;
1200
1201 /* Report the number of implemented ports */
1202 sata_hba_tran->sata_tran_hba_num_cports =
1203 ahci_ctlp->ahcictl_num_implemented_ports;
1204
yt16052368d33a22007-08-16 18:51:39 -07001205 /* Support ATAPI device */
1206 sata_hba_tran->sata_tran_hba_features_support = SATA_CTLF_ATAPI;
yt1605232fcbc372006-12-23 23:16:13 -08001207
1208 /* Get the data transfer capability for PIO command by the HBA */
1209 if (cap_status & AHCI_HBA_CAP_PMD) {
yt16052382263d522007-10-10 19:54:28 -07001210 ahci_ctlp->ahcictl_cap |= AHCI_CAP_PIO_MDRQ;
Fred Herardf5f2d262009-07-14 16:27:17 -04001211 AHCIDBG(AHCIDBG_INFO, ahci_ctlp, "HBA supports multiple "
1212 "DRQ block data transfer for PIO command protocol", NULL);
yt1605232fcbc372006-12-23 23:16:13 -08001213 }
1214
yt16052382263d522007-10-10 19:54:28 -07001215 /*
1216 * According to the AHCI spec, the ATA/ATAPI-7 queued feature set
1217 * is not supported by AHCI (including the READ QUEUED (EXT), WRITE
1218 * QUEUED (EXT), and SERVICE commands). Queued operations are
1219 * supported in AHCI using the READ FPDMA QUEUED and WRITE FPDMA
1220 * QUEUED commands when the HBA and device support native command
1221 * queuing(NCQ).
1222 *
1223 * SATA_CTLF_NCQ will be set to sata_tran_hba_features_support if the
1224 * CAP register of the HBA indicates NCQ is supported.
1225 *
1226 * SATA_CTLF_NCQ cannot be set if AHCI_CAP_NO_MCMDLIST_NONQUEUE is
1227 * set because the previous register content of PxCI can be re-written
1228 * in the register write.
1229 */
1230 if ((cap_status & AHCI_HBA_CAP_SNCQ) &&
1231 !(ahci_ctlp->ahcictl_cap & AHCI_CAP_NO_MCMDLIST_NONQUEUE)) {
1232 sata_hba_tran->sata_tran_hba_features_support |= SATA_CTLF_NCQ;
1233 ahci_ctlp->ahcictl_cap |= AHCI_CAP_NCQ;
Fred Herardf5f2d262009-07-14 16:27:17 -04001234 AHCIDBG(AHCIDBG_INFO, ahci_ctlp, "HBA supports Native "
1235 "Command Queuing", NULL);
yt16052382263d522007-10-10 19:54:28 -07001236 }
1237
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +08001238 /* Support port multiplier? */
1239 if (cap_status & AHCI_HBA_CAP_SPM) {
1240 sata_hba_tran->sata_tran_hba_features_support |=
1241 SATA_CTLF_PORT_MULTIPLIER;
1242
1243 /* Support FIS-based switching for port multiplier? */
1244 if (cap_status & AHCI_HBA_CAP_FBSS) {
1245 sata_hba_tran->sata_tran_hba_features_support |=
1246 SATA_CTLF_PMULT_FBS;
1247 }
1248 }
1249
yt1605232fcbc372006-12-23 23:16:13 -08001250 /* Report the number of command slots */
1251 sata_hba_tran->sata_tran_hba_qdepth = ahci_ctlp->ahcictl_num_cmd_slots;
1252
1253 sata_hba_tran->sata_tran_probe_port = ahci_tran_probe_port;
1254 sata_hba_tran->sata_tran_start = ahci_tran_start;
1255 sata_hba_tran->sata_tran_abort = ahci_tran_abort;
1256 sata_hba_tran->sata_tran_reset_dport = ahci_tran_reset_dport;
1257 sata_hba_tran->sata_tran_hotplug_ops = &ahci_tran_hotplug_ops;
1258#ifdef __lock_lint
1259 sata_hba_tran->sata_tran_selftest = ahci_selftest;
1260#endif
1261 /*
1262 * When SATA framework adds support for pwrmgt the
1263 * pwrmgt_ops needs to be updated
1264 */
1265 sata_hba_tran->sata_tran_pwrmgt_ops = NULL;
1266 sata_hba_tran->sata_tran_ioctl = NULL;
1267
1268 ahci_ctlp->ahcictl_sata_hba_tran = sata_hba_tran;
1269
1270 mutex_exit(&ahci_ctlp->ahcictl_mutex);
1271
1272 /* Attach it to SATA framework */
1273 if (sata_hba_attach(ahci_ctlp->ahcictl_dip, sata_hba_tran, DDI_ATTACH)
1274 != DDI_SUCCESS) {
1275 kmem_free((void *)sata_hba_tran, sizeof (sata_hba_tran_t));
1276 mutex_enter(&ahci_ctlp->ahcictl_mutex);
1277 ahci_ctlp->ahcictl_sata_hba_tran = NULL;
1278 mutex_exit(&ahci_ctlp->ahcictl_mutex);
1279 return (AHCI_FAILURE);
1280 }
1281
1282 return (AHCI_SUCCESS);
1283}
1284
1285/*
1286 * Unregisters the ahci with sata framework.
1287 */
1288static int
1289ahci_unregister_sata_hba_tran(ahci_ctl_t *ahci_ctlp)
1290{
Fred Herardf5f2d262009-07-14 16:27:17 -04001291 AHCIDBG(AHCIDBG_ENTRY, ahci_ctlp,
1292 "ahci_unregister_sata_hba_tran enter", NULL);
yt1605232fcbc372006-12-23 23:16:13 -08001293
1294 /* Detach from the SATA framework. */
1295 if (sata_hba_detach(ahci_ctlp->ahcictl_dip, DDI_DETACH) !=
1296 DDI_SUCCESS) {
1297 return (AHCI_FAILURE);
1298 }
1299
1300 /* Deallocate sata_hba_tran. */
1301 kmem_free((void *)ahci_ctlp->ahcictl_sata_hba_tran,
1302 sizeof (sata_hba_tran_t));
1303
1304 mutex_enter(&ahci_ctlp->ahcictl_mutex);
1305 ahci_ctlp->ahcictl_sata_hba_tran = NULL;
1306 mutex_exit(&ahci_ctlp->ahcictl_mutex);
1307
1308 return (AHCI_SUCCESS);
1309}
1310
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +08001311#define SET_PORTSTR(str, addrp) \
1312 if (AHCI_ADDR_IS_PORT(addrp)) \
1313 (void) sprintf((str), "%d", (addrp)->aa_port); \
1314 else if (AHCI_ADDR_IS_PMULT(addrp)) \
1315 (void) sprintf((str), "%d (pmult)", (addrp)->aa_port); \
1316 else \
1317 (void) sprintf((str), "%d:%d", (addrp)->aa_port, \
1318 (addrp)->aa_pmport);
1319
yt1605232fcbc372006-12-23 23:16:13 -08001320/*
1321 * ahci_tran_probe_port is called by SATA framework. It returns port state,
1322 * port status registers and an attached device type via sata_device
1323 * structure.
1324 *
1325 * We return the cached information from a previous hardware probe. The
1326 * actual hardware probing itself was done either from within
1327 * ahci_initialize_controller() during the driver attach or from a phy
1328 * ready change interrupt handler.
1329 */
1330static int
1331ahci_tran_probe_port(dev_info_t *dip, sata_device_t *sd)
1332{
1333 ahci_ctl_t *ahci_ctlp;
1334 ahci_port_t *ahci_portp;
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +08001335 ahci_addr_t addr, pmult_addr;
1336 uint8_t cport = sd->satadev_addr.cport;
1337 char portstr[10];
1338 uint8_t device_type;
yt1605232fcbc372006-12-23 23:16:13 -08001339 uint32_t port_state;
1340 uint8_t port;
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +08001341 int rval = SATA_SUCCESS, rval_init;
yt1605232fcbc372006-12-23 23:16:13 -08001342
1343 ahci_ctlp = ddi_get_soft_state(ahci_statep, ddi_get_instance(dip));
1344 port = ahci_ctlp->ahcictl_cport_to_port[cport];
1345
yt1605232fcbc372006-12-23 23:16:13 -08001346 ahci_portp = ahci_ctlp->ahcictl_ports[port];
1347
1348 mutex_enter(&ahci_portp->ahciport_mutex);
1349
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +08001350 ahci_get_ahci_addr(ahci_ctlp, sd, &addr);
1351 ASSERT(AHCI_ADDR_IS_VALID(&addr));
1352 SET_PORTSTR(portstr, &addr);
1353
1354 AHCIDBG(AHCIDBG_ENTRY, ahci_ctlp,
1355 "ahci_tran_probe_port enter: port %s", portstr);
1356
1357 if ((AHCI_ADDR_IS_PMULT(&addr) || AHCI_ADDR_IS_PMPORT(&addr)) &&
1358 (ahci_portp->ahciport_device_type != SATA_DTYPE_PMULT ||
1359 ahci_portp->ahciport_pmult_info == NULL)) {
1360 /* port mutliplier is removed. */
1361 AHCIDBG(AHCIDBG_PMULT, ahci_ctlp,
1362 "ahci_tran_probe_port: "
Xiao-Yu Zhang918304a2009-09-28 14:30:40 +08001363 "pmult is removed from port %s", portstr);
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +08001364 mutex_exit(&ahci_portp->ahciport_mutex);
1365 return (SATA_FAILURE);
1366 }
1367
1368 /*
1369 * The sata_device may refer to
1370 * 1. A controller port.
1371 * A controller port should be ready here.
1372 * 2. A port multiplier.
Xiao-Yu Zhang918304a2009-09-28 14:30:40 +08001373 * SATA_ADDR_PMULT_SPEC - if it is not initialized yet, initialize
1374 * it and register the port multiplier to the framework.
1375 * SATA_ADDR_PMULT - check the status of all its device ports.
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +08001376 * 3. A port multiplier port.
1377 * If it has not been initialized, initialized it.
1378 *
1379 * A port multiplier or a port multiplier port may require some
1380 * initialization because we cannot do these time-consuming jobs in an
1381 * interrupt context.
1382 */
Xiao-Yu Zhang918304a2009-09-28 14:30:40 +08001383 if (sd->satadev_addr.qual & SATA_ADDR_PMULT_SPEC) {
1384 AHCI_ADDR_SET_PMULT(&pmult_addr, port);
1385 /* Initialize registers on a port multiplier */
1386 rval_init = ahci_initialize_pmult(ahci_ctlp,
1387 ahci_portp, &pmult_addr, sd);
1388 if (rval_init != AHCI_SUCCESS) {
1389 AHCIDBG(AHCIDBG_PMULT, ahci_ctlp,
1390 "ahci_tran_probe_port: "
1391 "pmult initialization failed.", NULL);
1392 mutex_exit(&ahci_portp->ahciport_mutex);
1393 return (SATA_FAILURE);
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +08001394 }
Xiao-Yu Zhang918304a2009-09-28 14:30:40 +08001395 } else if (sd->satadev_addr.qual & SATA_ADDR_PMULT) {
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +08001396 /* Check pmports hotplug events */
1397 (void) ahci_probe_pmult(ahci_ctlp, ahci_portp, &addr);
Xiao-Yu Zhangd1b621d2009-11-19 16:54:57 +08001398 } else if (sd->satadev_addr.qual & (SATA_ADDR_PMPORT |
1399 SATA_ADDR_DPMPORT)) {
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +08001400 if (ahci_probe_pmport(ahci_ctlp, ahci_portp,
1401 &addr, sd) != AHCI_SUCCESS) {
1402 rval = SATA_FAILURE;
1403 goto out;
1404 }
1405 }
1406
1407 /* Update port state and device type */
1408 port_state = AHCIPORT_GET_STATE(ahci_portp, &addr);
1409
yt1605232fcbc372006-12-23 23:16:13 -08001410 switch (port_state) {
1411
1412 case SATA_PSTATE_FAILED:
1413 sd->satadev_state = SATA_PSTATE_FAILED;
Fred Herardf5f2d262009-07-14 16:27:17 -04001414 AHCIDBG(AHCIDBG_ERRS, ahci_ctlp,
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +08001415 "ahci_tran_probe_port: port %s PORT FAILED", portstr);
yt1605232fcbc372006-12-23 23:16:13 -08001416 goto out;
1417
1418 case SATA_PSTATE_SHUTDOWN:
1419 sd->satadev_state = SATA_PSTATE_SHUTDOWN;
Fred Herardf5f2d262009-07-14 16:27:17 -04001420 AHCIDBG(AHCIDBG_ERRS, ahci_ctlp,
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +08001421 "ahci_tran_probe_port: port %s PORT SHUTDOWN", portstr);
yt1605232fcbc372006-12-23 23:16:13 -08001422 goto out;
1423
1424 case SATA_PSTATE_PWROFF:
1425 sd->satadev_state = SATA_PSTATE_PWROFF;
Fred Herardf5f2d262009-07-14 16:27:17 -04001426 AHCIDBG(AHCIDBG_ERRS, ahci_ctlp,
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +08001427 "ahci_tran_probe_port: port %s PORT PWROFF", portstr);
yt1605232fcbc372006-12-23 23:16:13 -08001428 goto out;
1429
1430 case SATA_PSTATE_PWRON:
1431 sd->satadev_state = SATA_PSTATE_PWRON;
Fred Herardf5f2d262009-07-14 16:27:17 -04001432 AHCIDBG(AHCIDBG_INFO, ahci_ctlp,
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +08001433 "ahci_tran_probe_port: port %s PORT PWRON", portstr);
yt1605232fcbc372006-12-23 23:16:13 -08001434 break;
1435
1436 default:
1437 sd->satadev_state = port_state;
Fred Herardf5f2d262009-07-14 16:27:17 -04001438 AHCIDBG(AHCIDBG_INFO, ahci_ctlp,
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +08001439 "ahci_tran_probe_port: port %s PORT NORMAL %x",
1440 portstr, port_state);
yt1605232fcbc372006-12-23 23:16:13 -08001441 break;
1442 }
1443
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +08001444 device_type = AHCIPORT_GET_DEV_TYPE(ahci_portp, &addr);
yt1605232fcbc372006-12-23 23:16:13 -08001445
1446 switch (device_type) {
1447
1448 case SATA_DTYPE_ATADISK:
1449 sd->satadev_type = SATA_DTYPE_ATADISK;
Fred Herardf5f2d262009-07-14 16:27:17 -04001450 AHCIDBG(AHCIDBG_INFO, ahci_ctlp,
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +08001451 "ahci_tran_probe_port: port %s DISK found", portstr);
yt1605232fcbc372006-12-23 23:16:13 -08001452 break;
1453
ying tian - Beijing China38547052008-11-05 12:39:50 +08001454 case SATA_DTYPE_ATAPI:
1455 /*
1456 * HBA driver only knows it's an ATAPI device, and don't know
ying tian - Beijing Chinaf8a673a2008-12-09 11:24:13 +08001457 * it's CD/DVD, tape or ATAPI disk because the ATAPI device
1458 * type need to be determined by checking IDENTIFY PACKET
1459 * DEVICE data
ying tian - Beijing China38547052008-11-05 12:39:50 +08001460 */
1461 sd->satadev_type = SATA_DTYPE_ATAPI;
Fred Herardf5f2d262009-07-14 16:27:17 -04001462 AHCIDBG(AHCIDBG_INFO, ahci_ctlp,
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +08001463 "ahci_tran_probe_port: port %s ATAPI found", portstr);
yt1605232fcbc372006-12-23 23:16:13 -08001464 break;
1465
1466 case SATA_DTYPE_PMULT:
Marcel Telka265b5a42013-07-01 22:48:16 +02001467 ASSERT(AHCI_ADDR_IS_PORT(&addr) || AHCI_ADDR_IS_PMULT(&addr));
yt1605232fcbc372006-12-23 23:16:13 -08001468 sd->satadev_type = SATA_DTYPE_PMULT;
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +08001469
1470 /* Update the number of pmports. */
1471 ASSERT(ahci_portp->ahciport_pmult_info != NULL);
1472 sd->satadev_add_info = ahci_portp->
1473 ahciport_pmult_info->ahcipmi_num_dev_ports;
1474
Fred Herardf5f2d262009-07-14 16:27:17 -04001475 AHCIDBG(AHCIDBG_INFO, ahci_ctlp,
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +08001476 "ahci_tran_probe_port: port %s Port Multiplier found",
1477 portstr);
yt1605232fcbc372006-12-23 23:16:13 -08001478 break;
1479
1480 case SATA_DTYPE_UNKNOWN:
1481 sd->satadev_type = SATA_DTYPE_UNKNOWN;
Fred Herardf5f2d262009-07-14 16:27:17 -04001482 AHCIDBG(AHCIDBG_INFO, ahci_ctlp,
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +08001483 "ahci_tran_probe_port: port %s Unknown device found",
1484 portstr);
yt1605232fcbc372006-12-23 23:16:13 -08001485 break;
1486
1487 default:
1488 /* we don't support any other device types */
1489 sd->satadev_type = SATA_DTYPE_NONE;
Fred Herardf5f2d262009-07-14 16:27:17 -04001490 AHCIDBG(AHCIDBG_INFO, ahci_ctlp,
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +08001491 "ahci_tran_probe_port: port %s No device found", portstr);
yt1605232fcbc372006-12-23 23:16:13 -08001492 break;
1493 }
1494
1495out:
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +08001496 /* Register update only fails while probing a pmult/pmport */
Xiao-Yu Zhang918304a2009-09-28 14:30:40 +08001497 if (AHCI_ADDR_IS_PORT(&addr) || AHCI_ADDR_IS_PMULT(&addr)) {
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +08001498 ahci_update_sata_registers(ahci_ctlp, port, sd);
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +08001499 } else if (AHCI_ADDR_IS_PMPORT(&addr)) {
1500 if (port_state & SATA_STATE_READY)
1501 if (ahci_update_pmult_pscr(ahci_ctlp,
1502 &addr, sd) != AHCI_SUCCESS)
1503 rval = SATA_FAILURE;
1504 }
yt1605232fcbc372006-12-23 23:16:13 -08001505
Xiao-Yu Zhangb22851f2010-06-04 15:30:45 +08001506 /* Check handles for the sata registers access */
1507 if ((ahci_check_ctl_handle(ahci_ctlp) != DDI_SUCCESS) ||
1508 (ahci_check_port_handle(ahci_ctlp, port) != DDI_SUCCESS)) {
1509 ddi_fm_service_impact(ahci_ctlp->ahcictl_dip,
1510 DDI_SERVICE_UNAFFECTED);
1511 rval = SATA_FAILURE;
1512 }
1513
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +08001514 mutex_exit(&ahci_portp->ahciport_mutex);
1515 return (rval);
yt1605232fcbc372006-12-23 23:16:13 -08001516}
1517
1518/*
yt16052368d33a22007-08-16 18:51:39 -07001519 * There are four operation modes in sata framework:
1520 * SATA_OPMODE_INTERRUPTS
1521 * SATA_OPMODE_POLLING
1522 * SATA_OPMODE_ASYNCH
1523 * SATA_OPMODE_SYNCH
1524 *
1525 * Their combined meanings as following:
1526 *
1527 * SATA_OPMODE_SYNCH
1528 * The command has to be completed before sata_tran_start functions returns.
1529 * Either interrupts or polling could be used - it's up to the driver.
1530 * Mode used currently for internal, sata-module initiated operations.
1531 *
1532 * SATA_OPMODE_SYNCH | SATA_OPMODE_INTERRUPTS
1533 * It is the same as the one above.
1534 *
1535 * SATA_OPMODE_SYNCH | SATA_OPMODE_POLLING
1536 * The command has to be completed before sata_tran_start function returns.
1537 * No interrupt used, polling only. This should be the mode used for scsi
1538 * packets with FLAG_NOINTR.
1539 *
1540 * SATA_OPMODE_ASYNCH | SATA_OPMODE_INTERRUPTS
1541 * The command may be queued (callback function specified). Interrupts could
1542 * be used. It's normal operation mode.
1543 */
1544/*
yt1605232fcbc372006-12-23 23:16:13 -08001545 * Called by sata framework to transport a sata packet down stream.
1546 */
1547static int
1548ahci_tran_start(dev_info_t *dip, sata_pkt_t *spkt)
1549{
1550 ahci_ctl_t *ahci_ctlp;
1551 ahci_port_t *ahci_portp;
Xiao-Yu Zhang918304a2009-09-28 14:30:40 +08001552 ahci_addr_t addr;
yt1605232fcbc372006-12-23 23:16:13 -08001553 uint8_t cport = spkt->satapkt_device.satadev_addr.cport;
1554 uint8_t port;
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +08001555 char portstr[10];
yt1605232fcbc372006-12-23 23:16:13 -08001556
1557 ahci_ctlp = ddi_get_soft_state(ahci_statep, ddi_get_instance(dip));
1558 port = ahci_ctlp->ahcictl_cport_to_port[cport];
1559
Fred Herardf5f2d262009-07-14 16:27:17 -04001560 AHCIDBG(AHCIDBG_ENTRY, ahci_ctlp,
yt1605232fcbc372006-12-23 23:16:13 -08001561 "ahci_tran_start enter: cport %d satapkt 0x%p",
1562 cport, (void *)spkt);
1563
1564 ahci_portp = ahci_ctlp->ahcictl_ports[port];
1565
1566 mutex_enter(&ahci_portp->ahciport_mutex);
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +08001567 ahci_get_ahci_addr(ahci_ctlp, &spkt->satapkt_device, &addr);
1568 SET_PORTSTR(portstr, &addr);
yt1605232fcbc372006-12-23 23:16:13 -08001569
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +08001570 /* Sanity check */
1571 if (AHCI_ADDR_IS_PMPORT(&addr)) {
1572 if (ahci_portp->ahciport_device_type != SATA_DTYPE_PMULT ||
1573 ahci_portp->ahciport_pmult_info == NULL) {
1574
1575 spkt->satapkt_reason = SATA_PKT_PORT_ERROR;
1576 spkt->satapkt_device.satadev_type = SATA_DTYPE_NONE;
1577 spkt->satapkt_device.satadev_state = SATA_STATE_UNKNOWN;
1578 ahci_update_sata_registers(ahci_ctlp, port,
1579 &spkt->satapkt_device);
1580 AHCIDBG(AHCIDBG_ERRS, ahci_ctlp,
1581 "ahci_tran_start returning PORT_ERROR while "
1582 "pmult removed: port: %s", portstr);
1583 mutex_exit(&ahci_portp->ahciport_mutex);
1584 return (SATA_TRAN_PORT_ERROR);
1585 }
1586
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +08001587 if (!(AHCIPORT_GET_STATE(ahci_portp, &addr) &
1588 SATA_STATE_READY)) {
1589 if (!ddi_in_panic() ||
1590 ahci_initialize_pmport(ahci_ctlp,
1591 ahci_portp, &addr) != AHCI_SUCCESS) {
1592 spkt->satapkt_reason = SATA_PKT_PORT_ERROR;
1593 spkt->satapkt_device.satadev_type =
1594 AHCIPORT_GET_DEV_TYPE(ahci_portp, &addr);
1595 spkt->satapkt_device.satadev_state =
1596 AHCIPORT_GET_STATE(ahci_portp, &addr);
1597 ahci_update_sata_registers(ahci_ctlp, port,
1598 &spkt->satapkt_device);
1599 AHCIDBG(AHCIDBG_ERRS, ahci_ctlp,
1600 "ahci_tran_start returning PORT_ERROR "
1601 "while sub-link is not initialized "
1602 "at port: %s", portstr);
1603 mutex_exit(&ahci_portp->ahciport_mutex);
1604 return (SATA_TRAN_PORT_ERROR);
1605 }
1606 }
1607 }
1608
1609 if (AHCIPORT_GET_STATE(ahci_portp, &addr) & SATA_PSTATE_FAILED ||
1610 AHCIPORT_GET_STATE(ahci_portp, &addr) & SATA_PSTATE_SHUTDOWN||
1611 AHCIPORT_GET_STATE(ahci_portp, &addr) & SATA_PSTATE_PWROFF) {
yt1605232fcbc372006-12-23 23:16:13 -08001612 /*
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +08001613 * In case the target driver would send the packet before
yt1605232fcbc372006-12-23 23:16:13 -08001614 * sata framework can have the opportunity to process those
1615 * event reports.
1616 */
1617 spkt->satapkt_reason = SATA_PKT_PORT_ERROR;
1618 spkt->satapkt_device.satadev_state =
1619 ahci_portp->ahciport_port_state;
1620 ahci_update_sata_registers(ahci_ctlp, port,
1621 &spkt->satapkt_device);
Fred Herardf5f2d262009-07-14 16:27:17 -04001622 AHCIDBG(AHCIDBG_ERRS, ahci_ctlp,
yt1605232fcbc372006-12-23 23:16:13 -08001623 "ahci_tran_start returning PORT_ERROR while "
1624 "port in FAILED/SHUTDOWN/PWROFF state: "
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +08001625 "port: %s", portstr);
yt1605232fcbc372006-12-23 23:16:13 -08001626 mutex_exit(&ahci_portp->ahciport_mutex);
1627 return (SATA_TRAN_PORT_ERROR);
1628 }
1629
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +08001630 if (AHCIPORT_GET_DEV_TYPE(ahci_portp, &addr) == SATA_DTYPE_NONE) {
yt1605232fcbc372006-12-23 23:16:13 -08001631 /*
1632 * ahci_intr_phyrdy_change() may have rendered it to
1633 * SATA_DTYPE_NONE.
1634 */
1635 spkt->satapkt_reason = SATA_PKT_PORT_ERROR;
1636 spkt->satapkt_device.satadev_type = SATA_DTYPE_NONE;
1637 spkt->satapkt_device.satadev_state =
1638 ahci_portp->ahciport_port_state;
1639 ahci_update_sata_registers(ahci_ctlp, port,
1640 &spkt->satapkt_device);
Fred Herardf5f2d262009-07-14 16:27:17 -04001641 AHCIDBG(AHCIDBG_ERRS, ahci_ctlp,
yt1605232fcbc372006-12-23 23:16:13 -08001642 "ahci_tran_start returning PORT_ERROR while "
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +08001643 "no device attached: port: %s", portstr);
yt1605232fcbc372006-12-23 23:16:13 -08001644 mutex_exit(&ahci_portp->ahciport_mutex);
1645 return (SATA_TRAN_PORT_ERROR);
1646 }
1647
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +08001648 /* R/W PMULT command will occupy the whole HBA port */
1649 if (RDWR_PMULT_CMD_IN_PROGRESS(ahci_portp)) {
1650 AHCIDBG(AHCIDBG_ERRS, ahci_ctlp,
1651 "ahci_tran_start returning BUSY while "
1652 "executing READ/WRITE PORT-MULT command: "
1653 "port: %s", portstr);
1654 spkt->satapkt_reason = SATA_PKT_BUSY;
1655 mutex_exit(&ahci_portp->ahciport_mutex);
1656 return (SATA_TRAN_BUSY);
1657 }
1658
1659 if (ahci_portp->ahciport_flags & AHCI_PORT_FLAG_HOTPLUG) {
1660 AHCIDBG(AHCIDBG_ERRS, ahci_ctlp,
1661 "ahci_tran_start returning BUSY while "
1662 "hot-plug in progress: port: %s", portstr);
1663 spkt->satapkt_reason = SATA_PKT_BUSY;
1664 mutex_exit(&ahci_portp->ahciport_mutex);
1665 return (SATA_TRAN_BUSY);
1666 }
1667
yt1605232fcbc372006-12-23 23:16:13 -08001668 /*
1669 * SATA HBA driver should remember that a device was reset and it
1670 * is supposed to reject any packets which do not specify either
1671 * SATA_IGNORE_DEV_RESET_STATE or SATA_CLEAR_DEV_RESET_STATE.
1672 *
1673 * This is to prevent a race condition when a device was arbitrarily
1674 * reset by the HBA driver (and lost it's setting) and a target
1675 * driver sending some commands to a device before the sata framework
1676 * has a chance to restore the device setting (such as cache enable/
1677 * disable or other resettable stuff).
1678 */
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +08001679 /*
1680 * It is unnecessary to use specific flags to indicate
1681 * reset_in_progress for a pmport. While mopping, all command will be
1682 * mopped so that the entire HBA port is being dealt as a single
1683 * object.
1684 */
yt1605232fcbc372006-12-23 23:16:13 -08001685 if (spkt->satapkt_cmd.satacmd_flags.sata_clear_dev_reset) {
1686 ahci_portp->ahciport_reset_in_progress = 0;
Fred Herardf5f2d262009-07-14 16:27:17 -04001687 AHCIDBG(AHCIDBG_ERRS, ahci_ctlp,
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +08001688 "ahci_tran_start [CLEAR] the "
yt16052368d33a22007-08-16 18:51:39 -07001689 "reset_in_progress for port: %d", port);
yt1605232fcbc372006-12-23 23:16:13 -08001690 }
1691
1692 if (ahci_portp->ahciport_reset_in_progress &&
1693 ! spkt->satapkt_cmd.satacmd_flags.sata_ignore_dev_reset &&
1694 ! ddi_in_panic()) {
1695 spkt->satapkt_reason = SATA_PKT_BUSY;
Fred Herardf5f2d262009-07-14 16:27:17 -04001696 AHCIDBG(AHCIDBG_ERRS, ahci_ctlp,
yt1605232fcbc372006-12-23 23:16:13 -08001697 "ahci_tran_start returning BUSY while "
yt16052368d33a22007-08-16 18:51:39 -07001698 "reset in progress: port: %d", port);
yt1605232fcbc372006-12-23 23:16:13 -08001699 mutex_exit(&ahci_portp->ahciport_mutex);
1700 return (SATA_TRAN_BUSY);
1701 }
1702
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +08001703#ifdef AHCI_DEBUG
1704 if (spkt->satapkt_cmd.satacmd_flags.sata_ignore_dev_reset) {
1705 AHCIDBG(AHCIDBG_ERRS, ahci_ctlp,
1706 "ahci_tran_start: packet 0x%p [PASSTHRU] at port %d",
1707 spkt, port);
1708 }
1709#endif
1710
yt16052368d33a22007-08-16 18:51:39 -07001711 if (ahci_portp->ahciport_flags & AHCI_PORT_FLAG_MOPPING) {
yt1605232fcbc372006-12-23 23:16:13 -08001712 spkt->satapkt_reason = SATA_PKT_BUSY;
Fred Herardf5f2d262009-07-14 16:27:17 -04001713 AHCIDBG(AHCIDBG_ERRS, ahci_ctlp,
yt1605232fcbc372006-12-23 23:16:13 -08001714 "ahci_tran_start returning BUSY while "
yt16052368d33a22007-08-16 18:51:39 -07001715 "mopping in progress: port: %d", port);
yt1605232fcbc372006-12-23 23:16:13 -08001716 mutex_exit(&ahci_portp->ahciport_mutex);
1717 return (SATA_TRAN_BUSY);
1718 }
1719
Xiao-Yu Zhangb22851f2010-06-04 15:30:45 +08001720 if (ahci_check_ctl_handle(ahci_ctlp) != DDI_SUCCESS) {
1721 ddi_fm_service_impact(ahci_ctlp->ahcictl_dip,
1722 DDI_SERVICE_UNAFFECTED);
1723 mutex_exit(&ahci_portp->ahciport_mutex);
1724 return (SATA_TRAN_BUSY);
1725 }
1726
yt1605232fcbc372006-12-23 23:16:13 -08001727 if (spkt->satapkt_op_mode &
yt16052368d33a22007-08-16 18:51:39 -07001728 (SATA_OPMODE_SYNCH | SATA_OPMODE_POLLING)) {
ying tian - Beijing Chinab2e36452008-09-17 12:12:16 +08001729 /*
1730 * If a SYNC command to be executed in interrupt context,
1731 * bounce it back to sata module.
1732 */
1733 if (!(spkt->satapkt_op_mode & SATA_OPMODE_POLLING) &&
1734 servicing_interrupt()) {
1735 spkt->satapkt_reason = SATA_PKT_BUSY;
Fred Herardf5f2d262009-07-14 16:27:17 -04001736 AHCIDBG(AHCIDBG_ERRS, ahci_ctlp,
ying tian - Beijing Chinab2e36452008-09-17 12:12:16 +08001737 "ahci_tran_start returning BUSY while "
1738 "sending SYNC mode under interrupt context: "
1739 "port : %d", port);
1740 mutex_exit(&ahci_portp->ahciport_mutex);
1741 return (SATA_TRAN_BUSY);
1742 }
1743
yt16052368d33a22007-08-16 18:51:39 -07001744 /* We need to do the sync start now */
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +08001745 if (ahci_do_sync_start(ahci_ctlp, ahci_portp, &addr,
yt16052368d33a22007-08-16 18:51:39 -07001746 spkt) == AHCI_FAILURE) {
Xiao-Yu Zhangb22851f2010-06-04 15:30:45 +08001747 goto fail_out;
yt16052368d33a22007-08-16 18:51:39 -07001748 }
1749 } else {
1750 /* Async start, using interrupt */
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +08001751 if (ahci_deliver_satapkt(ahci_ctlp, ahci_portp, &addr, spkt)
yt16052368d33a22007-08-16 18:51:39 -07001752 == AHCI_FAILURE) {
1753 spkt->satapkt_reason = SATA_PKT_QUEUE_FULL;
Xiao-Yu Zhangb22851f2010-06-04 15:30:45 +08001754 goto fail_out;
yt16052368d33a22007-08-16 18:51:39 -07001755 }
yt1605232fcbc372006-12-23 23:16:13 -08001756 }
1757
Fred Herardf5f2d262009-07-14 16:27:17 -04001758 AHCIDBG(AHCIDBG_INFO, ahci_ctlp, "ahci_tran_start "
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +08001759 "sata tran accepted: port %s", portstr);
yt1605232fcbc372006-12-23 23:16:13 -08001760
yt16052368d33a22007-08-16 18:51:39 -07001761 mutex_exit(&ahci_portp->ahciport_mutex);
yt1605232fcbc372006-12-23 23:16:13 -08001762 return (SATA_TRAN_ACCEPTED);
Xiao-Yu Zhangb22851f2010-06-04 15:30:45 +08001763
1764fail_out:
1765 /*
1766 * Failed to deliver packet to the controller.
1767 * Check if it's caused by invalid handles.
1768 */
1769 if (ahci_check_ctl_handle(ahci_ctlp) != DDI_SUCCESS ||
1770 ahci_check_port_handle(ahci_ctlp, port) != DDI_SUCCESS) {
1771 spkt->satapkt_device.satadev_type =
1772 AHCIPORT_GET_DEV_TYPE(ahci_portp, &addr);
1773 spkt->satapkt_device.satadev_state =
1774 AHCIPORT_GET_STATE(ahci_portp, &addr);
1775 spkt->satapkt_reason = SATA_PKT_DEV_ERROR;
1776 mutex_exit(&ahci_portp->ahciport_mutex);
1777 return (SATA_TRAN_PORT_ERROR);
1778 }
1779
1780 AHCIDBG(AHCIDBG_ERRS, ahci_ctlp, "ahci_tran_start "
1781 "return QUEUE_FULL: port %d", port);
1782 mutex_exit(&ahci_portp->ahciport_mutex);
1783 return (SATA_TRAN_QUEUE_FULL);
yt1605232fcbc372006-12-23 23:16:13 -08001784}
1785
yt16052368d33a22007-08-16 18:51:39 -07001786/*
1787 * SATA_OPMODE_SYNCH flag is set
1788 *
1789 * If SATA_OPMODE_POLLING flag is set, then we must poll the command
1790 * without interrupt, otherwise we can still use the interrupt.
yt16052368d33a22007-08-16 18:51:39 -07001791 */
1792static int
1793ahci_do_sync_start(ahci_ctl_t *ahci_ctlp, ahci_port_t *ahci_portp,
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +08001794 ahci_addr_t *addrp, sata_pkt_t *spkt)
yt16052368d33a22007-08-16 18:51:39 -07001795{
1796 int pkt_timeout_ticks;
1797 uint32_t timeout_tags;
yt16052368d33a22007-08-16 18:51:39 -07001798 int rval;
yt160523a9440e82008-06-11 22:25:05 -07001799 int instance = ddi_get_instance(ahci_ctlp->ahcictl_dip);
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +08001800 uint8_t port = addrp->aa_port;
yt16052368d33a22007-08-16 18:51:39 -07001801
Marcel Telka265b5a42013-07-01 22:48:16 +02001802 ASSERT(MUTEX_HELD(&ahci_portp->ahciport_mutex));
1803
Fred Herardf5f2d262009-07-14 16:27:17 -04001804 AHCIDBG(AHCIDBG_ENTRY, ahci_ctlp, "ahci_do_sync_start enter: "
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +08001805 "port %d:%d spkt 0x%p", port, addrp->aa_pmport, spkt);
yt16052368d33a22007-08-16 18:51:39 -07001806
1807 if (spkt->satapkt_op_mode & SATA_OPMODE_POLLING) {
yt16052368d33a22007-08-16 18:51:39 -07001808 ahci_portp->ahciport_flags |= AHCI_PORT_FLAG_POLLING;
yt16052368d33a22007-08-16 18:51:39 -07001809 if ((rval = ahci_deliver_satapkt(ahci_ctlp, ahci_portp,
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +08001810 addrp, spkt)) == AHCI_FAILURE) {
Marcel Telka265b5a42013-07-01 22:48:16 +02001811 ahci_portp->ahciport_flags &= ~AHCI_PORT_FLAG_POLLING;
yt16052368d33a22007-08-16 18:51:39 -07001812 return (rval);
1813 }
1814
1815 pkt_timeout_ticks =
1816 drv_usectohz((clock_t)spkt->satapkt_time * 1000000);
1817
yt16052368d33a22007-08-16 18:51:39 -07001818 while (spkt->satapkt_reason == SATA_PKT_BUSY) {
yt16052368d33a22007-08-16 18:51:39 -07001819 /* Simulate the interrupt */
Joyce McIntoshd8873b32018-08-07 12:13:16 +03001820 mutex_exit(&ahci_portp->ahciport_mutex);
yt16052382263d522007-10-10 19:54:28 -07001821 ahci_port_intr(ahci_ctlp, ahci_portp, port);
yt16052368d33a22007-08-16 18:51:39 -07001822 mutex_enter(&ahci_portp->ahciport_mutex);
Joyce McIntoshd8873b32018-08-07 12:13:16 +03001823
1824 if (spkt->satapkt_reason != SATA_PKT_BUSY)
1825 break;
1826
1827 mutex_exit(&ahci_portp->ahciport_mutex);
1828 drv_usecwait(AHCI_1MS_USECS);
1829 mutex_enter(&ahci_portp->ahciport_mutex);
1830
1831 pkt_timeout_ticks -= AHCI_1MS_TICKS;
yt16052368d33a22007-08-16 18:51:39 -07001832 if (pkt_timeout_ticks < 0) {
yt160523a9440e82008-06-11 22:25:05 -07001833 cmn_err(CE_WARN, "!ahci%d: ahci_do_sync_start "
yt16052368d33a22007-08-16 18:51:39 -07001834 "port %d satapkt 0x%p timed out\n",
yt160523a9440e82008-06-11 22:25:05 -07001835 instance, port, (void *)spkt);
yt16052368d33a22007-08-16 18:51:39 -07001836 timeout_tags = (0x1 << rval);
1837 mutex_exit(&ahci_portp->ahciport_mutex);
1838 ahci_timeout_pkts(ahci_ctlp, ahci_portp,
yt16052382263d522007-10-10 19:54:28 -07001839 port, timeout_tags);
yt16052368d33a22007-08-16 18:51:39 -07001840 mutex_enter(&ahci_portp->ahciport_mutex);
1841 }
1842 }
Joyce McIntoshd8873b32018-08-07 12:13:16 +03001843
yt16052368d33a22007-08-16 18:51:39 -07001844 ahci_portp->ahciport_flags &= ~AHCI_PORT_FLAG_POLLING;
yt16052368d33a22007-08-16 18:51:39 -07001845 return (AHCI_SUCCESS);
1846
1847 } else {
1848 if ((rval = ahci_deliver_satapkt(ahci_ctlp, ahci_portp,
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +08001849 addrp, spkt)) == AHCI_FAILURE)
yt16052368d33a22007-08-16 18:51:39 -07001850 return (rval);
1851
yt16052382263d522007-10-10 19:54:28 -07001852#if AHCI_DEBUG
1853 /*
1854 * Note that the driver always uses the slot 0 to deliver
1855 * REQUEST SENSE or READ LOG EXT command
1856 */
1857 if (ERR_RETRI_CMD_IN_PROGRESS(ahci_portp))
1858 ASSERT(rval == 0);
1859#endif
1860
yt16052368d33a22007-08-16 18:51:39 -07001861 while (spkt->satapkt_reason == SATA_PKT_BUSY)
1862 cv_wait(&ahci_portp->ahciport_cv,
1863 &ahci_portp->ahciport_mutex);
1864
1865 return (AHCI_SUCCESS);
1866 }
1867}
1868
yt1605232fcbc372006-12-23 23:16:13 -08001869/*
yt16052382263d522007-10-10 19:54:28 -07001870 * Searches for and claims a free command slot.
yt1605232fcbc372006-12-23 23:16:13 -08001871 *
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +08001872 * Returns value:
yt16052382263d522007-10-10 19:54:28 -07001873 *
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +08001874 * AHCI_FAILURE returned only if
1875 * 1. No empty slot left
1876 * 2. Non-queued command requested while queued command(s) is outstanding
1877 * 3. Queued command requested while non-queued command(s) is outstanding
yt16052382263d522007-10-10 19:54:28 -07001878 * 4. HBA doesn't support multiple-use of command list while already a
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +08001879 * non-queued command is oustanding
1880 * 5. Queued command requested while some queued command(s) has been
1881 * outstanding on a different port multiplier port. (AHCI spec 1.2,
1882 * 9.1.2)
yt16052382263d522007-10-10 19:54:28 -07001883 *
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +08001884 * claimed slot number returned if succeeded
yt16052382263d522007-10-10 19:54:28 -07001885 *
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +08001886 * NOTE: it will always return slot 0 for following commands to simplify the
1887 * algorithm.
Andy Fiddaman44a84c12018-08-27 15:22:08 +00001888 * 1. REQUEST SENSE or READ LOG EXT command during error recovery process
1889 * 2. READ/WRITE PORTMULT command
yt1605232fcbc372006-12-23 23:16:13 -08001890 */
yt1605232fcbc372006-12-23 23:16:13 -08001891static int
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +08001892ahci_claim_free_slot(ahci_ctl_t *ahci_ctlp, ahci_port_t *ahci_portp,
1893 ahci_addr_t *addrp, int command_type)
yt1605232fcbc372006-12-23 23:16:13 -08001894{
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +08001895 uint32_t port_cmd_issue;
yt1605232fcbc372006-12-23 23:16:13 -08001896 uint32_t free_slots;
1897 int slot;
1898
Marcel Telka265b5a42013-07-01 22:48:16 +02001899 ASSERT(MUTEX_HELD(&ahci_portp->ahciport_mutex));
1900
Fred Herardf5f2d262009-07-14 16:27:17 -04001901 AHCIDBG(AHCIDBG_ENTRY, ahci_ctlp, "ahci_claim_free_slot enter "
yt16052382263d522007-10-10 19:54:28 -07001902 "ahciport_pending_tags = 0x%x "
1903 "ahciport_pending_ncq_tags = 0x%x",
1904 ahci_portp->ahciport_pending_tags,
1905 ahci_portp->ahciport_pending_ncq_tags);
yt1605232fcbc372006-12-23 23:16:13 -08001906
yt16052382263d522007-10-10 19:54:28 -07001907 /*
1908 * According to the AHCI spec, system software is responsible to
1909 * ensure that queued and non-queued commands are not mixed in
1910 * the command list.
1911 */
1912 if (command_type == AHCI_NON_NCQ_CMD) {
1913 /* Non-NCQ command request */
1914 if (NCQ_CMD_IN_PROGRESS(ahci_portp)) {
Fred Herardf5f2d262009-07-14 16:27:17 -04001915 AHCIDBG(AHCIDBG_INFO|AHCIDBG_NCQ, ahci_ctlp,
yt16052382263d522007-10-10 19:54:28 -07001916 "ahci_claim_free_slot: there is still pending "
1917 "queued command(s) in the command list, "
1918 "so no available slot for the non-queued "
Fred Herardf5f2d262009-07-14 16:27:17 -04001919 "command", NULL);
yt16052382263d522007-10-10 19:54:28 -07001920 return (AHCI_FAILURE);
1921 }
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +08001922 if (RDWR_PMULT_CMD_IN_PROGRESS(ahci_portp)) {
1923 AHCIDBG(AHCIDBG_INFO|AHCIDBG_PMULT, ahci_ctlp,
1924 "ahci_claim_free_slot: there is still pending "
1925 "read/write port-mult command(s) in command list, "
1926 "so no available slot for the non-queued command",
1927 NULL);
1928 return (AHCI_FAILURE);
1929 }
yt16052382263d522007-10-10 19:54:28 -07001930 if ((ahci_ctlp->ahcictl_cap & AHCI_CAP_NO_MCMDLIST_NONQUEUE) &&
1931 NON_NCQ_CMD_IN_PROGRESS(ahci_portp)) {
Fred Herardf5f2d262009-07-14 16:27:17 -04001932 AHCIDBG(AHCIDBG_INFO, ahci_ctlp,
yt16052382263d522007-10-10 19:54:28 -07001933 "ahci_claim_free_slot: HBA cannot support multiple-"
Fred Herardf5f2d262009-07-14 16:27:17 -04001934 "use of the command list for non-queued commands",
1935 NULL);
yt16052382263d522007-10-10 19:54:28 -07001936 return (AHCI_FAILURE);
1937 }
1938 free_slots = (~ahci_portp->ahciport_pending_tags) &
1939 AHCI_SLOT_MASK(ahci_ctlp);
1940 } else if (command_type == AHCI_NCQ_CMD) {
1941 /* NCQ command request */
1942 if (NON_NCQ_CMD_IN_PROGRESS(ahci_portp)) {
Fred Herardf5f2d262009-07-14 16:27:17 -04001943 AHCIDBG(AHCIDBG_INFO|AHCIDBG_NCQ, ahci_ctlp,
yt16052382263d522007-10-10 19:54:28 -07001944 "ahci_claim_free_slot: there is still pending "
1945 "non-queued command(s) in the command list, "
Fred Herardf5f2d262009-07-14 16:27:17 -04001946 "so no available slot for the queued command",
1947 NULL);
yt16052382263d522007-10-10 19:54:28 -07001948 return (AHCI_FAILURE);
1949 }
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +08001950
1951 /*
1952 * NCQ commands cannot be sent to different port multiplier
1953 * ports in Command-Based Switching mode
1954 */
1955 /*
1956 * NOTE: In Command-Based Switching mode, AHCI controller
1957 * usually reports a 'Handshake Error' when multiple NCQ
1958 * commands are outstanding simultaneously.
1959 */
1960 if (AHCIPORT_DEV_TYPE(ahci_portp, addrp) == SATA_DTYPE_PMULT) {
1961 ASSERT(ahci_portp->ahciport_pmult_info != NULL);
1962 if (!(ahci_ctlp->ahcictl_cap & AHCI_CAP_PMULT_FBSS) &&
1963 NCQ_CMD_IN_PROGRESS(ahci_portp) &&
1964 AHCIPORT_NCQ_PMPORT(ahci_portp) !=
1965 addrp->aa_pmport) {
1966 AHCIDBG(AHCIDBG_INFO, ahci_ctlp,
1967 "ahci_claim_free_slot: there is still "
1968 "pending queued command(s) in the "
1969 "command list for another Port Multiplier "
1970 "port, so no available slot.", NULL);
1971 return (AHCI_FAILURE);
1972 }
1973 }
1974
yt16052382263d522007-10-10 19:54:28 -07001975 free_slots = (~ahci_portp->ahciport_pending_ncq_tags) &
1976 AHCI_NCQ_SLOT_MASK(ahci_portp);
1977 } else if (command_type == AHCI_ERR_RETRI_CMD) {
1978 /* Error retrieval command request */
Fred Herardf5f2d262009-07-14 16:27:17 -04001979 AHCIDBG(AHCIDBG_ERRS, ahci_ctlp,
yt16052382263d522007-10-10 19:54:28 -07001980 "ahci_claim_free_slot: slot 0 is allocated for REQUEST "
Fred Herardf5f2d262009-07-14 16:27:17 -04001981 "SENSE or READ LOG EXT command", NULL);
yt16052382263d522007-10-10 19:54:28 -07001982 slot = 0;
1983 goto out;
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +08001984 } else if (command_type == AHCI_RDWR_PMULT_CMD) {
1985 /*
1986 * An extra check on PxCI. Sometimes PxCI bits may not be
1987 * cleared during hot-plug or error recovery process.
1988 */
1989 port_cmd_issue = ddi_get32(ahci_ctlp->ahcictl_ahci_acc_handle,
1990 (uint32_t *)AHCI_PORT_PxCI(ahci_ctlp, addrp->aa_port));
1991
1992 if (port_cmd_issue != 0) {
1993 AHCIDBG(AHCIDBG_INFO|AHCIDBG_PMULT, ahci_ctlp,
1994 "ahci_claim_free_slot: there is still pending "
1995 "command(s) in command list (0x%x/0x%x, PxCI %x),"
1996 "so no available slot for R/W PMULT command.",
1997 NON_NCQ_CMD_IN_PROGRESS(ahci_portp),
1998 NCQ_CMD_IN_PROGRESS(ahci_portp),
1999 port_cmd_issue);
2000 return (AHCI_FAILURE);
2001 }
2002
2003 AHCIDBG(AHCIDBG_INFO, ahci_ctlp,
2004 "ahci_claim_free_slot: slot 0 is allocated for "
2005 "READ/WRITE PORTMULT command", NULL);
2006 slot = 0;
2007 goto out;
yt16052382263d522007-10-10 19:54:28 -07002008 }
yt1605232fcbc372006-12-23 23:16:13 -08002009
2010 slot = ddi_ffs(free_slots) - 1;
2011 if (slot == -1) {
Fred Herardf5f2d262009-07-14 16:27:17 -04002012 AHCIDBG(AHCIDBG_VERBOSE, ahci_ctlp,
2013 "ahci_claim_free_slot: no empty slots", NULL);
yt1605232fcbc372006-12-23 23:16:13 -08002014 return (AHCI_FAILURE);
2015 }
2016
yt16052382263d522007-10-10 19:54:28 -07002017 /*
2018 * According to the AHCI spec, to allow a simple mechanism for the
2019 * HBA to map command list slots to queue entries, software must
2020 * match the tag number it uses to the slot it is placing the command
2021 * in. For example, if a queued command is placed in slot 5, the tag
2022 * for that command must be 5.
2023 */
2024 if (command_type == AHCI_NCQ_CMD) {
2025 ahci_portp->ahciport_pending_ncq_tags |= (0x1 << slot);
Xiao-Yu Zhang8aa6aad2009-08-16 16:01:00 +08002026 if (AHCI_ADDR_IS_PMPORT(addrp)) {
2027 ASSERT(ahci_portp->ahciport_pmult_info != NULL);
2028 AHCIPORT_NCQ_PMPORT(ahci_portp) = addrp->aa_pmport;
2029 }
yt16052382263d522007-10-10 19:54:28 -07002030 }
2031
yt1605232fcbc372006-12-23 23:16:13 -08002032 ahci_portp->ahciport_pending_tags |= (0x1 << slot);
2033
yt16052382263d522007-10-10 19:54:28 -07002034out:
Fred Herardf5f2d262009-07-14 16:27:17 -04002035 AHCIDBG(AHCIDBG_VERBOSE, ahci_ctlp,
yt1605232fcbc372006-12-23 23:16:13 -08002036 "ahci_claim_free_slot: found slot: 0x%x", slot);
2037
2038 return (slot);
2039}
2040
2041/*
2042 * Builds the Command Table for the sata packet and delivers it to controller.