sata.c revision 918304a3bd962ac065ad520336a044d94b40ad16
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * CDDL HEADER START
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * The contents of this file are subject to the terms of the
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Common Development and Distribution License (the "License").
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * You may not use this file except in compliance with the License.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * or http://www.opensolaris.org/os/licensing.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * See the License for the specific language governing permissions
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * and limitations under the License.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * When distributing Covered Code, include this CDDL HEADER in each
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * If applicable, add the following below this CDDL HEADER, with the
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * fields enclosed by brackets "[]" replaced with your own identifying
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * information: Portions Copyright [yyyy] [name of copyright owner]
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * CDDL HEADER END
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
7095af1983f107c8b16839f70101fdf710c4e620ying tian - Beijing China * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Use is subject to license terms.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * SATA Framework
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Generic SATA Host Adapter Implementation
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#include <sys/conf.h>
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#include <sys/file.h>
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#include <sys/ddi.h>
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#include <sys/sunddi.h>
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#include <sys/modctl.h>
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#include <sys/cmn_err.h>
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#include <sys/errno.h>
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#include <sys/thread.h>
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#include <sys/kstat.h>
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#include <sys/note.h>
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw#include <sys/sysevent.h>
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw#include <sys/sysevent/eventdefs.h>
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw#include <sys/sysevent/dr.h>
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw#include <sys/taskq.h>
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik#include <sys/disp.h>
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#include <sys/sata/impl/sata.h>
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#include <sys/sata/sata_hba.h>
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#include <sys/sata/sata_defs.h>
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#include <sys/sata/sata_cfgadm.h>
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang#include <sys/sata/sata_blacklist.h>
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/* Debug flags - defined in sata.h */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfint sata_debug_flags = 0;
ae8faf9c0cd738ab78a672de5bf7e7f7d004ebb2lsint sata_msg = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Flags enabling selected SATA HBA framework functionality
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#define SATA_ENABLE_QUEUING 1
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#define SATA_ENABLE_NCQ 2
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#define SATA_ENABLE_PROCESS_EVENTS 4
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang#define SATA_ENABLE_PMULT_FBS 8 /* FIS-Based Switching */
37a077ef1920ee044b2887247b2a802e726d3368lsint sata_func_enable =
37a077ef1920ee044b2887247b2a802e726d3368ls SATA_ENABLE_PROCESS_EVENTS | SATA_ENABLE_QUEUING | SATA_ENABLE_NCQ;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw/*
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw * Global variable setting default maximum queue depth (NCQ or TCQ)
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw * Note:minimum queue depth is 1
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw */
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelwint sata_max_queue_depth = SATA_MAX_QUEUE_DEPTH; /* max NCQ/TCQ queue depth */
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw/*
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw * Currently used default NCQ/TCQ queue depth. It is set-up during the driver
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw * initialization, using value from sata_max_queue_depth
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw * It is adjusted to minimum supported by the controller and by the device,
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw * if queueing is enabled.
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw */
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelwstatic int sata_current_max_qdepth;
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw
c75976d12071ddd21443266260066ba036671682pawelw/*
c75976d12071ddd21443266260066ba036671682pawelw * Global variable determining the default behavior after device hotpluggin.
c75976d12071ddd21443266260066ba036671682pawelw * If non-zero, the hotplugged device is onlined (if possible) without explicit
c75976d12071ddd21443266260066ba036671682pawelw * IOCTL request (AP_CONFIGURE).
c75976d12071ddd21443266260066ba036671682pawelw * If zero, hotplugged device is identified, but not onlined.
c75976d12071ddd21443266260066ba036671682pawelw * Enabling (AP_CONNECT) device port with an attached device does not result
c75976d12071ddd21443266260066ba036671682pawelw * in device onlining regardless of the flag setting
c75976d12071ddd21443266260066ba036671682pawelw */
c75976d12071ddd21443266260066ba036671682pawelwint sata_auto_online = 0;
c75976d12071ddd21443266260066ba036671682pawelw
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#ifdef SATA_DEBUG
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#define SATA_LOG_D(args) sata_log args
7a70ede882eacbae00c8d5209afb443e7755684cpawelwuint64_t mbuf_count = 0;
7a70ede882eacbae00c8d5209afb443e7755684cpawelwuint64_t mbuffail_count = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknownsata_atapi_cmd_t sata_atapi_trace[64];
2038334ab26baaa43c9083f35def041511c3cc1fUnknownuint32_t sata_atapi_trace_index = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknownint sata_atapi_trace_save = 1;
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic void sata_save_atapi_trace(sata_pkt_txlate_t *, int);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown#define SATAATAPITRACE(spx, count) if (sata_atapi_trace_save) \
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_save_atapi_trace(spx, count);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#else
f5f2d263454d943a366844932bdb677530ba733bFred Herard#define SATA_LOG_D(args) sata_trace_log args
2038334ab26baaa43c9083f35def041511c3cc1fUnknown#define SATAATAPITRACE(spx, count)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#endif
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown#if 0
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic void
2038334ab26baaa43c9083f35def041511c3cc1fUnknownsata_test_atapi_packet_command(sata_hba_inst_t *, int);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown#endif
8d483882aa3390058094b043f3d62187b5d1de03mlf
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw#ifdef SATA_INJECT_FAULTS
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw#define SATA_INJECT_PKT_FAULT 1
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelwuint32_t sata_inject_fault = 0;
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelwuint32_t sata_inject_fault_count = 0;
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelwuint32_t sata_inject_fault_pause_count = 0;
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcikuint32_t sata_fault_type = 0;
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcikuint32_t sata_fault_cmd = 0;
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcikdev_info_t *sata_fault_ctrl = NULL;
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojciksata_device_t sata_fault_device;
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcikstatic void sata_inject_pkt_fault(sata_pkt_t *, int *, int);
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw#endif
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw#define LEGACY_HWID_LEN 64 /* Model (40) + Serial (20) + pad */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhangstatic char sata_rev_tag[] = {"1.46"};
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * SATA cb_ops functions
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int sata_hba_open(dev_t *, int, int, cred_t *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int sata_hba_close(dev_t, int, int, cred_t *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int sata_hba_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * SCSA required entry points
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int sata_scsi_tgt_init(dev_info_t *, dev_info_t *,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsi_hba_tran_t *, struct scsi_device *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int sata_scsi_tgt_probe(struct scsi_device *,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int (*callback)(void));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void sata_scsi_tgt_free(dev_info_t *, dev_info_t *,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsi_hba_tran_t *, struct scsi_device *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int sata_scsi_start(struct scsi_address *, struct scsi_pkt *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int sata_scsi_abort(struct scsi_address *, struct scsi_pkt *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int sata_scsi_reset(struct scsi_address *, int);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int sata_scsi_getcap(struct scsi_address *, char *, int);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int sata_scsi_setcap(struct scsi_address *, char *, int, int);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic struct scsi_pkt *sata_scsi_init_pkt(struct scsi_address *,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf struct scsi_pkt *, struct buf *, int, int, int, int, int (*)(caddr_t),
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf caddr_t);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void sata_scsi_destroy_pkt(struct scsi_address *, struct scsi_pkt *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void sata_scsi_dmafree(struct scsi_address *, struct scsi_pkt *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void sata_scsi_sync_pkt(struct scsi_address *, struct scsi_pkt *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * SATA HBA interface functions are defined in sata_hba.h header file
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/* Event processing functions */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void sata_event_daemon(void *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void sata_event_thread_control(int);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void sata_process_controller_events(sata_hba_inst_t *sata_hba_inst);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhangstatic void sata_process_pmult_events(sata_hba_inst_t *, uint8_t);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void sata_process_device_reset(sata_hba_inst_t *, sata_address_t *);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhangstatic void sata_process_pmdevice_reset(sata_hba_inst_t *, sata_address_t *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void sata_process_port_failed_event(sata_hba_inst_t *,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_address_t *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void sata_process_port_link_events(sata_hba_inst_t *,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_address_t *);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhangstatic void sata_process_pmport_link_events(sata_hba_inst_t *,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_address_t *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void sata_process_device_detached(sata_hba_inst_t *, sata_address_t *);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhangstatic void sata_process_pmdevice_detached(sata_hba_inst_t *,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_address_t *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void sata_process_device_attached(sata_hba_inst_t *, sata_address_t *);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhangstatic void sata_process_pmdevice_attached(sata_hba_inst_t *,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_address_t *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void sata_process_port_pwr_change(sata_hba_inst_t *, sata_address_t *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void sata_process_cntrl_pwr_level_change(sata_hba_inst_t *);
4360436b3c604bc28d37be269ad152b4c38157c3pawelwstatic void sata_process_target_node_cleanup(sata_hba_inst_t *,
4360436b3c604bc28d37be269ad152b4c38157c3pawelw sata_address_t *);
c75976d12071ddd21443266260066ba036671682pawelwstatic void sata_process_device_autoonline(sata_hba_inst_t *,
c75976d12071ddd21443266260066ba036671682pawelw sata_address_t *saddr);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown/*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Local translation functions
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int sata_txlt_inquiry(sata_pkt_txlate_t *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int sata_txlt_test_unit_ready(sata_pkt_txlate_t *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int sata_txlt_start_stop_unit(sata_pkt_txlate_t *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int sata_txlt_read_capacity(sata_pkt_txlate_t *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int sata_txlt_request_sense(sata_pkt_txlate_t *);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chustatic int sata_txlt_read(sata_pkt_txlate_t *);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chustatic int sata_txlt_write(sata_pkt_txlate_t *);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chustatic int sata_txlt_log_sense(sata_pkt_txlate_t *);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chustatic int sata_txlt_log_select(sata_pkt_txlate_t *);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chustatic int sata_txlt_mode_sense(sata_pkt_txlate_t *);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chustatic int sata_txlt_mode_select(sata_pkt_txlate_t *);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chustatic int sata_txlt_synchronize_cache(sata_pkt_txlate_t *);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chustatic int sata_txlt_write_buffer(sata_pkt_txlate_t *);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chustatic int sata_txlt_nodata_cmd_immediate(sata_pkt_txlate_t *);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chustatic int sata_hba_start(sata_pkt_txlate_t *, int *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int sata_txlt_invalid_command(sata_pkt_txlate_t *);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chustatic int sata_txlt_check_condition(sata_pkt_txlate_t *, uchar_t, uchar_t);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int sata_txlt_lba_out_of_range(sata_pkt_txlate_t *);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chustatic void sata_txlt_rw_completion(sata_pkt_t *);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chustatic void sata_txlt_nodata_cmd_completion(sata_pkt_t *);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chustatic void sata_txlt_download_mcode_cmd_completion(sata_pkt_t *);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chustatic int sata_emul_rw_completion(sata_pkt_txlate_t *);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chustatic struct scsi_extended_sense *sata_immediate_error_response(
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_pkt_txlate_t *, int);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic struct scsi_extended_sense *sata_arq_sense(sata_pkt_txlate_t *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chustatic int sata_txlt_atapi(sata_pkt_txlate_t *);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chustatic void sata_txlt_atapi_completion(sata_pkt_t *);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown/*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Local functions for ioctl
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic int32_t sata_get_port_num(sata_hba_inst_t *, struct devctl_iocdata *);
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic void sata_cfgadm_state(sata_hba_inst_t *, int32_t,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown devctl_ap_state_t *);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhangstatic dev_info_t *sata_get_target_dip(dev_info_t *, uint8_t, uint8_t);
c75976d12071ddd21443266260066ba036671682pawelwstatic dev_info_t *sata_get_scsi_target_dip(dev_info_t *, sata_address_t *);
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic dev_info_t *sata_devt_to_devinfo(dev_t);
c75976d12071ddd21443266260066ba036671682pawelwstatic int sata_ioctl_connect(sata_hba_inst_t *, sata_device_t *);
c75976d12071ddd21443266260066ba036671682pawelwstatic int sata_ioctl_disconnect(sata_hba_inst_t *, sata_device_t *);
c75976d12071ddd21443266260066ba036671682pawelwstatic int sata_ioctl_configure(sata_hba_inst_t *, sata_device_t *);
c75976d12071ddd21443266260066ba036671682pawelwstatic int sata_ioctl_unconfigure(sata_hba_inst_t *, sata_device_t *);
c75976d12071ddd21443266260066ba036671682pawelwstatic int sata_ioctl_activate(sata_hba_inst_t *, sata_device_t *);
c75976d12071ddd21443266260066ba036671682pawelwstatic int sata_ioctl_deactivate(sata_hba_inst_t *, sata_device_t *);
c75976d12071ddd21443266260066ba036671682pawelwstatic int sata_ioctl_reset_port(sata_hba_inst_t *, sata_device_t *);
c75976d12071ddd21443266260066ba036671682pawelwstatic int sata_ioctl_reset_device(sata_hba_inst_t *, sata_device_t *);
c75976d12071ddd21443266260066ba036671682pawelwstatic int sata_ioctl_reset_all(sata_hba_inst_t *);
c75976d12071ddd21443266260066ba036671682pawelwstatic int sata_ioctl_port_self_test(sata_hba_inst_t *, sata_device_t *);
c75976d12071ddd21443266260066ba036671682pawelwstatic int sata_ioctl_get_device_path(sata_hba_inst_t *, sata_device_t *,
c75976d12071ddd21443266260066ba036671682pawelw sata_ioctl_data_t *, int mode);
c75976d12071ddd21443266260066ba036671682pawelwstatic int sata_ioctl_get_ap_type(sata_hba_inst_t *, sata_device_t *,
c75976d12071ddd21443266260066ba036671682pawelw sata_ioctl_data_t *, int mode);
c75976d12071ddd21443266260066ba036671682pawelwstatic int sata_ioctl_get_model_info(sata_hba_inst_t *, sata_device_t *,
c75976d12071ddd21443266260066ba036671682pawelw sata_ioctl_data_t *, int mode);
c75976d12071ddd21443266260066ba036671682pawelwstatic int sata_ioctl_get_revfirmware_info(sata_hba_inst_t *, sata_device_t *,
c75976d12071ddd21443266260066ba036671682pawelw sata_ioctl_data_t *, int mode);
c75976d12071ddd21443266260066ba036671682pawelwstatic int sata_ioctl_get_serialnumber_info(sata_hba_inst_t *,
c75976d12071ddd21443266260066ba036671682pawelw sata_device_t *, sata_ioctl_data_t *, int mode);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown/*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Local functions
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic void sata_remove_hba_instance(dev_info_t *);
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic int sata_validate_sata_hba_tran(dev_info_t *, sata_hba_tran_t *);
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic void sata_probe_ports(sata_hba_inst_t *);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhangstatic void sata_probe_pmports(sata_hba_inst_t *, uint8_t);
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic int sata_reprobe_port(sata_hba_inst_t *, sata_device_t *, int);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhangstatic int sata_reprobe_pmult(sata_hba_inst_t *, sata_device_t *, int);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhangstatic int sata_reprobe_pmport(sata_hba_inst_t *, sata_device_t *, int);
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhangstatic int sata_alloc_pmult(sata_hba_inst_t *, sata_device_t *);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhangstatic void sata_free_pmult(sata_hba_inst_t *, sata_device_t *);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhangstatic int sata_add_device(dev_info_t *, sata_hba_inst_t *, sata_device_t *);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhangstatic int sata_offline_device(sata_hba_inst_t *, sata_device_t *,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_drive_info_t *);
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic dev_info_t *sata_create_target_node(dev_info_t *, sata_hba_inst_t *,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_address_t *);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhangstatic void sata_remove_target_node(sata_hba_inst_t *,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_address_t *);
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic int sata_validate_scsi_address(sata_hba_inst_t *,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown struct scsi_address *, sata_device_t *);
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic int sata_validate_sata_address(sata_hba_inst_t *, int, int, int);
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic sata_pkt_t *sata_pkt_alloc(sata_pkt_txlate_t *, int (*)(caddr_t));
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic void sata_pkt_free(sata_pkt_txlate_t *);
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic int sata_dma_buf_setup(sata_pkt_txlate_t *, int, int (*)(caddr_t),
2038334ab26baaa43c9083f35def041511c3cc1fUnknown caddr_t, ddi_dma_attr_t *);
b5fc475bca6525d8da80728128eefb7100aaf66bapstatic void sata_common_free_dma_rsrcs(sata_pkt_txlate_t *);
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic int sata_probe_device(sata_hba_inst_t *, sata_device_t *);
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic sata_drive_info_t *sata_get_device_info(sata_hba_inst_t *,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_device_t *);
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic int sata_identify_device(sata_hba_inst_t *, sata_drive_info_t *);
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xzstatic void sata_reidentify_device(sata_pkt_txlate_t *);
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic struct buf *sata_alloc_local_buffer(sata_pkt_txlate_t *, int);
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic void sata_free_local_buffer(sata_pkt_txlate_t *);
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic uint64_t sata_check_capacity(sata_drive_info_t *);
2038334ab26baaa43c9083f35def041511c3cc1fUnknownvoid sata_adjust_dma_attr(sata_drive_info_t *, ddi_dma_attr_t *,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ddi_dma_attr_t *);
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic int sata_fetch_device_identify_data(sata_hba_inst_t *,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_drive_info_t *);
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic void sata_update_port_info(sata_hba_inst_t *, sata_device_t *);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhangstatic void sata_update_pmport_info(sata_hba_inst_t *, sata_device_t *);
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic void sata_update_port_scr(sata_port_scr_t *, sata_device_t *);
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic int sata_set_dma_mode(sata_hba_inst_t *, sata_drive_info_t *);
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic int sata_set_cache_mode(sata_hba_inst_t *, sata_drive_info_t *, int);
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic int sata_set_rmsn(sata_hba_inst_t *, sata_drive_info_t *, int);
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic int sata_set_drive_features(sata_hba_inst_t *,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_drive_info_t *, int flag);
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic void sata_init_write_cache_mode(sata_drive_info_t *sdinfo);
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic int sata_initialize_device(sata_hba_inst_t *, sata_drive_info_t *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void sata_identdev_to_inquiry(sata_hba_inst_t *, sata_drive_info_t *,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf uint8_t *);
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic int sata_get_atapi_inquiry_data(sata_hba_inst_t *, sata_address_t *,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown struct scsi_inquiry *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int sata_build_msense_page_1(sata_drive_info_t *, int, uint8_t *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int sata_build_msense_page_8(sata_drive_info_t *, int, uint8_t *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int sata_build_msense_page_1a(sata_drive_info_t *, int, uint8_t *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int sata_build_msense_page_1c(sata_drive_info_t *, int, uint8_t *);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chustatic int sata_build_msense_page_30(sata_drive_info_t *, int, uint8_t *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int sata_mode_select_page_8(sata_pkt_txlate_t *,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf struct mode_cache_scsi3 *, int, int *, int *, int *);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chustatic int sata_mode_select_page_1a(sata_pkt_txlate_t *,
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu struct mode_info_power_cond *, int, int *, int *, int *);
2c9565cfcd87a2045c2e4b76f31ac4e978903589lsstatic int sata_mode_select_page_1c(sata_pkt_txlate_t *,
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls struct mode_info_excpt_page *, int, int *, int *, int *);
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960lsstatic int sata_mode_select_page_30(sata_pkt_txlate_t *,
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls struct mode_acoustic_management *, int, int *, int *, int *);
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls
c03acfcad7780db4ddf763511a82026680b3b2c1lsstatic int sata_build_lsense_page_0(sata_drive_info_t *, uint8_t *);
c03acfcad7780db4ddf763511a82026680b3b2c1lsstatic int sata_build_lsense_page_10(sata_drive_info_t *, uint8_t *,
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_hba_inst_t *);
c03acfcad7780db4ddf763511a82026680b3b2c1lsstatic int sata_build_lsense_page_2f(sata_drive_info_t *, uint8_t *,
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_hba_inst_t *);
c03acfcad7780db4ddf763511a82026680b3b2c1lsstatic int sata_build_lsense_page_30(sata_drive_info_t *, uint8_t *,
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_hba_inst_t *);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chustatic int sata_build_lsense_page_0e(sata_drive_info_t *, uint8_t *,
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sata_pkt_txlate_t *);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chustatic void sata_set_arq_data(sata_pkt_t *);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chustatic void sata_build_read_verify_cmd(sata_cmd_t *, uint16_t, uint64_t);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chustatic void sata_build_generic_cmd(sata_cmd_t *, uint8_t);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chustatic uint8_t sata_get_standby_timer(uint8_t *timer);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void sata_save_drive_settings(sata_drive_info_t *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void sata_show_drive_info(sata_hba_inst_t *, sata_drive_info_t *);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhangstatic void sata_show_pmult_info(sata_hba_inst_t *, sata_device_t *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void sata_log(sata_hba_inst_t *, uint_t, char *fmt, ...);
f5f2d263454d943a366844932bdb677530ba733bFred Herardstatic void sata_trace_log(sata_hba_inst_t *, uint_t, const char *fmt, ...);
4360436b3c604bc28d37be269ad152b4c38157c3pawelwstatic int sata_fetch_smart_return_status(sata_hba_inst_t *,
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_drive_info_t *);
4360436b3c604bc28d37be269ad152b4c38157c3pawelwstatic int sata_fetch_smart_data(sata_hba_inst_t *, sata_drive_info_t *,
c03acfcad7780db4ddf763511a82026680b3b2c1ls struct smart_data *);
4360436b3c604bc28d37be269ad152b4c38157c3pawelwstatic int sata_smart_selftest_log(sata_hba_inst_t *,
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_drive_info_t *,
c03acfcad7780db4ddf763511a82026680b3b2c1ls struct smart_selftest_log *);
4360436b3c604bc28d37be269ad152b4c38157c3pawelwstatic int sata_ext_smart_selftest_read_log(sata_hba_inst_t *,
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_drive_info_t *, struct smart_ext_selftest_log *, uint16_t);
c03acfcad7780db4ddf763511a82026680b3b2c1lsstatic int sata_smart_read_log(sata_hba_inst_t *, sata_drive_info_t *,
c03acfcad7780db4ddf763511a82026680b3b2c1ls uint8_t *, uint8_t, uint8_t);
c03acfcad7780db4ddf763511a82026680b3b2c1lsstatic int sata_read_log_ext_directory(sata_hba_inst_t *, sata_drive_info_t *,
c03acfcad7780db4ddf763511a82026680b3b2c1ls struct read_log_ext_directory *);
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelwstatic void sata_gen_sysevent(sata_hba_inst_t *, sata_address_t *, int);
2c9565cfcd87a2045c2e4b76f31ac4e978903589lsstatic void sata_xlate_errors(sata_pkt_txlate_t *);
a022fe3e0bc959fae460b8b5b818cd1265bf4c66lsstatic void sata_decode_device_error(sata_pkt_txlate_t *,
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls struct scsi_extended_sense *);
4360436b3c604bc28d37be269ad152b4c38157c3pawelwstatic void sata_set_device_removed(dev_info_t *);
4360436b3c604bc28d37be269ad152b4c38157c3pawelwstatic boolean_t sata_check_device_removed(dev_info_t *);
c75976d12071ddd21443266260066ba036671682pawelwstatic void sata_set_target_node_cleanup(sata_hba_inst_t *, sata_address_t *);
82263d52a84b4a969aa53f8ededddff841646ad9ytstatic int sata_ncq_err_ret_cmd_setup(sata_pkt_txlate_t *,
82263d52a84b4a969aa53f8ededddff841646ad9yt sata_drive_info_t *);
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic int sata_atapi_err_ret_cmd_setup(sata_pkt_txlate_t *,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_drive_info_t *);
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic void sata_atapi_packet_cmd_setup(sata_cmd_t *, sata_drive_info_t *);
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic void sata_fixed_sense_data_preset(struct scsi_extended_sense *);
8d483882aa3390058094b043f3d62187b5d1de03mlfstatic void sata_target_devid_register(dev_info_t *, sata_drive_info_t *);
8d483882aa3390058094b043f3d62187b5d1de03mlfstatic int sata_check_modser(char *, int);
8d483882aa3390058094b043f3d62187b5d1de03mlf
4360436b3c604bc28d37be269ad152b4c38157c3pawelw
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * SATA Framework will ignore SATA HBA driver cb_ops structure and
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * register following one with SCSA framework.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Open & close are provided, so scsi framework will not use its own
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic struct cb_ops sata_cb_ops = {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_open, /* open */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_close, /* close */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf nodev, /* strategy */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf nodev, /* print */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf nodev, /* dump */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf nodev, /* read */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf nodev, /* write */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_ioctl, /* ioctl */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf nodev, /* devmap */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf nodev, /* mmap */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf nodev, /* segmap */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf nochpoll, /* chpoll */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ddi_prop_op, /* cb_prop_op */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf 0, /* streamtab */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf D_NEW | D_MP, /* cb_flag */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf CB_REV, /* rev */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf nodev, /* aread */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf nodev /* awrite */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf};
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfextern struct mod_ops mod_miscops;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfextern uchar_t scsi_cdb_size[];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic struct modlmisc modlmisc = {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf &mod_miscops, /* Type of module */
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik "SATA Module" /* module name */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf};
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic struct modlinkage modlinkage = {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf MODREV_1,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (void *)&modlmisc,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf NULL
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf};
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Default sata pkt timeout. Used when a target driver scsi_pkt time is zero,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * i.e. when scsi_pkt has not timeout specified.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int sata_default_pkt_time = 60; /* 60 seconds */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
7a70ede882eacbae00c8d5209afb443e7755684cpawelw/*
7a70ede882eacbae00c8d5209afb443e7755684cpawelw * Intermediate buffer device access attributes - they are required,
7a70ede882eacbae00c8d5209afb443e7755684cpawelw * but not necessarily used.
7a70ede882eacbae00c8d5209afb443e7755684cpawelw */
7a70ede882eacbae00c8d5209afb443e7755684cpawelwstatic ddi_device_acc_attr_t sata_acc_attr = {
7a70ede882eacbae00c8d5209afb443e7755684cpawelw DDI_DEVICE_ATTR_V0,
7a70ede882eacbae00c8d5209afb443e7755684cpawelw DDI_STRUCTURE_LE_ACC,
7a70ede882eacbae00c8d5209afb443e7755684cpawelw DDI_STRICTORDER_ACC
7a70ede882eacbae00c8d5209afb443e7755684cpawelw};
7a70ede882eacbae00c8d5209afb443e7755684cpawelw
7a70ede882eacbae00c8d5209afb443e7755684cpawelw
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Mutexes protecting structures in multithreaded operations.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Because events are relatively rare, a single global mutex protecting
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * data structures should be sufficient. To increase performance, add
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * separate mutex per each sata port and use global mutex only to protect
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * common data structures.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic kmutex_t sata_mutex; /* protects sata_hba_list */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic kmutex_t sata_log_mutex; /* protects log */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic char sata_log_buf[256];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
f5f2d263454d943a366844932bdb677530ba733bFred Herard/*
f5f2d263454d943a366844932bdb677530ba733bFred Herard * sata trace debug
f5f2d263454d943a366844932bdb677530ba733bFred Herard */
f5f2d263454d943a366844932bdb677530ba733bFred Herardstatic sata_trace_rbuf_t *sata_debug_rbuf;
f5f2d263454d943a366844932bdb677530ba733bFred Herardstatic sata_trace_dmsg_t *sata_trace_dmsg_alloc(void);
f5f2d263454d943a366844932bdb677530ba733bFred Herardstatic void sata_trace_dmsg_free(void);
f5f2d263454d943a366844932bdb677530ba733bFred Herardstatic void sata_trace_rbuf_alloc(void);
f5f2d263454d943a366844932bdb677530ba733bFred Herardstatic void sata_trace_rbuf_free(void);
f5f2d263454d943a366844932bdb677530ba733bFred Herard
f5f2d263454d943a366844932bdb677530ba733bFred Herardint dmsg_ring_size = DMSG_RING_SIZE;
f5f2d263454d943a366844932bdb677530ba733bFred Herard
2038334ab26baaa43c9083f35def041511c3cc1fUnknown/* Default write cache setting for SATA hard disks */
2038334ab26baaa43c9083f35def041511c3cc1fUnknownint sata_write_cache = 1; /* enabled */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown/* Default write cache setting for SATA ATAPI CD/DVD */
f8a673ad9145b262edb65a98fb3fb92027d23a05ying tian - Beijing Chinaint sata_atapicdvd_write_cache = 1; /* enabled */
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China/* Default write cache setting for SATA ATAPI tape */
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing Chinaint sata_atapitape_write_cache = 1; /* enabled */
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China
f8a673ad9145b262edb65a98fb3fb92027d23a05ying tian - Beijing China/* Default write cache setting for SATA ATAPI disk */
f8a673ad9145b262edb65a98fb3fb92027d23a05ying tian - Beijing Chinaint sata_atapidisk_write_cache = 1; /* enabled */
f8a673ad9145b262edb65a98fb3fb92027d23a05ying tian - Beijing China
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Linked list of HBA instances
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic sata_hba_inst_t *sata_hba_list = NULL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic sata_hba_inst_t *sata_hba_list_tail = NULL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Pointer to per-instance SATA HBA soft structure is stored in sata_hba_tran
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * structure and in sata soft state.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Event daemon related variables
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic kmutex_t sata_event_mutex;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic kcondvar_t sata_event_cv;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic kthread_t *sata_event_thread = NULL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int sata_event_thread_terminate = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int sata_event_pending = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int sata_event_thread_active = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfextern pri_t minclsyspri;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
37a077ef1920ee044b2887247b2a802e726d3368ls/*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * NCQ error recovery command
37a077ef1920ee044b2887247b2a802e726d3368ls */
37a077ef1920ee044b2887247b2a802e726d3368lsstatic const sata_cmd_t sata_rle_cmd = {
37a077ef1920ee044b2887247b2a802e726d3368ls SATA_CMD_REV,
37a077ef1920ee044b2887247b2a802e726d3368ls NULL,
37a077ef1920ee044b2887247b2a802e726d3368ls {
37a077ef1920ee044b2887247b2a802e726d3368ls SATA_DIR_READ
37a077ef1920ee044b2887247b2a802e726d3368ls },
37a077ef1920ee044b2887247b2a802e726d3368ls ATA_ADDR_LBA48,
37a077ef1920ee044b2887247b2a802e726d3368ls 0,
37a077ef1920ee044b2887247b2a802e726d3368ls 0,
37a077ef1920ee044b2887247b2a802e726d3368ls 0,
37a077ef1920ee044b2887247b2a802e726d3368ls 0,
37a077ef1920ee044b2887247b2a802e726d3368ls 0,
37a077ef1920ee044b2887247b2a802e726d3368ls 1,
37a077ef1920ee044b2887247b2a802e726d3368ls READ_LOG_EXT_NCQ_ERROR_RECOVERY,
37a077ef1920ee044b2887247b2a802e726d3368ls 0,
37a077ef1920ee044b2887247b2a802e726d3368ls 0,
37a077ef1920ee044b2887247b2a802e726d3368ls 0,
37a077ef1920ee044b2887247b2a802e726d3368ls SATAC_READ_LOG_EXT,
37a077ef1920ee044b2887247b2a802e726d3368ls 0,
37a077ef1920ee044b2887247b2a802e726d3368ls 0,
37a077ef1920ee044b2887247b2a802e726d3368ls 0,
37a077ef1920ee044b2887247b2a802e726d3368ls};
37a077ef1920ee044b2887247b2a802e726d3368ls
2038334ab26baaa43c9083f35def041511c3cc1fUnknown/*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * ATAPI error recovery CDB
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic const uint8_t sata_rqsense_cdb[SATA_ATAPI_RQSENSE_CDB_LEN] = {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SCMD_REQUEST_SENSE,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown 0, /* Only fixed RQ format is supported */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown 0,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown 0,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_ATAPI_MIN_RQSENSE_LEN, /* Less data may be returned */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown 0
2038334ab26baaa43c9083f35def041511c3cc1fUnknown};
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/* Warlock directives */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf_NOTE(SCHEME_PROTECTS_DATA("No Mutex Needed", scsi_hba_tran))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf_NOTE(SCHEME_PROTECTS_DATA("No Mutex Needed", scsi_device))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf_NOTE(SCHEME_PROTECTS_DATA("No Mutex Needed", dev_ops))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf_NOTE(SCHEME_PROTECTS_DATA("No Mutex Needed", scsi_extended_sense))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf_NOTE(SCHEME_PROTECTS_DATA("No Mutex Needed", scsi_arq_status))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf_NOTE(SCHEME_PROTECTS_DATA("No Mutex Needed", ddi_dma_attr))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf_NOTE(SCHEME_PROTECTS_DATA("No Mutex Needed", ddi_dma_cookie_t))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf_NOTE(SCHEME_PROTECTS_DATA("No Mutex Needed", devctl_ap_state))
2038334ab26baaa43c9083f35def041511c3cc1fUnknown_NOTE(SCHEME_PROTECTS_DATA("No Mutex Needed", dev_info::devi_state))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf_NOTE(MUTEX_PROTECTS_DATA(sata_mutex, sata_hba_list))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf_NOTE(DATA_READABLE_WITHOUT_LOCK(sata_hba_list))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf_NOTE(MUTEX_PROTECTS_DATA(sata_mutex, sata_hba_inst::satahba_next))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf_NOTE(MUTEX_PROTECTS_DATA(sata_mutex, sata_hba_inst::satahba_prev))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf_NOTE(SCHEME_PROTECTS_DATA("No Mutex Needed", \
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst::satahba_scsi_tran))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf_NOTE(SCHEME_PROTECTS_DATA("No Mutex Needed", sata_hba_inst::satahba_tran))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf_NOTE(SCHEME_PROTECTS_DATA("No Mutex Needed", sata_hba_inst::satahba_dip))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf_NOTE(SCHEME_PROTECTS_DATA("Scheme", sata_hba_inst::satahba_attached))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf_NOTE(DATA_READABLE_WITHOUT_LOCK(sata_hba_inst::satahba_dev_port))
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang_NOTE(MUTEX_PROTECTS_DATA(sata_hba_inst::satahba_mutex,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst::satahba_event_flags))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf_NOTE(MUTEX_PROTECTS_DATA(sata_cport_info::cport_mutex, \
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_cport_info::cport_devp))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf_NOTE(DATA_READABLE_WITHOUT_LOCK(sata_cport_info::cport_devp))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf_NOTE(SCHEME_PROTECTS_DATA("Scheme", sata_cport_info::cport_addr))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf_NOTE(MUTEX_PROTECTS_DATA(sata_cport_info::cport_mutex, \
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_cport_info::cport_dev_type))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf_NOTE(DATA_READABLE_WITHOUT_LOCK(sata_cport_info::cport_dev_type))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf_NOTE(MUTEX_PROTECTS_DATA(sata_cport_info::cport_mutex, \
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_cport_info::cport_state))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf_NOTE(DATA_READABLE_WITHOUT_LOCK(sata_cport_info::cport_state))
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang_NOTE(MUTEX_PROTECTS_DATA(sata_pmport_info::pmport_mutex, \
c75976d12071ddd21443266260066ba036671682pawelw sata_pmport_info::pmport_state))
c75976d12071ddd21443266260066ba036671682pawelw_NOTE(DATA_READABLE_WITHOUT_LOCK(sata_pmport_info::pmport_state))
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang_NOTE(MUTEX_PROTECTS_DATA(sata_pmport_info::pmport_mutex, \
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_pmport_info::pmport_dev_type))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf_NOTE(DATA_READABLE_WITHOUT_LOCK(sata_pmport_info::pmport_dev_type))
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang_NOTE(MUTEX_PROTECTS_DATA(sata_pmport_info::pmport_mutex, \
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_pmport_info::pmport_sata_drive))
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang_NOTE(MUTEX_PROTECTS_DATA(sata_pmport_info::pmport_mutex, \
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_pmport_info::pmport_tgtnode_clean))
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang_NOTE(MUTEX_PROTECTS_DATA(sata_pmport_info::pmport_mutex, \
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_pmport_info::pmport_event_flags))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf_NOTE(DATA_READABLE_WITHOUT_LOCK(sata_pmport_info::pmport_sata_drive))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf_NOTE(DATA_READABLE_WITHOUT_LOCK(sata_pmult_info::pmult_dev_port))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf_NOTE(DATA_READABLE_WITHOUT_LOCK(sata_pmult_info::pmult_num_dev_ports))
37a077ef1920ee044b2887247b2a802e726d3368ls#ifdef SATA_DEBUG
37a077ef1920ee044b2887247b2a802e726d3368ls_NOTE(SCHEME_PROTECTS_DATA("No Mutex Needed", mbuf_count))
37a077ef1920ee044b2887247b2a802e726d3368ls_NOTE(SCHEME_PROTECTS_DATA("No Mutex Needed", mbuffail_count))
2038334ab26baaa43c9083f35def041511c3cc1fUnknown_NOTE(SCHEME_PROTECTS_DATA("No Mutex Needed", sata_atapi_trace))
2038334ab26baaa43c9083f35def041511c3cc1fUnknown_NOTE(SCHEME_PROTECTS_DATA("No Mutex Needed", sata_atapi_trace_index))
37a077ef1920ee044b2887247b2a802e726d3368ls#endif
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/* End of warlock directives */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/* ************** loadable module configuration functions ************** */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfint
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf_init()
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int rval;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_init(&sata_mutex, NULL, MUTEX_DRIVER, NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_init(&sata_event_mutex, NULL, MUTEX_DRIVER, NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_init(&sata_log_mutex, NULL, MUTEX_DRIVER, NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cv_init(&sata_event_cv, NULL, CV_DRIVER, NULL);
f5f2d263454d943a366844932bdb677530ba733bFred Herard sata_trace_rbuf_alloc();
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((rval = mod_install(&modlinkage)) != 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#ifdef SATA_DEBUG
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cmn_err(CE_WARN, "sata: _init: mod_install failed\n");
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#endif
f5f2d263454d943a366844932bdb677530ba733bFred Herard sata_trace_rbuf_free();
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_destroy(&sata_log_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cv_destroy(&sata_event_cv);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_destroy(&sata_event_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_destroy(&sata_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (rval);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfint
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf_fini()
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int rval;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((rval = mod_remove(&modlinkage)) != 0)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (rval);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
f5f2d263454d943a366844932bdb677530ba733bFred Herard sata_trace_rbuf_free();
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_destroy(&sata_log_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cv_destroy(&sata_event_cv);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_destroy(&sata_event_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_destroy(&sata_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (rval);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfint
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf_info(struct modinfo *modinfop)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (mod_info(&modlinkage, modinfop));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/* ********************* SATA HBA entry points ********************* */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Called by SATA HBA from _init().
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Registers HBA driver instance/sata framework pair with scsi framework, by
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * calling scsi_hba_init().
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * SATA HBA driver cb_ops are ignored - SATA HBA framework cb_ops are used
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * instead. SATA HBA framework cb_ops pointer overwrites SATA HBA driver
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * cb_ops pointer in SATA HBA driver dev_ops structure.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * SATA HBA framework cb_ops supplies cb_open cb_close and cb_ioctl vectors.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Return status of the scsi_hba_init() is returned to a calling SATA HBA
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * driver.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfint
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_hba_init(struct modlinkage *modlp)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int rval;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf struct dev_ops *hba_ops;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG1(SATA_DBG_HBA_IF, NULL,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_hba_init: name %s \n",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ((struct modldrv *)(modlp->ml_linkage[0]))->drv_linkinfo);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Fill-up cb_ops and dev_ops when necessary
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf hba_ops = ((struct modldrv *)(modlp->ml_linkage[0]))->drv_dev_ops;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Provide pointer to SATA dev_ops
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf hba_ops->devo_cb_ops = &sata_cb_ops;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Register SATA HBA with SCSI framework
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((rval = scsi_hba_init(modlp)) != 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG1(SATA_DBG_HBA_IF, NULL,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_hba_init: scsi hba init failed\n", NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (rval);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (0);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/* HBA attach stages */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#define HBA_ATTACH_STAGE_SATA_HBA_INST 1
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#define HBA_ATTACH_STAGE_SCSI_ATTACHED 2
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#define HBA_ATTACH_STAGE_SETUP 4
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#define HBA_ATTACH_STAGE_LINKED 8
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Called from SATA HBA driver's attach routine to attach an instance of
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * the HBA.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * For DDI_ATTACH command:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * sata_hba_inst structure is allocated here and initialized with pointers to
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * SATA framework implementation of required scsi tran functions.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * The scsi_tran's tran_hba_private field is used by SATA Framework to point
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * to the soft structure (sata_hba_inst) allocated by SATA framework for
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * SATA HBA instance related data.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * The scsi_tran's tran_hba_private field is used by SATA framework to
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * store a pointer to per-HBA-instance of sata_hba_inst structure.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * The sata_hba_inst structure is cross-linked to scsi tran structure.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Among other info, a pointer to sata_hba_tran structure is stored in
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * sata_hba_inst. The sata_hba_inst structures for different HBA instances are
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * linked together into the list, pointed to by sata_hba_list.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * On the first HBA instance attach the sata event thread is initialized.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Attachment points are created for all SATA ports of the HBA being attached.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * All HBA instance's SATA ports are probed and type of plugged devices is
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * determined. For each device of a supported type, a target node is created.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * DDI_SUCCESS is returned when attachment process is successful,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * DDI_FAILURE is returned otherwise.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * For DDI_RESUME command:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Not implemented at this time (postponed until phase 2 of the development).
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfint
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_hba_attach(dev_info_t *dip, sata_hba_tran_t *sata_tran,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ddi_attach_cmd_t cmd)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst_t *sata_hba_inst;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsi_hba_tran_t *scsi_tran = NULL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int hba_attach_state = 0;
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw char taskq_name[MAXPATHLEN];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG3(SATA_DBG_HBA_IF, NULL,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_hba_attach: node %s (%s%d)\n",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ddi_node_name(dip), ddi_driver_name(dip),
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ddi_get_instance(dip));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (cmd == DDI_RESUME) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Postponed until phase 2 of the development
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (DDI_FAILURE);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (cmd != DDI_ATTACH) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (DDI_FAILURE);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* cmd == DDI_ATTACH */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_validate_sata_hba_tran(dip, sata_tran) != SATA_SUCCESS) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_LOG_D((NULL, CE_WARN,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_hba_attach: invalid sata_hba_tran"));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (DDI_FAILURE);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Allocate and initialize SCSI tran structure.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * SATA copy of tran_bus_config is provided to create port nodes.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsi_tran = scsi_hba_tran_alloc(dip, SCSI_HBA_CANSLEEP);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (scsi_tran == NULL)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (DDI_FAILURE);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Allocate soft structure for SATA HBA instance.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * There is a separate softstate for each HBA instance.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst = kmem_zalloc(sizeof (struct sata_hba_inst), KM_SLEEP);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ASSERT(sata_hba_inst != NULL); /* this should not fail */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_init(&sata_hba_inst->satahba_mutex, NULL, MUTEX_DRIVER, NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf hba_attach_state |= HBA_ATTACH_STAGE_SATA_HBA_INST;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * scsi_trans's tran_hba_private is used by SATA Framework to point to
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * soft structure allocated by SATA framework for
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * SATA HBA instance related data.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsi_tran->tran_hba_private = sata_hba_inst;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsi_tran->tran_tgt_private = NULL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsi_tran->tran_tgt_init = sata_scsi_tgt_init;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsi_tran->tran_tgt_probe = sata_scsi_tgt_probe;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsi_tran->tran_tgt_free = sata_scsi_tgt_free;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsi_tran->tran_start = sata_scsi_start;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsi_tran->tran_reset = sata_scsi_reset;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsi_tran->tran_abort = sata_scsi_abort;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsi_tran->tran_getcap = sata_scsi_getcap;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsi_tran->tran_setcap = sata_scsi_setcap;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsi_tran->tran_init_pkt = sata_scsi_init_pkt;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsi_tran->tran_destroy_pkt = sata_scsi_destroy_pkt;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsi_tran->tran_dmafree = sata_scsi_dmafree;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsi_tran->tran_sync_pkt = sata_scsi_sync_pkt;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsi_tran->tran_reset_notify = NULL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsi_tran->tran_get_bus_addr = NULL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsi_tran->tran_quiesce = NULL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsi_tran->tran_unquiesce = NULL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsi_tran->tran_bus_reset = NULL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (scsi_hba_attach_setup(dip, sata_tran->sata_tran_hba_dma_attr,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsi_tran, 0) != DDI_SUCCESS) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#ifdef SATA_DEBUG
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cmn_err(CE_WARN, "?SATA: %s%d hba scsi attach failed",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ddi_driver_name(dip), ddi_get_instance(dip));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#endif
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf goto fail;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf hba_attach_state |= HBA_ATTACH_STAGE_SCSI_ATTACHED;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (!ddi_prop_exists(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "sata")) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (ddi_prop_update_int(DDI_DEV_T_NONE, dip,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata", 1) != DDI_PROP_SUCCESS) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_LOG_D((NULL, CE_WARN, "sata_hba_attach: "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "failed to create hba sata prop"));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf goto fail;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Save pointers in hba instance soft state.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst->satahba_scsi_tran = scsi_tran;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst->satahba_tran = sata_tran;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst->satahba_dip = dip;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw /*
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw * Create a task queue to handle emulated commands completion
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw * Use node name, dash, instance number as the queue name.
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw */
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw taskq_name[0] = '\0';
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw (void) strlcat(taskq_name, DEVI(dip)->devi_node_name,
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw sizeof (taskq_name));
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw (void) snprintf(taskq_name + strlen(taskq_name),
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw sizeof (taskq_name) - strlen(taskq_name),
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw "-%d", DEVI(dip)->devi_instance);
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw sata_hba_inst->satahba_taskq = taskq_create(taskq_name, 1,
378b31fa4c69b519b0e53dee7eed925cd397adc1Martin Faltesek minclsyspri, 1, sata_tran->sata_tran_hba_num_cports * 4,
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw TASKQ_DYNAMIC);
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf hba_attach_state |= HBA_ATTACH_STAGE_SETUP;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Create events thread if not created yet.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_event_thread_control(1);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Link this hba instance into the list.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&sata_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw if (sata_hba_list == NULL) {
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw /*
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw * The first instance of HBA is attached.
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw * Set current/active default maximum NCQ/TCQ queue depth for
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw * all SATA devices. It is done here and now, to eliminate the
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw * possibility of the dynamic, programatic modification of the
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw * queue depth via global (and public) sata_max_queue_depth
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw * variable (this would require special handling in HBA drivers)
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw */
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw sata_current_max_qdepth = sata_max_queue_depth;
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw if (sata_current_max_qdepth > 32)
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw sata_current_max_qdepth = 32;
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw else if (sata_current_max_qdepth < 1)
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw sata_current_max_qdepth = 1;
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst->satahba_next = NULL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst->satahba_prev = sata_hba_list_tail;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_hba_list == NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_list = sata_hba_inst;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_hba_list_tail != NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_list_tail->satahba_next = sata_hba_inst;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_list_tail = sata_hba_inst;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&sata_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf hba_attach_state |= HBA_ATTACH_STAGE_LINKED;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Create SATA HBA devctl minor node for sata_hba_open, close, ioctl
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * SATA HBA driver should not use its own open/close entry points.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Make sure that instance number doesn't overflow
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * when forming minor numbers.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ASSERT(ddi_get_instance(dip) <= (L_MAXMIN >> INST_MINOR_SHIFT));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (ddi_create_minor_node(dip, "devctl", S_IFCHR,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf INST2DEVCTL(ddi_get_instance(dip)),
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf DDI_NT_SATA_NEXUS, 0) != DDI_SUCCESS) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#ifdef SATA_DEBUG
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cmn_err(CE_WARN, "sata_hba_attach: "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "cannot create devctl minor node");
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#endif
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf goto fail;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Set-up kstats here, if necessary.
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik * (postponed until future phase of the development).
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik /*
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik * Indicate that HBA is attached. This will enable events processing
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik * for this HBA.
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik */
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik sata_hba_inst->satahba_attached = 1;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Probe controller ports. This operation will describe a current
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * controller/port/multipliers/device configuration and will create
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * attachment points.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * We may end-up with just a controller with no devices attached.
6ed1276fb5fe78fb1cce38682748a830ef8bd157pawelw * For the ports with a supported device attached, device target nodes
6ed1276fb5fe78fb1cce38682748a830ef8bd157pawelw * are created and devices are initialized.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_probe_ports(sata_hba_inst);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (DDI_SUCCESS);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlffail:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (hba_attach_state & HBA_ATTACH_STAGE_LINKED) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (void) sata_remove_hba_instance(dip);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_hba_list == NULL)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_event_thread_control(0);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw if (hba_attach_state & HBA_ATTACH_STAGE_SETUP) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (void) ddi_prop_remove(DDI_DEV_T_ANY, dip, "sata");
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw taskq_destroy(sata_hba_inst->satahba_taskq);
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (hba_attach_state & HBA_ATTACH_STAGE_SCSI_ATTACHED)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (void) scsi_hba_detach(dip);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (hba_attach_state & HBA_ATTACH_STAGE_SATA_HBA_INST) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_destroy(&sata_hba_inst->satahba_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf kmem_free((void *)sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sizeof (struct sata_hba_inst));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsi_hba_tran_free(scsi_tran);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_log(NULL, CE_WARN, "?SATA: %s%d hba attach failed",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ddi_driver_name(dip), ddi_get_instance(dip));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (DDI_FAILURE);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Called by SATA HBA from to detach an instance of the driver.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * For DDI_DETACH command:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Free local structures allocated for SATA HBA instance during
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * sata_hba_attach processing.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Returns DDI_SUCCESS when HBA was detached, DDI_FAILURE otherwise.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * For DDI_SUSPEND command:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Not implemented at this time (postponed until phase 2 of the development)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Returnd DDI_SUCCESS.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * When the last HBA instance is detached, the event daemon is terminated.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * NOTE: Port multiplier is supported.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfint
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_hba_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf dev_info_t *tdip;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst_t *sata_hba_inst;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsi_hba_tran_t *scsi_hba_tran;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_cport_info_t *cportinfo;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_pmult_info_t *pminfo;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_drive_info_t *sdinfo;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device_t sdevice;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang int ncport, npmport;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG3(SATA_DBG_HBA_IF, NULL, "sata_hba_detach: node %s (%s%d)\n",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ddi_node_name(dip), ddi_driver_name(dip), ddi_get_instance(dip));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf switch (cmd) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case DDI_DETACH:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((scsi_hba_tran = ddi_get_driver_private(dip)) == NULL)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (DDI_FAILURE);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst = scsi_hba_tran->tran_hba_private;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_hba_inst == NULL)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (DDI_FAILURE);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (scsi_hba_detach(dip) == DDI_FAILURE) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst->satahba_attached = 1;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (DDI_FAILURE);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Free all target nodes - at this point
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * devices should be at least offlined
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * otherwise scsi_hba_detach() should not be called.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf for (ncport = 0; ncport < SATA_NUM_CPORTS(sata_hba_inst);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ncport++) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo = SATA_CPORT_INFO(sata_hba_inst, ncport);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (cportinfo->cport_dev_type != SATA_DTYPE_PMULT) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo = SATA_CPORTINFO_DRV_INFO(cportinfo);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sdinfo != NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf tdip = sata_get_target_dip(dip,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang ncport, 0);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (tdip != NULL) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (ndi_devi_offline(tdip,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang NDI_DEVI_REMOVE) !=
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang NDI_SUCCESS) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_LOG_D((
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang CE_WARN,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "sata_hba_detach: "
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "Target node not "
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "removed !"));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang return (DDI_FAILURE);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang } else { /* SATA_DTYPE_PMULT */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&cportinfo->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pminfo = SATA_CPORTINFO_PMULT_INFO(cportinfo);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (pminfo == NULL) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_LOG_D((sata_hba_inst, CE_WARN,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "sata_hba_detach: Port multiplier "
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "not ready yet!"));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&cportinfo->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang return (DDI_FAILURE);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Detach would fail if removal of any of the
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * target nodes is failed - albeit in that
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * case some of them may have been removed.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang for (npmport = 0; npmport < SATA_NUM_PMPORTS(
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_hba_inst, ncport); npmport++) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang tdip = sata_get_target_dip(dip, ncport,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang npmport);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (tdip != NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (ndi_devi_offline(tdip,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf NDI_DEVI_REMOVE) !=
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf NDI_SUCCESS) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_LOG_D((
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf CE_WARN,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_hba_detach: "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "Target node not "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "removed !"));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&cportinfo->
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (DDI_FAILURE);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&cportinfo->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Disable sata event daemon processing for this HBA
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst->satahba_attached = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Remove event daemon thread, if it is last HBA instance.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&sata_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_hba_list->satahba_next == NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&sata_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_event_thread_control(0);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&sata_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&sata_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Remove this HBA instance from the HBA list */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_remove_hba_instance(dip);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * At this point there should be no target nodes attached.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Detach and destroy device and port info structures.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf for (ncport = 0; ncport < SATA_NUM_CPORTS(sata_hba_inst);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ncport++) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo = SATA_CPORT_INFO(sata_hba_inst, ncport);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (cportinfo->cport_dev_type != SATA_DTYPE_PMULT) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo->cport_devp.cport_sata_drive;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sdinfo != NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Release device structure */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf kmem_free(sdinfo,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sizeof (sata_drive_info_t));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Release cport info */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_destroy(&cportinfo->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf kmem_free(cportinfo,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sizeof (sata_cport_info_t));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang } else { /* SATA_DTYPE_PMULT */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sdevice.satadev_addr.cport = (uint8_t)ncport;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sdevice.satadev_addr.qual = SATA_ADDR_PMULT;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_free_pmult(sata_hba_inst, &sdevice);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsi_hba_tran_free(sata_hba_inst->satahba_scsi_tran);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw (void) ddi_prop_remove(DDI_DEV_T_ANY, dip, "sata");
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw taskq_destroy(sata_hba_inst->satahba_taskq);
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_destroy(&sata_hba_inst->satahba_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf kmem_free((void *)sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sizeof (struct sata_hba_inst));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (DDI_SUCCESS);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case DDI_SUSPEND:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Postponed until phase 2
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (DDI_FAILURE);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf default:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (DDI_FAILURE);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Called by an HBA drive from _fini() routine.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Unregisters SATA HBA instance/SATA framework pair from the scsi framework.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfvoid
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_hba_fini(struct modlinkage *modlp)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG1(SATA_DBG_HBA_IF, NULL,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_hba_fini: name %s\n",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ((struct modldrv *)(modlp->ml_linkage[0]))->drv_linkinfo);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsi_hba_fini(modlp);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Default open and close routine for sata_hba framework.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Open devctl node.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Returns:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * 0 if node was open successfully, error code otherwise.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_hba_open(dev_t *devp, int flags, int otyp, cred_t *credp)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#ifndef __lock_lint
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf _NOTE(ARGUNUSED(credp))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#endif
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int rv = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf dev_info_t *dip;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsi_hba_tran_t *scsi_hba_tran;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst_t *sata_hba_inst;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG1(SATA_DBG_IOCTL_IF, NULL, "sata_hba_open: entered", NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (otyp != OTYP_CHR)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (EINVAL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf dip = sata_devt_to_devinfo(*devp);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (dip == NULL)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (ENXIO);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((scsi_hba_tran = ddi_get_driver_private(dip)) == NULL)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (ENXIO);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst = scsi_hba_tran->tran_hba_private;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_hba_inst == NULL || sata_hba_inst->satahba_attached == 0)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (ENXIO);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&sata_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (flags & FEXCL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_hba_inst->satahba_open_flag != 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rv = EBUSY;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst->satahba_open_flag =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_DEVCTL_EXOPENED;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_hba_inst->satahba_open_flag == SATA_DEVCTL_EXOPENED) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rv = EBUSY;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst->satahba_open_flag =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_DEVCTL_SOPENED;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&sata_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (rv);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Close devctl node.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Returns:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * 0 if node was closed successfully, error code otherwise.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_hba_close(dev_t dev, int flag, int otyp, cred_t *credp)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#ifndef __lock_lint
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf _NOTE(ARGUNUSED(credp))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf _NOTE(ARGUNUSED(flag))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#endif
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf dev_info_t *dip;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsi_hba_tran_t *scsi_hba_tran;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst_t *sata_hba_inst;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG1(SATA_DBG_IOCTL_IF, NULL, "sata_hba_close: entered", NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (otyp != OTYP_CHR)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (EINVAL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf dip = sata_devt_to_devinfo(dev);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (dip == NULL)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (ENXIO);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((scsi_hba_tran = ddi_get_driver_private(dip)) == NULL)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (ENXIO);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst = scsi_hba_tran->tran_hba_private;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_hba_inst == NULL || sata_hba_inst->satahba_attached == 0)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (ENXIO);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&sata_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst->satahba_open_flag = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&sata_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (0);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Standard IOCTL commands for SATA hotplugging.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Implemented DEVCTL_AP commands:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * DEVCTL_AP_CONNECT
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * DEVCTL_AP_DISCONNECT
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * DEVCTL_AP_CONFIGURE
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * DEVCTL_UNCONFIGURE
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * DEVCTL_AP_CONTROL
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Commands passed to default ndi ioctl handler:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * DEVCTL_DEVICE_GETSTATE
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * DEVCTL_DEVICE_ONLINE
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * DEVCTL_DEVICE_OFFLINE
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * DEVCTL_DEVICE_REMOVE
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * DEVCTL_DEVICE_INSERT
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * DEVCTL_BUS_GETSTATE
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * All other cmds are passed to HBA if it provide ioctl handler, or failed
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * if not.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Returns:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * 0 if successful,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * error code if operation failed.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Port Multiplier support is supported now.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * NOTE: qual should be SATA_ADDR_DCPORT or SATA_ADDR_DPMPORT
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_hba_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int *rvalp)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#ifndef __lock_lint
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf _NOTE(ARGUNUSED(credp))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf _NOTE(ARGUNUSED(rvalp))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#endif
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int rv = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int32_t comp_port = -1;
c75976d12071ddd21443266260066ba036671682pawelw dev_info_t *dip;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf devctl_ap_state_t ap_state;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf struct devctl_iocdata *dcp = NULL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsi_hba_tran_t *scsi_hba_tran;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst_t *sata_hba_inst;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device_t sata_device;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_cport_info_t *cportinfo;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int cport, pmport, qual;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int rval = SATA_SUCCESS;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf dip = sata_devt_to_devinfo(dev);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (dip == NULL)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (ENXIO);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((scsi_hba_tran = ddi_get_driver_private(dip)) == NULL)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (ENXIO);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst = scsi_hba_tran->tran_hba_private;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_hba_inst == NULL)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (ENXIO);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_hba_inst->satahba_tran == NULL)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (ENXIO);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf switch (cmd) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case DEVCTL_DEVICE_GETSTATE:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case DEVCTL_DEVICE_ONLINE:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case DEVCTL_DEVICE_OFFLINE:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case DEVCTL_DEVICE_REMOVE:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case DEVCTL_BUS_GETSTATE:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * There may be more cases that we want to pass to default
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * handler rather than fail them.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (ndi_devctl_ioctl(dip, cmd, arg, mode, 0));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* read devctl ioctl data */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (cmd != DEVCTL_AP_CONTROL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (ndi_dc_allochdl((void *)arg, &dcp) != NDI_SUCCESS)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (EFAULT);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((comp_port = sata_get_port_num(sata_hba_inst, dcp)) ==
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf -1) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (dcp)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ndi_dc_freehdl(dcp);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (EINVAL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * According to SCSI_TO_SATA_ADDR_QUAL, qual should be either
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * SATA_ADDR_DCPORT or SATA_ADDR_DPMPORT.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport = SCSI_TO_SATA_CPORT(comp_port);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf pmport = SCSI_TO_SATA_PMPORT(comp_port);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang qual = SCSI_TO_SATA_ADDR_QUAL(comp_port);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_validate_sata_address(sata_hba_inst, cport, pmport,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf qual) != 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ndi_dc_freehdl(dcp);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (EINVAL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo = SATA_CPORT_INFO(sata_hba_inst, cport);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&SATA_CPORT_INFO(sata_hba_inst, cport)->
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (cportinfo->cport_event_flags & SATA_EVNT_LOCK_PORT_BUSY) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Cannot process ioctl request now. Come back later.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, cport)->
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ndi_dc_freehdl(dcp);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (EBUSY);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Block event processing for this port */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo->cport_event_flags |= SATA_APCTL_LOCK_PORT_BUSY;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, cport)->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_addr.cport = cport;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_addr.pmport = pmport;
c75976d12071ddd21443266260066ba036671682pawelw sata_device.satadev_addr.qual = qual;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_rev = SATA_DEVICE_REV;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf switch (cmd) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case DEVCTL_AP_DISCONNECT:
c75976d12071ddd21443266260066ba036671682pawelw
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Normally, cfgadm sata plugin will try to offline
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * (unconfigure) device before this request. Nevertheless,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * if a device is still configured, we need to
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * attempt to offline and unconfigure device first, and we will
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * deactivate the port regardless of the unconfigure
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * operation results.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw */
c75976d12071ddd21443266260066ba036671682pawelw rv = sata_ioctl_disconnect(sata_hba_inst, &sata_device);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case DEVCTL_AP_UNCONFIGURE:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * The unconfigure operation uses generic nexus operation to
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * offline a device. It leaves a target device node attached.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * and obviously sata_drive_info attached as well, because
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * from the hardware point of view nothing has changed.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
c75976d12071ddd21443266260066ba036671682pawelw rv = sata_ioctl_unconfigure(sata_hba_inst, &sata_device);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case DEVCTL_AP_CONNECT:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * The sata cfgadm pluging will invoke this operation only if
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * port was found in the disconnect state (failed state
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * is also treated as the disconnected state).
c75976d12071ddd21443266260066ba036671682pawelw * If port activation is successful and a device is found
c75976d12071ddd21443266260066ba036671682pawelw * attached to the port, the initialization sequence is
c75976d12071ddd21443266260066ba036671682pawelw * executed to probe the port and attach
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * a device structure to a port structure. The device is not
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * set in configured state (system-wise) by this operation.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
c75976d12071ddd21443266260066ba036671682pawelw rv = sata_ioctl_connect(sata_hba_inst, &sata_device);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case DEVCTL_AP_CONFIGURE:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * A port may be in an active or shutdown state.
c75976d12071ddd21443266260066ba036671682pawelw * If port is in a failed state, operation is aborted.
c75976d12071ddd21443266260066ba036671682pawelw * If a port is in a shutdown state, sata_tran_port_activate()
c75976d12071ddd21443266260066ba036671682pawelw * is invoked prior to any other operation.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
c75976d12071ddd21443266260066ba036671682pawelw * Onlining the device involves creating a new target node.
c75976d12071ddd21443266260066ba036671682pawelw * If there is an old target node present (belonging to
c75976d12071ddd21443266260066ba036671682pawelw * previously removed device), the operation is aborted - the
c75976d12071ddd21443266260066ba036671682pawelw * old node has to be released and removed before configure
c75976d12071ddd21443266260066ba036671682pawelw * operation is attempted.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
c75976d12071ddd21443266260066ba036671682pawelw rv = sata_ioctl_configure(sata_hba_inst, &sata_device);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case DEVCTL_AP_GETSTATE:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_cfgadm_state(sata_hba_inst, comp_port, &ap_state);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ap_state.ap_last_change = (time_t)-1;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ap_state.ap_error_code = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ap_state.ap_in_transition = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Copy the return AP-state information to the user space */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (ndi_dc_return_ap_state(&ap_state, dcp) != NDI_SUCCESS) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rv = EFAULT;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case DEVCTL_AP_CONTROL:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Generic devctl for hardware specific functionality
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_ioctl_data_t ioc;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ASSERT(dcp == NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Copy in user ioctl data first */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#ifdef _MULTI_DATAMODEL
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (ddi_model_convert_from(mode & FMODELS) ==
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf DDI_MODEL_ILP32) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_ioctl_data_32_t ioc32;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (ddi_copyin((void *)arg, (void *)&ioc32,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sizeof (ioc32), mode) != 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rv = EFAULT;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ioc.cmd = (uint_t)ioc32.cmd;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ioc.port = (uint_t)ioc32.port;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ioc.get_size = (uint_t)ioc32.get_size;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ioc.buf = (caddr_t)(uintptr_t)ioc32.buf;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ioc.bufsiz = (uint_t)ioc32.bufsiz;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ioc.misc_arg = (uint_t)ioc32.misc_arg;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#endif /* _MULTI_DATAMODEL */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (ddi_copyin((void *)arg, (void *)&ioc, sizeof (ioc),
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mode) != 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (EFAULT);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG2(SATA_DBG_IOCTL_IF, sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_hba_ioctl: DEVCTL_AP_CONTROL "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "cmd 0x%x, port 0x%x", ioc.cmd, ioc.port);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * To avoid BE/LE and 32/64 issues, a get_size always returns
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * a 32-bit number.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (ioc.get_size != 0 && ioc.bufsiz != (sizeof (uint32_t))) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (EINVAL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* validate address */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport = SCSI_TO_SATA_CPORT(ioc.port);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf pmport = SCSI_TO_SATA_PMPORT(ioc.port);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf qual = SCSI_TO_SATA_ADDR_QUAL(ioc.port);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATADBG3(SATA_DBG_IOCTL_IF, sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "sata_hba_ioctl: target port is %d:%d (%d)",
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cport, pmport, qual);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_validate_sata_address(sata_hba_inst, cport,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf pmport, qual) != 0)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (EINVAL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo = SATA_CPORT_INFO(sata_hba_inst, cport);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&SATA_CPORT_INFO(sata_hba_inst, cport)->
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Is the port locked by event processing daemon ? */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (cportinfo->cport_event_flags & SATA_EVNT_LOCK_PORT_BUSY) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Cannot process ioctl request now. Come back later
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, cport)->
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (EBUSY);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Block event processing for this port */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo->cport_event_flags |= SATA_APCTL_LOCK_PORT_BUSY;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, cport)->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_addr.cport = cport;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_addr.pmport = pmport;
c75976d12071ddd21443266260066ba036671682pawelw sata_device.satadev_addr.qual = qual;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_rev = SATA_DEVICE_REV;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf switch (ioc.cmd) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SATA_CFGA_RESET_PORT:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
c75976d12071ddd21443266260066ba036671682pawelw * There is no protection for configured device.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
c75976d12071ddd21443266260066ba036671682pawelw rv = sata_ioctl_reset_port(sata_hba_inst, &sata_device);
c75976d12071ddd21443266260066ba036671682pawelw break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
c75976d12071ddd21443266260066ba036671682pawelw case SATA_CFGA_RESET_DEVICE:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
c75976d12071ddd21443266260066ba036671682pawelw * There is no protection for configured device.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
c75976d12071ddd21443266260066ba036671682pawelw rv = sata_ioctl_reset_device(sata_hba_inst,
c75976d12071ddd21443266260066ba036671682pawelw &sata_device);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
c75976d12071ddd21443266260066ba036671682pawelw case SATA_CFGA_RESET_ALL:
c75976d12071ddd21443266260066ba036671682pawelw /*
c75976d12071ddd21443266260066ba036671682pawelw * There is no protection for configured devices.
c75976d12071ddd21443266260066ba036671682pawelw */
c75976d12071ddd21443266260066ba036671682pawelw rv = sata_ioctl_reset_all(sata_hba_inst);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
c75976d12071ddd21443266260066ba036671682pawelw * We return here, because common return is for
c75976d12071ddd21443266260066ba036671682pawelw * a single port operation - we have already unlocked
c75976d12071ddd21443266260066ba036671682pawelw * all ports and no dc handle was allocated.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
c75976d12071ddd21443266260066ba036671682pawelw return (rv);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
c75976d12071ddd21443266260066ba036671682pawelw case SATA_CFGA_PORT_DEACTIVATE:
c75976d12071ddd21443266260066ba036671682pawelw /*
c75976d12071ddd21443266260066ba036671682pawelw * Arbitrarily unconfigure attached device, if any.
c75976d12071ddd21443266260066ba036671682pawelw * Even if the unconfigure fails, proceed with the
c75976d12071ddd21443266260066ba036671682pawelw * port deactivation.
c75976d12071ddd21443266260066ba036671682pawelw */
c75976d12071ddd21443266260066ba036671682pawelw rv = sata_ioctl_deactivate(sata_hba_inst, &sata_device);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
c75976d12071ddd21443266260066ba036671682pawelw break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
c75976d12071ddd21443266260066ba036671682pawelw case SATA_CFGA_PORT_ACTIVATE:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
c75976d12071ddd21443266260066ba036671682pawelw rv = sata_ioctl_activate(sata_hba_inst, &sata_device);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
c75976d12071ddd21443266260066ba036671682pawelw case SATA_CFGA_PORT_SELF_TEST:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
c75976d12071ddd21443266260066ba036671682pawelw rv = sata_ioctl_port_self_test(sata_hba_inst,
c75976d12071ddd21443266260066ba036671682pawelw &sata_device);
c75976d12071ddd21443266260066ba036671682pawelw break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
c75976d12071ddd21443266260066ba036671682pawelw case SATA_CFGA_GET_DEVICE_PATH:
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
c75976d12071ddd21443266260066ba036671682pawelw rv = sata_ioctl_get_device_path(sata_hba_inst,
c75976d12071ddd21443266260066ba036671682pawelw &sata_device, &ioc, mode);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
c75976d12071ddd21443266260066ba036671682pawelw case SATA_CFGA_GET_AP_TYPE:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
c75976d12071ddd21443266260066ba036671682pawelw rv = sata_ioctl_get_ap_type(sata_hba_inst,
c75976d12071ddd21443266260066ba036671682pawelw &sata_device, &ioc, mode);
c75976d12071ddd21443266260066ba036671682pawelw break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
c75976d12071ddd21443266260066ba036671682pawelw case SATA_CFGA_GET_MODEL_INFO:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
c75976d12071ddd21443266260066ba036671682pawelw rv = sata_ioctl_get_model_info(sata_hba_inst,
c75976d12071ddd21443266260066ba036671682pawelw &sata_device, &ioc, mode);
c75976d12071ddd21443266260066ba036671682pawelw break;
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw
c75976d12071ddd21443266260066ba036671682pawelw case SATA_CFGA_GET_REVFIRMWARE_INFO:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
c75976d12071ddd21443266260066ba036671682pawelw rv = sata_ioctl_get_revfirmware_info(sata_hba_inst,
c75976d12071ddd21443266260066ba036671682pawelw &sata_device, &ioc, mode);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
c75976d12071ddd21443266260066ba036671682pawelw case SATA_CFGA_GET_SERIALNUMBER_INFO:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
c75976d12071ddd21443266260066ba036671682pawelw rv = sata_ioctl_get_serialnumber_info(sata_hba_inst,
c75976d12071ddd21443266260066ba036671682pawelw &sata_device, &ioc, mode);
c75976d12071ddd21443266260066ba036671682pawelw break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
c75976d12071ddd21443266260066ba036671682pawelw default:
c75976d12071ddd21443266260066ba036671682pawelw rv = EINVAL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
c75976d12071ddd21443266260066ba036671682pawelw } /* End of DEVCTL_AP_CONTROL cmd switch */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
c75976d12071ddd21443266260066ba036671682pawelw break;
c75976d12071ddd21443266260066ba036671682pawelw }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
c75976d12071ddd21443266260066ba036671682pawelw default:
c75976d12071ddd21443266260066ba036671682pawelw {
c75976d12071ddd21443266260066ba036671682pawelw /*
c75976d12071ddd21443266260066ba036671682pawelw * If we got here, we got an IOCTL that SATA HBA Framework
c75976d12071ddd21443266260066ba036671682pawelw * does not recognize. Pass ioctl to HBA driver, in case
c75976d12071ddd21443266260066ba036671682pawelw * it could process it.
c75976d12071ddd21443266260066ba036671682pawelw */
c75976d12071ddd21443266260066ba036671682pawelw sata_hba_tran_t *sata_tran = sata_hba_inst->satahba_tran;
c75976d12071ddd21443266260066ba036671682pawelw dev_info_t *mydip = SATA_DIP(sata_hba_inst);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
c75976d12071ddd21443266260066ba036671682pawelw SATADBG1(SATA_DBG_IOCTL_IF, sata_hba_inst,
c75976d12071ddd21443266260066ba036671682pawelw "IOCTL 0x%2x not supported in SATA framework, "
c75976d12071ddd21443266260066ba036671682pawelw "passthrough to HBA", cmd);
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw if (sata_tran->sata_tran_ioctl == NULL) {
c75976d12071ddd21443266260066ba036671682pawelw rv = EINVAL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
c75976d12071ddd21443266260066ba036671682pawelw rval = (*sata_tran->sata_tran_ioctl)(mydip, cmd, arg);
c75976d12071ddd21443266260066ba036671682pawelw if (rval != 0) {
c75976d12071ddd21443266260066ba036671682pawelw SATADBG1(SATA_DBG_IOCTL_IF, sata_hba_inst,
c75976d12071ddd21443266260066ba036671682pawelw "IOCTL 0x%2x failed in HBA", cmd);
c75976d12071ddd21443266260066ba036671682pawelw rv = rval;
c75976d12071ddd21443266260066ba036671682pawelw }
c75976d12071ddd21443266260066ba036671682pawelw break;
c75976d12071ddd21443266260066ba036671682pawelw }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
c75976d12071ddd21443266260066ba036671682pawelw } /* End of main IOCTL switch */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
c75976d12071ddd21443266260066ba036671682pawelw if (dcp) {
c75976d12071ddd21443266260066ba036671682pawelw ndi_dc_freehdl(dcp);
c75976d12071ddd21443266260066ba036671682pawelw }
c75976d12071ddd21443266260066ba036671682pawelw mutex_enter(&SATA_CPORT_INFO(sata_hba_inst, cport)->cport_mutex);
c75976d12071ddd21443266260066ba036671682pawelw cportinfo->cport_event_flags &= ~SATA_APCTL_LOCK_PORT_BUSY;
c75976d12071ddd21443266260066ba036671682pawelw mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, cport)->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
c75976d12071ddd21443266260066ba036671682pawelw return (rv);
c75976d12071ddd21443266260066ba036671682pawelw}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
c75976d12071ddd21443266260066ba036671682pawelw/*
c75976d12071ddd21443266260066ba036671682pawelw * Create error retrieval sata packet
c75976d12071ddd21443266260066ba036671682pawelw *
c75976d12071ddd21443266260066ba036671682pawelw * A sata packet is allocated and set-up to contain specified error retrieval
c75976d12071ddd21443266260066ba036671682pawelw * command and appropriate dma-able data buffer.
c75976d12071ddd21443266260066ba036671682pawelw * No association with any scsi packet is made and no callback routine is
c75976d12071ddd21443266260066ba036671682pawelw * specified.
c75976d12071ddd21443266260066ba036671682pawelw *
c75976d12071ddd21443266260066ba036671682pawelw * Returns a pointer to sata packet upon successfull packet creation.
c75976d12071ddd21443266260066ba036671682pawelw * Returns NULL, if packet cannot be created.
c75976d12071ddd21443266260066ba036671682pawelw */
c75976d12071ddd21443266260066ba036671682pawelwsata_pkt_t *
c75976d12071ddd21443266260066ba036671682pawelwsata_get_error_retrieval_pkt(dev_info_t *dip, sata_device_t *sata_device,
c75976d12071ddd21443266260066ba036671682pawelw int pkt_type)
c75976d12071ddd21443266260066ba036671682pawelw{
c75976d12071ddd21443266260066ba036671682pawelw sata_hba_inst_t *sata_hba_inst;
c75976d12071ddd21443266260066ba036671682pawelw sata_pkt_txlate_t *spx;
c75976d12071ddd21443266260066ba036671682pawelw sata_pkt_t *spkt;
c75976d12071ddd21443266260066ba036671682pawelw sata_drive_info_t *sdinfo;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_enter(&sata_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown for (sata_hba_inst = sata_hba_list; sata_hba_inst != NULL;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_hba_inst = sata_hba_inst->satahba_next) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (SATA_DIP(sata_hba_inst) == dip)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown break;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&sata_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ASSERT(sata_hba_inst != NULL);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo = sata_get_device_info(sata_hba_inst, sata_device);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sdinfo == NULL) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_log(sata_hba_inst, CE_WARN,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "sata: error recovery request for non-attached device at "
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "cport %d", sata_device->satadev_addr.cport);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (NULL);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx = kmem_zalloc(sizeof (sata_pkt_txlate_t), KM_SLEEP);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_sata_hba_inst = sata_hba_inst;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_scsi_pkt = NULL; /* No scsi pkt involved */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt = sata_pkt_alloc(spx, NULL);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (spkt == NULL) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown kmem_free(spx, sizeof (sata_pkt_txlate_t));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (NULL);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* address is needed now */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_device.satadev_addr = sata_device->satadev_addr;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown switch (pkt_type) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown case SATA_ERR_RETR_PKT_TYPE_NCQ:
82263d52a84b4a969aa53f8ededddff841646ad9yt if (sata_ncq_err_ret_cmd_setup(spx, sdinfo) == SATA_SUCCESS)
82263d52a84b4a969aa53f8ededddff841646ad9yt return (spkt);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown break;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown case SATA_ERR_RETR_PKT_TYPE_ATAPI:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sata_atapi_err_ret_cmd_setup(spx, sdinfo) == SATA_SUCCESS)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (spkt);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown break;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown default:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown break;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_pkt_free(spx);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown kmem_free(spx, sizeof (sata_pkt_txlate_t));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (NULL);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown}
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown/*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Free error retrieval sata packet
2038334ab26baaa43c9083f35def041511c3cc1fUnknown *
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Free sata packet and any associated resources allocated previously by
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * sata_get_error_retrieval_pkt().
2038334ab26baaa43c9083f35def041511c3cc1fUnknown *
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Void return.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknownvoid
2038334ab26baaa43c9083f35def041511c3cc1fUnknownsata_free_error_retrieval_pkt(sata_pkt_t *sata_pkt)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown{
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_pkt_txlate_t *spx =
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (sata_pkt_txlate_t *)sata_pkt->satapkt_framework_private;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ASSERT(sata_pkt != NULL);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_free_local_buffer(spx);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_pkt_free(spx);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown kmem_free(spx, sizeof (sata_pkt_txlate_t));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang/*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Create READ PORT MULTIPLIER and WRITE PORT MULTIPLIER sata packet
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang *
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * No association with any scsi packet is made and no callback routine is
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * specified.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang *
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Returns a pointer to sata packet upon successfull packet creation.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Returns NULL, if packet cannot be created.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang *
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * NOTE: Input/Output value includes 64 bits accoring to SATA Spec 2.6,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * only lower 32 bits are available currently.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhangsata_pkt_t *
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhangsata_get_rdwr_pmult_pkt(dev_info_t *dip, sata_device_t *sd,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang uint8_t regn, uint32_t regv, uint32_t type)
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang{
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_hba_inst_t *sata_hba_inst;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_pkt_txlate_t *spx;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_pkt_t *spkt;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_cmd_t *scmd;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Only READ/WRITE commands are accepted. */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang ASSERT(type == SATA_RDWR_PMULT_PKT_TYPE_READ ||
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang type == SATA_RDWR_PMULT_PKT_TYPE_WRITE);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&sata_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang for (sata_hba_inst = sata_hba_list; sata_hba_inst != NULL;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_hba_inst = sata_hba_inst->satahba_next) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (SATA_DIP(sata_hba_inst) == dip)
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang break;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&sata_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang ASSERT(sata_hba_inst != NULL);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang spx = kmem_zalloc(sizeof (sata_pkt_txlate_t), KM_SLEEP);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang spx->txlt_sata_hba_inst = sata_hba_inst;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang spx->txlt_scsi_pkt = NULL; /* No scsi pkt involved */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang spkt = sata_pkt_alloc(spx, SLEEP_FUNC);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (spkt == NULL) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang kmem_free(spx, sizeof (sata_pkt_txlate_t));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang return (NULL);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * NOTE: We need to send this command to the port multiplier,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * that means send to SATA_PMULT_HOSTPORT(0xf) pmport
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang *
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * sata_device contains the address of actual target device, and the
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * pmport number in the command comes from the sata_device structure.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang spkt->satapkt_device.satadev_addr = sd->satadev_addr;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang spkt->satapkt_device.satadev_addr.pmport = SATA_PMULT_HOSTPORT;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang spkt->satapkt_device.satadev_addr.qual = SATA_ADDR_PMULT;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Fill sata_pkt */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang spkt->satapkt_op_mode = SATA_OPMODE_SYNCH | SATA_OPMODE_POLLING;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang spkt->satapkt_comp = NULL; /* Synchronous mode, no callback */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang spkt->satapkt_time = 10; /* Timeout 10s */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Build READ PORT MULTIPLIER cmd in the sata_pkt */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang scmd = &spkt->satapkt_cmd;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang scmd->satacmd_features_reg = regn & 0xff;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang scmd->satacmd_features_reg_ext = (regn >> 8) & 0xff;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang scmd->satacmd_device_reg = sd->satadev_addr.pmport;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang scmd->satacmd_addr_type = 0; /* N/A */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang scmd->satacmd_flags.sata_ignore_dev_reset = B_TRUE;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (type == SATA_RDWR_PMULT_PKT_TYPE_READ) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang scmd->satacmd_cmd_reg = SATAC_READ_PORTMULT;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang scmd->satacmd_flags.sata_data_direction = SATA_DIR_READ;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang scmd->satacmd_flags.sata_special_regs = 1;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang scmd->satacmd_flags.sata_copy_out_lba_high_lsb = 1;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang scmd->satacmd_flags.sata_copy_out_lba_mid_lsb = 1;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang scmd->satacmd_flags.sata_copy_out_lba_low_lsb = 1;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang scmd->satacmd_flags.sata_copy_out_sec_count_lsb = 1;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang } else if (type == SATA_RDWR_PMULT_PKT_TYPE_WRITE) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang scmd->satacmd_cmd_reg = SATAC_WRITE_PORTMULT;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang scmd->satacmd_flags.sata_data_direction = SATA_DIR_WRITE;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang scmd->satacmd_sec_count_lsb = regv & 0xff;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang scmd->satacmd_lba_low_lsb = regv >> 8 & 0xff;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang scmd->satacmd_lba_mid_lsb = regv >> 16 & 0xff;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang scmd->satacmd_lba_high_lsb = regv >> 24 & 0xff;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang return (spkt);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang}
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang/*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Free sata packet and any associated resources allocated previously by
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * sata_get_rdwr_pmult_pkt().
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang *
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Void return.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhangvoid
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhangsata_free_rdwr_pmult_pkt(sata_pkt_t *sata_pkt)
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang{
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_pkt_txlate_t *spx =
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (sata_pkt_txlate_t *)sata_pkt->satapkt_framework_private;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Free allocated resources */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_pkt_free(spx);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang kmem_free(spx, sizeof (sata_pkt_txlate_t));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang}
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang/*
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang * Register a port multiplier to framework.
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang * 1) Store the GSCR values in the previous allocated pmult_info strctures.
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang * 2) Search in the blacklist and update the number of the device ports of the
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang * port multiplier.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang *
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang * Void return.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhangvoid
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhangsata_register_pmult(dev_info_t *dip, sata_device_t *sd, sata_pmult_gscr_t *sg)
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang{
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang sata_hba_inst_t *sata_hba_inst = NULL;
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang sata_pmult_info_t *pmultinfo;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_pmult_bl_t *blp;
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang int cport = sd->satadev_addr.cport;
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang mutex_enter(&sata_mutex);
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang for (sata_hba_inst = sata_hba_list; sata_hba_inst != NULL;
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang sata_hba_inst = sata_hba_inst->satahba_next) {
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang if (SATA_DIP(sata_hba_inst) == dip)
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang if (sata_hba_inst->satahba_attached == 1)
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang break;
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang }
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang mutex_exit(&sata_mutex);
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang /* HBA not attached? */
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang if (sata_hba_inst == NULL)
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang return;
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang /* Number of pmports */
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang sd->satadev_add_info = sg->gscr2 & SATA_PMULT_PORTNUM_MASK;
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang /* Check the blacklist */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang for (blp = sata_pmult_blacklist; blp->bl_gscr0; blp++) {
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang if (sg->gscr0 != blp->bl_gscr0 && blp->bl_gscr0)
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang continue;
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang if (sg->gscr1 != blp->bl_gscr1 && blp->bl_gscr1)
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang continue;
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang if (sg->gscr2 != blp->bl_gscr2 && blp->bl_gscr2)
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang continue;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cmn_err(CE_WARN, "!Port multiplier is on the blacklist.");
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sd->satadev_add_info = blp->bl_flags;
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang break;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang /* Register the port multiplier GSCR */
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang mutex_enter(&(SATA_CPORT_MUTEX(sata_hba_inst, cport)));
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang pmultinfo = SATA_PMULT_INFO(sata_hba_inst, cport);
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang if (pmultinfo != NULL) {
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang pmultinfo->pmult_gscr = *sg;
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang pmultinfo->pmult_num_dev_ports =
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang sd->satadev_add_info & SATA_PMULT_PORTNUM_MASK;
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang SATADBG1(SATA_DBG_PMULT, sata_hba_inst,
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang "Port multiplier registered at port %d", cport);
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang }
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst, cport)));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang}
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
5c44817c0d1a2b9b02dbbf343823da0b064f0ee7jw/*
5c44817c0d1a2b9b02dbbf343823da0b064f0ee7jw * sata_name_child is for composing the name of the node
5c44817c0d1a2b9b02dbbf343823da0b064f0ee7jw * the format of the name is "target,0".
5c44817c0d1a2b9b02dbbf343823da0b064f0ee7jw */
5c44817c0d1a2b9b02dbbf343823da0b064f0ee7jwstatic int
5c44817c0d1a2b9b02dbbf343823da0b064f0ee7jwsata_name_child(dev_info_t *dip, char *name, int namelen)
5c44817c0d1a2b9b02dbbf343823da0b064f0ee7jw{
5c44817c0d1a2b9b02dbbf343823da0b064f0ee7jw int target;
5c44817c0d1a2b9b02dbbf343823da0b064f0ee7jw
5c44817c0d1a2b9b02dbbf343823da0b064f0ee7jw target = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
5c44817c0d1a2b9b02dbbf343823da0b064f0ee7jw DDI_PROP_DONTPASS, "target", -1);
5c44817c0d1a2b9b02dbbf343823da0b064f0ee7jw if (target == -1)
5c44817c0d1a2b9b02dbbf343823da0b064f0ee7jw return (DDI_FAILURE);
5c44817c0d1a2b9b02dbbf343823da0b064f0ee7jw (void) snprintf(name, namelen, "%x,0", target);
5c44817c0d1a2b9b02dbbf343823da0b064f0ee7jw return (DDI_SUCCESS);
5c44817c0d1a2b9b02dbbf343823da0b064f0ee7jw}
5c44817c0d1a2b9b02dbbf343823da0b064f0ee7jw
5c44817c0d1a2b9b02dbbf343823da0b064f0ee7jw
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/* ****************** SCSA required entry points *********************** */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Implementation of scsi tran_tgt_init.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * sata_scsi_tgt_init() initializes scsi_device structure
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * If successful, DDI_SUCCESS is returned.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * DDI_FAILURE is returned if addressed device does not exist
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_scsi_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#ifndef __lock_lint
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf _NOTE(ARGUNUSED(hba_dip))
2038334ab26baaa43c9083f35def041511c3cc1fUnknown _NOTE(ARGUNUSED(tgt_dip))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#endif
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device_t sata_device;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_drive_info_t *sdinfo;
184cd04c26b064536977dfbb913a1240eaf6f708cth struct sata_id *sid;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst_t *sata_hba_inst;
184cd04c26b064536977dfbb913a1240eaf6f708cth char model[SATA_ID_MODEL_LEN + 1];
184cd04c26b064536977dfbb913a1240eaf6f708cth char fw[SATA_ID_FW_LEN + 1];
184cd04c26b064536977dfbb913a1240eaf6f708cth char *vid, *pid;
184cd04c26b064536977dfbb913a1240eaf6f708cth int i;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
5c44817c0d1a2b9b02dbbf343823da0b064f0ee7jw /*
5c44817c0d1a2b9b02dbbf343823da0b064f0ee7jw * Fail tran_tgt_init for .conf stub node
5c44817c0d1a2b9b02dbbf343823da0b064f0ee7jw */
5c44817c0d1a2b9b02dbbf343823da0b064f0ee7jw if (ndi_dev_is_persistent_node(tgt_dip) == 0) {
5c44817c0d1a2b9b02dbbf343823da0b064f0ee7jw (void) ndi_merge_node(tgt_dip, sata_name_child);
5c44817c0d1a2b9b02dbbf343823da0b064f0ee7jw ddi_set_name_addr(tgt_dip, NULL);
5c44817c0d1a2b9b02dbbf343823da0b064f0ee7jw return (DDI_FAILURE);
5c44817c0d1a2b9b02dbbf343823da0b064f0ee7jw }
5c44817c0d1a2b9b02dbbf343823da0b064f0ee7jw
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst = (sata_hba_inst_t *)(hba_tran->tran_hba_private);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Validate scsi device address */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_validate_scsi_address(sata_hba_inst, &sd->sd_address,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf &sata_device) != 0)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (DDI_FAILURE);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&(SATA_CPORT_MUTEX(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_addr.cport)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* sata_device now contains a valid sata address */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo = sata_get_device_info(sata_hba_inst, &sata_device);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sdinfo == NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_addr.cport)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (DDI_FAILURE);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
184cd04c26b064536977dfbb913a1240eaf6f708cth mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst,
184cd04c26b064536977dfbb913a1240eaf6f708cth sata_device.satadev_addr.cport)));
184cd04c26b064536977dfbb913a1240eaf6f708cth
8d483882aa3390058094b043f3d62187b5d1de03mlf /*
8d483882aa3390058094b043f3d62187b5d1de03mlf * Check if we need to create a legacy devid (i.e cmdk style) for
8d483882aa3390058094b043f3d62187b5d1de03mlf * the target disks.
8d483882aa3390058094b043f3d62187b5d1de03mlf *
8d483882aa3390058094b043f3d62187b5d1de03mlf * HBA devinfo node will have the property "use-cmdk-devid-format"
8d483882aa3390058094b043f3d62187b5d1de03mlf * if we need to create cmdk-style devid for all the disk devices
8d483882aa3390058094b043f3d62187b5d1de03mlf * attached to this controller. This property may have been set
8d483882aa3390058094b043f3d62187b5d1de03mlf * from HBA driver's .conf file or by the HBA driver in its
8d483882aa3390058094b043f3d62187b5d1de03mlf * attach(9F) function.
8d483882aa3390058094b043f3d62187b5d1de03mlf */
8d483882aa3390058094b043f3d62187b5d1de03mlf if ((sdinfo->satadrv_type == SATA_DTYPE_ATADISK) &&
8d483882aa3390058094b043f3d62187b5d1de03mlf (ddi_getprop(DDI_DEV_T_ANY, hba_dip, DDI_PROP_DONTPASS,
8d483882aa3390058094b043f3d62187b5d1de03mlf "use-cmdk-devid-format", 0) == 1)) {
8d483882aa3390058094b043f3d62187b5d1de03mlf /* register a legacy devid for this target node */
8d483882aa3390058094b043f3d62187b5d1de03mlf sata_target_devid_register(tgt_dip, sdinfo);
8d483882aa3390058094b043f3d62187b5d1de03mlf }
8d483882aa3390058094b043f3d62187b5d1de03mlf
8d483882aa3390058094b043f3d62187b5d1de03mlf
184cd04c26b064536977dfbb913a1240eaf6f708cth /*
184cd04c26b064536977dfbb913a1240eaf6f708cth * 'Identify Device Data' does not always fit in standard SCSI
184cd04c26b064536977dfbb913a1240eaf6f708cth * INQUIRY data, so establish INQUIRY_* properties with full-form
184cd04c26b064536977dfbb913a1240eaf6f708cth * of information.
184cd04c26b064536977dfbb913a1240eaf6f708cth */
184cd04c26b064536977dfbb913a1240eaf6f708cth sid = &sdinfo->satadrv_id;
184cd04c26b064536977dfbb913a1240eaf6f708cth#ifdef _LITTLE_ENDIAN
184cd04c26b064536977dfbb913a1240eaf6f708cth swab(sid->ai_model, model, SATA_ID_MODEL_LEN);
184cd04c26b064536977dfbb913a1240eaf6f708cth swab(sid->ai_fw, fw, SATA_ID_FW_LEN);
184cd04c26b064536977dfbb913a1240eaf6f708cth#else /* _LITTLE_ENDIAN */
184cd04c26b064536977dfbb913a1240eaf6f708cth bcopy(sid->ai_model, model, SATA_ID_MODEL_LEN);
184cd04c26b064536977dfbb913a1240eaf6f708cth bcopy(sid->ai_fw, fw, SATA_ID_FW_LEN);
184cd04c26b064536977dfbb913a1240eaf6f708cth#endif /* _LITTLE_ENDIAN */
184cd04c26b064536977dfbb913a1240eaf6f708cth model[SATA_ID_MODEL_LEN] = 0;
184cd04c26b064536977dfbb913a1240eaf6f708cth fw[SATA_ID_FW_LEN] = 0;
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth /* split model into into vid/pid */
184cd04c26b064536977dfbb913a1240eaf6f708cth for (i = 0, pid = model; i < SATA_ID_MODEL_LEN; i++, pid++)
184cd04c26b064536977dfbb913a1240eaf6f708cth if ((*pid == ' ') || (*pid == '\t'))
184cd04c26b064536977dfbb913a1240eaf6f708cth break;
184cd04c26b064536977dfbb913a1240eaf6f708cth if (i < SATA_ID_MODEL_LEN) {
184cd04c26b064536977dfbb913a1240eaf6f708cth vid = model;
184cd04c26b064536977dfbb913a1240eaf6f708cth *pid++ = 0; /* terminate vid, establish pid */
184cd04c26b064536977dfbb913a1240eaf6f708cth } else {
184cd04c26b064536977dfbb913a1240eaf6f708cth vid = NULL; /* vid will stay "ATA " */
184cd04c26b064536977dfbb913a1240eaf6f708cth pid = model; /* model is all pid */
184cd04c26b064536977dfbb913a1240eaf6f708cth }
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth if (vid)
184cd04c26b064536977dfbb913a1240eaf6f708cth (void) scsi_hba_prop_update_inqstring(sd, INQUIRY_VENDOR_ID,
184cd04c26b064536977dfbb913a1240eaf6f708cth vid, strlen(vid));
184cd04c26b064536977dfbb913a1240eaf6f708cth if (pid)
184cd04c26b064536977dfbb913a1240eaf6f708cth (void) scsi_hba_prop_update_inqstring(sd, INQUIRY_PRODUCT_ID,
184cd04c26b064536977dfbb913a1240eaf6f708cth pid, strlen(pid));
184cd04c26b064536977dfbb913a1240eaf6f708cth (void) scsi_hba_prop_update_inqstring(sd, INQUIRY_REVISION_ID,
184cd04c26b064536977dfbb913a1240eaf6f708cth fw, strlen(fw));
184cd04c26b064536977dfbb913a1240eaf6f708cth
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (DDI_SUCCESS);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Implementation of scsi tran_tgt_probe.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Probe target, by calling default scsi routine scsi_hba_probe()
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_scsi_tgt_probe(struct scsi_device *sd, int (*callback)(void))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst_t *sata_hba_inst =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (sata_hba_inst_t *)(sd->sd_address.a_hba_tran->tran_hba_private);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int rval;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu uint32_t pm_cap;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rval = scsi_hba_probe(sd, callback);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu pm_cap = SATA_CAP_POWER_CONDITON | SATA_CAP_SMART_PAGE |
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu SATA_CAP_LOG_SENSE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (rval == SCSIPROBE_EXISTS) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Set property "pm-capable" on the target device node, so that
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * the target driver will not try to fetch scsi cycle counters
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * before enabling device power-management.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((ddi_prop_update_int(DDI_DEV_T_NONE, sd->sd_dev,
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu "pm-capable", pm_cap)) != DDI_PROP_SUCCESS) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_log(sata_hba_inst, CE_WARN,
184cd04c26b064536977dfbb913a1240eaf6f708cth "SATA device at port %d: "
184cd04c26b064536977dfbb913a1240eaf6f708cth "will not be power-managed ",
184cd04c26b064536977dfbb913a1240eaf6f708cth SCSI_TO_SATA_CPORT(sd->sd_address.a_target));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_LOG_D((sata_hba_inst, CE_WARN,
184cd04c26b064536977dfbb913a1240eaf6f708cth "failure updating pm-capable property"));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (rval);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Implementation of scsi tran_tgt_free.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Release all resources allocated for scsi_device
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_scsi_tgt_free(dev_info_t *hba_dip, dev_info_t *tgt_dip,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#ifndef __lock_lint
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf _NOTE(ARGUNUSED(hba_dip))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#endif
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device_t sata_device;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_drive_info_t *sdinfo;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst_t *sata_hba_inst;
8d483882aa3390058094b043f3d62187b5d1de03mlf ddi_devid_t devid;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst = (sata_hba_inst_t *)(hba_tran->tran_hba_private);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Validate scsi device address */
a9d5ae2e08c504913c088349c3d4c144f3c92be8Pawel Wojcik /*
a9d5ae2e08c504913c088349c3d4c144f3c92be8Pawel Wojcik * Note: tgt_free relates to the SCSA view of a device. If called, there
a9d5ae2e08c504913c088349c3d4c144f3c92be8Pawel Wojcik * was a device at this address, so even if the sata framework internal
a9d5ae2e08c504913c088349c3d4c144f3c92be8Pawel Wojcik * resources were alredy released because a device was detached,
a9d5ae2e08c504913c088349c3d4c144f3c92be8Pawel Wojcik * this function should be executed as long as its actions do
a9d5ae2e08c504913c088349c3d4c144f3c92be8Pawel Wojcik * not require the internal sata view of a device and the address
a9d5ae2e08c504913c088349c3d4c144f3c92be8Pawel Wojcik * refers to a valid sata address.
a9d5ae2e08c504913c088349c3d4c144f3c92be8Pawel Wojcik * Validating the address here means that we do not trust SCSA...
a9d5ae2e08c504913c088349c3d4c144f3c92be8Pawel Wojcik */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_validate_scsi_address(sata_hba_inst, &sd->sd_address,
a9d5ae2e08c504913c088349c3d4c144f3c92be8Pawel Wojcik &sata_device) == -1)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&(SATA_CPORT_MUTEX(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_addr.cport)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* sata_device now should contain a valid sata address */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo = sata_get_device_info(sata_hba_inst, &sata_device);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sdinfo == NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_addr.cport)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * We did not allocate any resources in sata_scsi_tgt_init()
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * other than few properties.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Free them.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_device.satadev_addr.cport)));
c75976d12071ddd21443266260066ba036671682pawelw (void) ndi_prop_remove(DDI_DEV_T_NONE, tgt_dip, "pm-capable");
8d483882aa3390058094b043f3d62187b5d1de03mlf
8d483882aa3390058094b043f3d62187b5d1de03mlf /*
8d483882aa3390058094b043f3d62187b5d1de03mlf * If devid was previously created but not freed up from
8d483882aa3390058094b043f3d62187b5d1de03mlf * sd(7D) driver (i.e during detach(9F)) then do it here.
8d483882aa3390058094b043f3d62187b5d1de03mlf */
8d483882aa3390058094b043f3d62187b5d1de03mlf if ((sdinfo->satadrv_type == SATA_DTYPE_ATADISK) &&
8d483882aa3390058094b043f3d62187b5d1de03mlf (ddi_getprop(DDI_DEV_T_ANY, hba_dip, DDI_PROP_DONTPASS,
8d483882aa3390058094b043f3d62187b5d1de03mlf "use-cmdk-devid-format", 0) == 1) &&
8d483882aa3390058094b043f3d62187b5d1de03mlf (ddi_devid_get(tgt_dip, &devid) == DDI_SUCCESS)) {
8d483882aa3390058094b043f3d62187b5d1de03mlf ddi_devid_unregister(tgt_dip);
8d483882aa3390058094b043f3d62187b5d1de03mlf ddi_devid_free(devid);
8d483882aa3390058094b043f3d62187b5d1de03mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Implementation of scsi tran_init_pkt
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Upon successful return, scsi pkt buffer has DMA resources allocated.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * It seems that we should always allocate pkt, even if the address is
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * for non-existing device - just use some default for dma_attr.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * The reason is that there is no way to communicate this to a caller here.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Subsequent call to sata_scsi_start may fail appropriately.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Simply returning NULL does not seem to discourage a target driver...
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Returns a pointer to initialized scsi_pkt, or NULL otherwise.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic struct scsi_pkt *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_scsi_init_pkt(struct scsi_address *ap, struct scsi_pkt *pkt,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf struct buf *bp, int cmdlen, int statuslen, int tgtlen, int flags,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int (*callback)(caddr_t), caddr_t arg)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst_t *sata_hba_inst =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (sata_hba_inst_t *)(ap->a_hba_tran->tran_hba_private);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf dev_info_t *dip = SATA_DIP(sata_hba_inst);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device_t sata_device;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_drive_info_t *sdinfo;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_pkt_txlate_t *spx;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ddi_dma_attr_t cur_dma_attr;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int rval;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf boolean_t new_pkt = TRUE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ASSERT(ap->a_hba_tran->tran_hba_dip == dip);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * We need to translate the address, even if it could be
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * a bogus one, for a non-existing device
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_addr.qual = SCSI_TO_SATA_ADDR_QUAL(ap->a_target);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_addr.cport = SCSI_TO_SATA_CPORT(ap->a_target);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_addr.pmport = SCSI_TO_SATA_PMPORT(ap->a_target);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_rev = SATA_DEVICE_REV;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (pkt == NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Have to allocate a brand new scsi packet.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * We need to operate with auto request sense enabled.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf pkt = scsi_hba_pkt_alloc(dip, ap, cmdlen,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf MAX(statuslen, sizeof (struct scsi_arq_status)),
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf tgtlen, sizeof (sata_pkt_txlate_t), callback, arg);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (pkt == NULL)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Fill scsi packet structure */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf pkt->pkt_comp = (void (*)())NULL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf pkt->pkt_time = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf pkt->pkt_resid = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf pkt->pkt_statistics = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf pkt->pkt_reason = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * pkt_hba_private will point to sata pkt txlate structure
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx = (sata_pkt_txlate_t *)pkt->pkt_ha_private;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf bzero(spx, sizeof (sata_pkt_txlate_t));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_scsi_pkt = pkt;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_sata_hba_inst = sata_hba_inst;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Allocate sata_pkt */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_sata_pkt = sata_pkt_alloc(spx, callback);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (spx->txlt_sata_pkt == NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Could not allocate sata pkt */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsi_hba_pkt_free(ap, pkt);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Set sata address */
6ed1276fb5fe78fb1cce38682748a830ef8bd157pawelw spx->txlt_sata_pkt->satapkt_device.satadev_addr =
6ed1276fb5fe78fb1cce38682748a830ef8bd157pawelw sata_device.satadev_addr;
6ed1276fb5fe78fb1cce38682748a830ef8bd157pawelw spx->txlt_sata_pkt->satapkt_device.satadev_rev =
6ed1276fb5fe78fb1cce38682748a830ef8bd157pawelw sata_device.satadev_rev;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((bp == NULL) || (bp->b_bcount == 0))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (pkt);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_total_residue = bp->b_bcount;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf new_pkt = FALSE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Packet was preallocated/initialized by previous call
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx = (sata_pkt_txlate_t *)pkt->pkt_ha_private;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((bp == NULL) || (bp->b_bcount == 0)) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (pkt);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Pkt is available already: spx->txlt_scsi_pkt == pkt; */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_sata_pkt->satapkt_cmd.satacmd_bp = bp;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * We use an adjusted version of the dma_attr, to account
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * for device addressing limitations.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * sata_adjust_dma_attr() will handle sdinfo == NULL which may
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * happen when a device is not yet configured.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&(SATA_CPORT_MUTEX(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_addr.cport)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo = sata_get_device_info(spx->txlt_sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf &spx->txlt_sata_pkt->satapkt_device);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* NULL sdinfo may be passsed to sata_adjust_dma_attr() */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_adjust_dma_attr(sdinfo,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_DMA_ATTR(spx->txlt_sata_hba_inst), &cur_dma_attr);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_addr.cport)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
4360436b3c604bc28d37be269ad152b4c38157c3pawelw * Allocate necessary DMA resources for the packet's data buffer
4360436b3c604bc28d37be269ad152b4c38157c3pawelw * NOTE:
4360436b3c604bc28d37be269ad152b4c38157c3pawelw * In case of read/write commands, DMA resource allocation here is
4360436b3c604bc28d37be269ad152b4c38157c3pawelw * based on the premise that the transfer length specified in
4360436b3c604bc28d37be269ad152b4c38157c3pawelw * the read/write scsi cdb will match exactly DMA resources -
4360436b3c604bc28d37be269ad152b4c38157c3pawelw * returning correct packet residue is crucial.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((rval = sata_dma_buf_setup(spx, flags, callback, arg,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf &cur_dma_attr)) != DDI_SUCCESS) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * If a DMA allocation request fails with
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * DDI_DMA_NOMAPPING, indicate the error by calling
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * bioerror(9F) with bp and an error code of EFAULT.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * If a DMA allocation request fails with
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * DDI_DMA_TOOBIG, indicate the error by calling
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * bioerror(9F) with bp and an error code of EINVAL.
6a2bb0c23e183d064817bc0ab8bff3b8c346c967pawelw * For DDI_DMA_NORESOURCES, we may have some of them allocated.
6a2bb0c23e183d064817bc0ab8bff3b8c346c967pawelw * Request may be repeated later - there is no real error.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf switch (rval) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case DDI_DMA_NORESOURCES:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf bioerror(bp, 0);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case DDI_DMA_NOMAPPING:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case DDI_DMA_BADATTR:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf bioerror(bp, EFAULT);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case DDI_DMA_TOOBIG:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf default:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf bioerror(bp, EINVAL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
6a2bb0c23e183d064817bc0ab8bff3b8c346c967pawelw if (new_pkt == TRUE) {
6a2bb0c23e183d064817bc0ab8bff3b8c346c967pawelw /*
6a2bb0c23e183d064817bc0ab8bff3b8c346c967pawelw * Since this is a new packet, we can clean-up
6a2bb0c23e183d064817bc0ab8bff3b8c346c967pawelw * everything
6a2bb0c23e183d064817bc0ab8bff3b8c346c967pawelw */
6a2bb0c23e183d064817bc0ab8bff3b8c346c967pawelw sata_scsi_destroy_pkt(ap, pkt);
6a2bb0c23e183d064817bc0ab8bff3b8c346c967pawelw } else {
6a2bb0c23e183d064817bc0ab8bff3b8c346c967pawelw /*
6a2bb0c23e183d064817bc0ab8bff3b8c346c967pawelw * This is a re-used packet. It will be target driver's
6a2bb0c23e183d064817bc0ab8bff3b8c346c967pawelw * responsibility to eventually destroy it (which
6a2bb0c23e183d064817bc0ab8bff3b8c346c967pawelw * will free allocated resources).
6a2bb0c23e183d064817bc0ab8bff3b8c346c967pawelw * Here, we just "complete" the request, leaving
6a2bb0c23e183d064817bc0ab8bff3b8c346c967pawelw * allocated resources intact, so the request may
6a2bb0c23e183d064817bc0ab8bff3b8c346c967pawelw * be retried.
6a2bb0c23e183d064817bc0ab8bff3b8c346c967pawelw */
6a2bb0c23e183d064817bc0ab8bff3b8c346c967pawelw spx->txlt_sata_pkt->satapkt_cmd.satacmd_bp = NULL;
6a2bb0c23e183d064817bc0ab8bff3b8c346c967pawelw sata_pkt_free(spx);
6a2bb0c23e183d064817bc0ab8bff3b8c346c967pawelw }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Set number of bytes that are not yet accounted for */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf pkt->pkt_resid = spx->txlt_total_residue;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ASSERT(pkt->pkt_resid >= 0);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (pkt);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Implementation of scsi tran_start.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Translate scsi cmd into sata operation and return status.
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw * ATAPI CDBs are passed to ATAPI devices - the device determines what commands
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw * are supported.
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw * For SATA hard disks, supported scsi commands:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * SCMD_INQUIRY
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * SCMD_TEST_UNIT_READY
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * SCMD_START_STOP
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * SCMD_READ_CAPACITY
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * SCMD_REQUEST_SENSE
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw * SCMD_LOG_SENSE_G1
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw * SCMD_LOG_SELECT_G1
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * SCMD_MODE_SENSE (specific pages)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * SCMD_MODE_SENSE_G1 (specific pages)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * SCMD_MODE_SELECT (specific pages)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * SCMD_MODE_SELECT_G1 (specific pages)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * SCMD_SYNCHRONIZE_CACHE
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * SCMD_SYNCHRONIZE_CACHE_G1
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * SCMD_READ
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * SCMD_READ_G1
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * SCMD_READ_G4
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * SCMD_READ_G5
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * SCMD_WRITE
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls * SCMD_WRITE_BUFFER
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * SCMD_WRITE_G1
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * SCMD_WRITE_G4
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * SCMD_WRITE_G5
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * SCMD_SEEK (noop)
489f952b4388bd1ea1feff97164a4416e0c621eals * SCMD_SDIAG
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * All other commands are rejected as unsupported.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Returns:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * TRAN_ACCEPT if command was executed successfully or accepted by HBA driver
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * for execution. TRAN_ACCEPT may be returned also if device was removed but
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * a callback could be scheduled.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * TRAN_BADPKT if cmd was directed to invalid address.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * TRAN_FATAL_ERROR is command was rejected due to hardware error, including
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * some unspecified error. TRAN_FATAL_ERROR may be also returned if a device
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * was removed and there was no callback specified in scsi pkt.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * TRAN_BUSY if command could not be executed becasue HBA driver or SATA
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * framework was busy performing some other operation(s).
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_scsi_start(struct scsi_address *ap, struct scsi_pkt *pkt)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst_t *sata_hba_inst =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (sata_hba_inst_t *)(ap->a_hba_tran->tran_hba_private);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_pkt_txlate_t *spx = (sata_pkt_txlate_t *)pkt->pkt_ha_private;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device_t *sdevice = &spx->txlt_sata_pkt->satapkt_device;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_drive_info_t *sdinfo;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf struct buf *bp;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang uint8_t cport, pmport;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang boolean_t dev_gone = B_FALSE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int rval;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG1(SATA_DBG_SCSI_IF, sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_scsi_start: cmd 0x%02x\n", pkt->pkt_cdbp[0]);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ASSERT(spx != NULL &&
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_scsi_pkt == pkt && spx->txlt_sata_pkt != NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport = SCSI_TO_SATA_CPORT(ap->a_target);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmport = SCSI_TO_SATA_PMPORT(ap->a_target);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&(SATA_CPORT_MUTEX(sata_hba_inst, cport)));
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (sdevice->satadev_addr.qual == SATA_ADDR_DCPORT) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sdinfo = sata_get_device_info(sata_hba_inst, sdevice);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (sdinfo == NULL ||
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_CPORT_INFO(sata_hba_inst, cport)->
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cport_tgtnode_clean == B_FALSE ||
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (sdinfo->satadrv_state & SATA_DSTATE_FAILED) != 0) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang dev_gone = B_TRUE;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang } else if (sdevice->satadev_addr.qual == SATA_ADDR_DPMPORT) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (SATA_CPORT_DEV_TYPE(sata_hba_inst, cport) !=
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_DTYPE_PMULT || SATA_PMULT_INFO(sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cport) == NULL) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang dev_gone = B_TRUE;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang } else if (SATA_PMPORT_INFO(sata_hba_inst, cport,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmport) == NULL) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang dev_gone = B_TRUE;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang } else {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&(SATA_PMPORT_MUTEX(sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cport, pmport)));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sdinfo = sata_get_device_info(sata_hba_inst, sdevice);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (sdinfo == NULL ||
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_PMPORT_INFO(sata_hba_inst, cport, pmport)->
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmport_tgtnode_clean == B_FALSE ||
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (sdinfo->satadrv_state & SATA_DSTATE_FAILED) != 0) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang dev_gone = B_TRUE;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&(SATA_PMPORT_MUTEX(sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cport, pmport)));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (dev_gone == B_TRUE) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst, cport)));
4360436b3c604bc28d37be269ad152b4c38157c3pawelw pkt->pkt_reason = CMD_DEV_GONE;
4360436b3c604bc28d37be269ad152b4c38157c3pawelw /*
4360436b3c604bc28d37be269ad152b4c38157c3pawelw * The sd target driver is checking CMD_DEV_GONE pkt_reason
4360436b3c604bc28d37be269ad152b4c38157c3pawelw * only in callback function (for normal requests) and
4360436b3c604bc28d37be269ad152b4c38157c3pawelw * in the dump code path.
4360436b3c604bc28d37be269ad152b4c38157c3pawelw * So, if the callback is available, we need to do
4360436b3c604bc28d37be269ad152b4c38157c3pawelw * the callback rather than returning TRAN_FATAL_ERROR here.
4360436b3c604bc28d37be269ad152b4c38157c3pawelw */
4360436b3c604bc28d37be269ad152b4c38157c3pawelw if (pkt->pkt_comp != NULL) {
4360436b3c604bc28d37be269ad152b4c38157c3pawelw /* scsi callback required */
4360436b3c604bc28d37be269ad152b4c38157c3pawelw if (taskq_dispatch(SATA_TXLT_TASKQ(spx),
4360436b3c604bc28d37be269ad152b4c38157c3pawelw (task_func_t *)pkt->pkt_comp,
4360436b3c604bc28d37be269ad152b4c38157c3pawelw (void *)pkt, TQ_SLEEP) == NULL)
4360436b3c604bc28d37be269ad152b4c38157c3pawelw /* Scheduling the callback failed */
4360436b3c604bc28d37be269ad152b4c38157c3pawelw return (TRAN_BUSY);
4360436b3c604bc28d37be269ad152b4c38157c3pawelw return (TRAN_ACCEPT);
4360436b3c604bc28d37be269ad152b4c38157c3pawelw }
4360436b3c604bc28d37be269ad152b4c38157c3pawelw /* No callback available */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (TRAN_FATAL_ERROR);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China if (sdinfo->satadrv_type & SATA_DTYPE_ATAPI) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst, cport)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rval = sata_txlt_atapi(spx);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG1(SATA_DBG_SCSI_IF, sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_scsi_start atapi: rval %d\n", rval);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (rval);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst, cport)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu /*
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu * Checking for power state, if it was on
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu * STOPPED state, then the drive is not capable
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu * of processing media access command. And
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu * TEST_UNIT_READY, REQUEST_SENSE has special handling
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu * in the function for different power state.
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu */
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if (((sdinfo->satadrv_power_level == SATA_POWER_STANDBY) ||
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu (sdinfo->satadrv_power_level == SATA_POWER_STOPPED)) &&
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu (SATA_IS_MEDIUM_ACCESS_CMD(pkt->pkt_cdbp[0]))) {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu return (sata_txlt_check_condition(spx, KEY_NOT_READY,
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu SD_SCSI_ASC_LU_NOT_READY));
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu }
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* ATA Disk commands processing starts here */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf bp = spx->txlt_sata_pkt->satapkt_cmd.satacmd_bp;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf switch (pkt->pkt_cdbp[0]) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SCMD_INQUIRY:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Mapped to identify device */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (bp != NULL && (bp->b_flags & (B_PHYS | B_PAGEIO)))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf bp_mapin(bp);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rval = sata_txlt_inquiry(spx);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SCMD_TEST_UNIT_READY:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * SAT "SATA to ATA Translation" doc specifies translation
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * to ATA CHECK POWER MODE.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rval = sata_txlt_test_unit_ready(spx);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SCMD_START_STOP:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Mapping depends on the command */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rval = sata_txlt_start_stop_unit(spx);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SCMD_READ_CAPACITY:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (bp != NULL && (bp->b_flags & (B_PHYS | B_PAGEIO)))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf bp_mapin(bp);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rval = sata_txlt_read_capacity(spx);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SCMD_REQUEST_SENSE:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Always No Sense, since we force ARQ
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (bp != NULL && (bp->b_flags & (B_PHYS | B_PAGEIO)))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf bp_mapin(bp);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rval = sata_txlt_request_sense(spx);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SCMD_LOG_SENSE_G1:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (bp != NULL && (bp->b_flags & (B_PHYS | B_PAGEIO)))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf bp_mapin(bp);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rval = sata_txlt_log_sense(spx);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SCMD_LOG_SELECT_G1:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (bp != NULL && (bp->b_flags & (B_PHYS | B_PAGEIO)))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf bp_mapin(bp);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rval = sata_txlt_log_select(spx);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SCMD_MODE_SENSE:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SCMD_MODE_SENSE_G1:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (bp != NULL && (bp->b_flags & (B_PHYS | B_PAGEIO)))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf bp_mapin(bp);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rval = sata_txlt_mode_sense(spx);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SCMD_MODE_SELECT:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SCMD_MODE_SELECT_G1:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (bp != NULL && (bp->b_flags & (B_PHYS | B_PAGEIO)))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf bp_mapin(bp);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rval = sata_txlt_mode_select(spx);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SCMD_SYNCHRONIZE_CACHE:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SCMD_SYNCHRONIZE_CACHE_G1:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rval = sata_txlt_synchronize_cache(spx);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SCMD_READ:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SCMD_READ_G1:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SCMD_READ_G4:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SCMD_READ_G5:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rval = sata_txlt_read(spx);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls case SCMD_WRITE_BUFFER:
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls if (bp != NULL && (bp->b_flags & (B_PHYS | B_PAGEIO)))
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls bp_mapin(bp);
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls rval = sata_txlt_write_buffer(spx);
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SCMD_WRITE:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SCMD_WRITE_G1:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SCMD_WRITE_G4:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SCMD_WRITE_G5:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rval = sata_txlt_write(spx);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SCMD_SEEK:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rval = sata_txlt_nodata_cmd_immediate(spx);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Other cases will be filed later */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* postponed until phase 2 of the development */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf default:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rval = sata_txlt_invalid_command(spx);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG1(SATA_DBG_SCSI_IF, sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_scsi_start: rval %d\n", rval);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (rval);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Implementation of scsi tran_abort.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Abort specific pkt or all packets.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Returns 1 if one or more packets were aborted, returns 0 otherwise
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * May be called from an interrupt level.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_scsi_abort(struct scsi_address *ap, struct scsi_pkt *scsi_pkt)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst_t *sata_hba_inst =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (sata_hba_inst_t *)(ap->a_hba_tran->tran_hba_private);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device_t sata_device;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_pkt_t *sata_pkt;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG2(SATA_DBG_SCSI_IF, sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_scsi_abort: %s at target: 0x%x\n",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsi_pkt == NULL ? "all packets" : "one pkt", ap->a_target);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Validate address */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_validate_scsi_address(sata_hba_inst, ap, &sata_device) != 0)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Invalid address */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (0);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&(SATA_CPORT_MUTEX(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_addr.cport)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_get_device_info(sata_hba_inst, &sata_device) == NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* invalid address */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_addr.cport)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (0);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (scsi_pkt == NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Abort all packets.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Although we do not have specific packet, we still need
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * dummy packet structure to pass device address to HBA.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Allocate one, without sleeping. Fail if pkt cannot be
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * allocated.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_pkt = kmem_zalloc(sizeof (sata_pkt_t), KM_NOSLEEP);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_pkt == NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_addr.cport)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_LOG_D((sata_hba_inst, CE_WARN, "sata_pkt_abort: "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "could not allocate sata_pkt"));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (0);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_pkt->satapkt_rev = SATA_PKT_REV;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_pkt->satapkt_device = sata_device;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_pkt->satapkt_device.satadev_rev = SATA_DEVICE_REV;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (scsi_pkt->pkt_ha_private == NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_addr.cport)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (0); /* Bad scsi pkt */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* extract pointer to sata pkt */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_pkt = ((sata_pkt_txlate_t *)scsi_pkt->pkt_ha_private)->
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf txlt_sata_pkt;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_addr.cport)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Send abort request to HBA */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((*SATA_ABORT_FUNC(sata_hba_inst))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (SATA_DIP(sata_hba_inst), sata_pkt,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsi_pkt == NULL ? SATA_ABORT_ALL_PACKETS : SATA_ABORT_PACKET) ==
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_SUCCESS) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (scsi_pkt == NULL)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf kmem_free(sata_pkt, sizeof (sata_pkt_t));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Success */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (1);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Else, something did not go right */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (scsi_pkt == NULL)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf kmem_free(sata_pkt, sizeof (sata_pkt_t));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Failure */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (0);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Implementation of scsi tran_reset.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * RESET_ALL request is translated into port reset.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * RESET_TARGET requests is translated into a device reset,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * RESET_LUN request is accepted only for LUN 0 and translated into
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * device reset.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * The target reset should cause all HBA active and queued packets to
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * be terminated and returned with pkt reason SATA_PKT_RESET prior to
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * the return. HBA should report reset event for the device.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Returns 1 upon success, 0 upon failure.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_scsi_reset(struct scsi_address *ap, int level)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst_t *sata_hba_inst =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (sata_hba_inst_t *)(ap->a_hba_tran->tran_hba_private);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device_t sata_device;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int val;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG2(SATA_DBG_SCSI_IF, sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_scsi_reset: level %d target: 0x%x\n",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf level, ap->a_target);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Validate address */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf val = sata_validate_scsi_address(sata_hba_inst, ap, &sata_device);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (val == -1)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Invalid address */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (0);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&(SATA_CPORT_MUTEX(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_addr.cport)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_get_device_info(sata_hba_inst, &sata_device) == NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* invalid address */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_addr.cport)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (0);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_addr.cport)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (level == RESET_ALL) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* port reset */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (sata_device.satadev_addr.qual == SATA_ADDR_DCPORT)
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device.satadev_addr.qual = SATA_ADDR_CPORT;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang else
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device.satadev_addr.qual = SATA_ADDR_PMPORT;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((*SATA_RESET_DPORT_FUNC(sata_hba_inst))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (SATA_DIP(sata_hba_inst), &sata_device) == SATA_SUCCESS)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (1);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf else
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (0);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else if (val == 0 &&
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (level == RESET_TARGET || level == RESET_LUN)) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* reset device (device attached) */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((*SATA_RESET_DPORT_FUNC(sata_hba_inst))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (SATA_DIP(sata_hba_inst), &sata_device) == SATA_SUCCESS)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (1);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf else
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (0);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (0);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Implementation of scsi tran_getcap (get transport/device capabilities).
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Supported capabilities for SATA hard disks:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * auto-rqsense (always supported)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * tagged-qing (supported if HBA supports it)
37a077ef1920ee044b2887247b2a802e726d3368ls * untagged-qing (could be supported if disk supports it, but because
37a077ef1920ee044b2887247b2a802e726d3368ls * caching behavior allowing untagged queuing actually
37a077ef1920ee044b2887247b2a802e726d3368ls * results in reduced performance. sd tries to throttle
37a077ef1920ee044b2887247b2a802e726d3368ls * back to only 3 outstanding commands, which may
37a077ef1920ee044b2887247b2a802e726d3368ls * work for real SCSI disks, but with read ahead
37a077ef1920ee044b2887247b2a802e726d3368ls * caching, having more than 1 outstanding command
37a077ef1920ee044b2887247b2a802e726d3368ls * results in cache thrashing.)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * sector_size
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * dma_max
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * interconnect-type (INTERCONNECT_SATA)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown *
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China * Supported capabilities for ATAPI CD/DVD devices:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * auto-rqsense (always supported)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * sector_size
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * dma_max
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China * max-cdb-length
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * interconnect-type (INTERCONNECT_SATA)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China * Supported capabilities for ATAPI TAPE devices:
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China * auto-rqsense (always supported)
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China * dma_max
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China * max-cdb-length
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China *
f8a673ad9145b262edb65a98fb3fb92027d23a05ying tian - Beijing China * Supported capabilities for SATA ATAPI hard disks:
f8a673ad9145b262edb65a98fb3fb92027d23a05ying tian - Beijing China * auto-rqsense (always supported)
f8a673ad9145b262edb65a98fb3fb92027d23a05ying tian - Beijing China * interconnect-type (INTERCONNECT_SATA)
f8a673ad9145b262edb65a98fb3fb92027d23a05ying tian - Beijing China * max-cdb-length
f8a673ad9145b262edb65a98fb3fb92027d23a05ying tian - Beijing China *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Request for other capabilities is rejected as unsupported.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Returns supported capability value, or -1 if capability is unsuppported or
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * the address is invalid - no device.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_scsi_getcap(struct scsi_address *ap, char *cap, int whom)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst_t *sata_hba_inst =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (sata_hba_inst_t *)(ap->a_hba_tran->tran_hba_private);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device_t sata_device;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_drive_info_t *sdinfo;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ddi_dma_attr_t adj_dma_attr;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int rval;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG2(SATA_DBG_SCSI_IF, sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_scsi_getcap: target: 0x%x, cap: %s\n",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ap->a_target, cap);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * We want to process the capabilities on per port granularity.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * So, we are specifically restricting ourselves to whom != 0
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * to exclude the controller wide handling.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (cap == NULL || whom == 0)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (-1);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_validate_scsi_address(sata_hba_inst, ap, &sata_device) != 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Invalid address */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (-1);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&(SATA_CPORT_MUTEX(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_addr.cport)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((sdinfo = sata_get_device_info(sata_hba_inst, &sata_device)) ==
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* invalid address */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_addr.cport)));
4e54023805e14cf984b9f0041df73c16334a7a88ls return (-1);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf switch (scsi_hba_lookup_capstr(cap)) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SCSI_CAP_ARQ:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rval = 1; /* ARQ supported, turned on */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SCSI_CAP_SECTOR_SIZE:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sdinfo->satadrv_type == SATA_DTYPE_ATADISK)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rval = SATA_DISK_SECTOR_SIZE; /* fixed size */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf else if (sdinfo->satadrv_type == SATA_DTYPE_ATAPICD)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rval = SATA_ATAPI_SECTOR_SIZE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf else rval = -1;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
37a077ef1920ee044b2887247b2a802e726d3368ls /*
37a077ef1920ee044b2887247b2a802e726d3368ls * untagged queuing cause a performance inversion because of
37a077ef1920ee044b2887247b2a802e726d3368ls * the way sd operates. Because of this reason we do not
37a077ef1920ee044b2887247b2a802e726d3368ls * use it when available.
37a077ef1920ee044b2887247b2a802e726d3368ls */
37a077ef1920ee044b2887247b2a802e726d3368ls case SCSI_CAP_UNTAGGED_QING:
4e54023805e14cf984b9f0041df73c16334a7a88ls if (sdinfo->satadrv_features_enabled &
4e54023805e14cf984b9f0041df73c16334a7a88ls SATA_DEV_F_E_UNTAGGED_QING)
4e54023805e14cf984b9f0041df73c16334a7a88ls rval = 1; /* Untagged queuing available */
37a077ef1920ee044b2887247b2a802e726d3368ls else
4e54023805e14cf984b9f0041df73c16334a7a88ls rval = -1; /* Untagged queuing not available */
37a077ef1920ee044b2887247b2a802e726d3368ls break;
37a077ef1920ee044b2887247b2a802e726d3368ls
37a077ef1920ee044b2887247b2a802e726d3368ls case SCSI_CAP_TAGGED_QING:
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw if ((sdinfo->satadrv_features_enabled &
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw SATA_DEV_F_E_TAGGED_QING) &&
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw (sdinfo->satadrv_max_queue_depth > 1))
4e54023805e14cf984b9f0041df73c16334a7a88ls rval = 1; /* Tagged queuing available */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf else
4e54023805e14cf984b9f0041df73c16334a7a88ls rval = -1; /* Tagged queuing not available */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SCSI_CAP_DMA_MAX:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_adjust_dma_attr(sdinfo, SATA_DMA_ATTR(sata_hba_inst),
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf &adj_dma_attr);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rval = (int)adj_dma_attr.dma_attr_maxxfer;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* We rely on the fact that dma_attr_maxxfer < 0x80000000 */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SCSI_CAP_INTERCONNECT_TYPE:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rval = INTERCONNECT_SATA; /* SATA interconnect type */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China case SCSI_CAP_CDB_LEN:
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China if (sdinfo->satadrv_type & SATA_DTYPE_ATAPI)
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China rval = sdinfo->satadrv_atapi_cdb_len;
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China else
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China rval = -1;
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China break;
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf default:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rval = -1;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_addr.cport)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (rval);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Implementation of scsi tran_setcap
2038334ab26baaa43c9083f35def041511c3cc1fUnknown *
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Only SCSI_CAP_UNTAGGED_QING and SCSI_CAP_TAGGED_QING are changeable.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_scsi_setcap(struct scsi_address *ap, char *cap, int value, int whom)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst_t *sata_hba_inst =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (sata_hba_inst_t *)(ap->a_hba_tran->tran_hba_private);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device_t sata_device;
4e54023805e14cf984b9f0041df73c16334a7a88ls sata_drive_info_t *sdinfo;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int rval;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG2(SATA_DBG_SCSI_IF, sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_scsi_setcap: target: 0x%x, cap: %s\n", ap->a_target, cap);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * We want to process the capabilities on per port granularity.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * So, we are specifically restricting ourselves to whom != 0
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * to exclude the controller wide handling.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (cap == NULL || whom == 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (-1);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_validate_scsi_address(sata_hba_inst, ap, &sata_device) != 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Invalid address */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (-1);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&(SATA_CPORT_MUTEX(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_addr.cport)));
184cd04c26b064536977dfbb913a1240eaf6f708cth if ((sdinfo = sata_get_device_info(sata_hba_inst,
184cd04c26b064536977dfbb913a1240eaf6f708cth &sata_device)) == NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* invalid address */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_addr.cport)));
4e54023805e14cf984b9f0041df73c16334a7a88ls return (-1);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_addr.cport)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf switch (scsi_hba_lookup_capstr(cap)) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SCSI_CAP_ARQ:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SCSI_CAP_SECTOR_SIZE:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SCSI_CAP_DMA_MAX:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SCSI_CAP_INTERCONNECT_TYPE:
4e54023805e14cf984b9f0041df73c16334a7a88ls rval = 0;
4e54023805e14cf984b9f0041df73c16334a7a88ls break;
37a077ef1920ee044b2887247b2a802e726d3368ls case SCSI_CAP_UNTAGGED_QING:
4e54023805e14cf984b9f0041df73c16334a7a88ls if (SATA_QDEPTH(sata_hba_inst) > 1) {
4e54023805e14cf984b9f0041df73c16334a7a88ls rval = 1;
4e54023805e14cf984b9f0041df73c16334a7a88ls if (value == 1) {
4e54023805e14cf984b9f0041df73c16334a7a88ls sdinfo->satadrv_features_enabled |=
184cd04c26b064536977dfbb913a1240eaf6f708cth SATA_DEV_F_E_UNTAGGED_QING;
4e54023805e14cf984b9f0041df73c16334a7a88ls } else if (value == 0) {
4e54023805e14cf984b9f0041df73c16334a7a88ls sdinfo->satadrv_features_enabled &=
184cd04c26b064536977dfbb913a1240eaf6f708cth ~SATA_DEV_F_E_UNTAGGED_QING;
4e54023805e14cf984b9f0041df73c16334a7a88ls } else {
4e54023805e14cf984b9f0041df73c16334a7a88ls rval = -1;
4e54023805e14cf984b9f0041df73c16334a7a88ls }
4e54023805e14cf984b9f0041df73c16334a7a88ls } else {
4e54023805e14cf984b9f0041df73c16334a7a88ls rval = 0;
4e54023805e14cf984b9f0041df73c16334a7a88ls }
4e54023805e14cf984b9f0041df73c16334a7a88ls break;
4e54023805e14cf984b9f0041df73c16334a7a88ls case SCSI_CAP_TAGGED_QING:
4e54023805e14cf984b9f0041df73c16334a7a88ls /* This can TCQ or NCQ */
4e54023805e14cf984b9f0041df73c16334a7a88ls if (sata_func_enable & SATA_ENABLE_QUEUING &&
4e54023805e14cf984b9f0041df73c16334a7a88ls ((sdinfo->satadrv_features_support & SATA_DEV_F_TCQ &&
4e54023805e14cf984b9f0041df73c16334a7a88ls SATA_FEATURES(sata_hba_inst) & SATA_CTLF_QCMD) ||
4e54023805e14cf984b9f0041df73c16334a7a88ls (sata_func_enable & SATA_ENABLE_NCQ &&
4e54023805e14cf984b9f0041df73c16334a7a88ls sdinfo->satadrv_features_support & SATA_DEV_F_NCQ &&
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw SATA_FEATURES(sata_hba_inst) & SATA_CTLF_NCQ)) &&
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw (sdinfo->satadrv_max_queue_depth > 1)) {
4e54023805e14cf984b9f0041df73c16334a7a88ls rval = 1;
4e54023805e14cf984b9f0041df73c16334a7a88ls if (value == 1) {
4e54023805e14cf984b9f0041df73c16334a7a88ls sdinfo->satadrv_features_enabled |=
184cd04c26b064536977dfbb913a1240eaf6f708cth SATA_DEV_F_E_TAGGED_QING;
4e54023805e14cf984b9f0041df73c16334a7a88ls } else if (value == 0) {
4e54023805e14cf984b9f0041df73c16334a7a88ls sdinfo->satadrv_features_enabled &=
184cd04c26b064536977dfbb913a1240eaf6f708cth ~SATA_DEV_F_E_TAGGED_QING;
4e54023805e14cf984b9f0041df73c16334a7a88ls } else {
4e54023805e14cf984b9f0041df73c16334a7a88ls rval = -1;
4e54023805e14cf984b9f0041df73c16334a7a88ls }
4e54023805e14cf984b9f0041df73c16334a7a88ls } else {
4e54023805e14cf984b9f0041df73c16334a7a88ls rval = 0;
4e54023805e14cf984b9f0041df73c16334a7a88ls }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf default:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rval = -1;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (rval);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Implementations of scsi tran_destroy_pkt.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Free resources allocated by sata_scsi_init_pkt()
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_scsi_destroy_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_pkt_txlate_t *spx;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx = (sata_pkt_txlate_t *)pkt->pkt_ha_private;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
b5fc475bca6525d8da80728128eefb7100aaf66bap sata_common_free_dma_rsrcs(spx);
b5fc475bca6525d8da80728128eefb7100aaf66bap
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_sata_pkt->satapkt_cmd.satacmd_bp = NULL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_pkt_free(spx);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsi_hba_pkt_free(ap, pkt);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Implementation of scsi tran_dmafree.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Free DMA resources allocated by sata_scsi_init_pkt()
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_scsi_dmafree(struct scsi_address *ap, struct scsi_pkt *pkt)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#ifndef __lock_lint
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf _NOTE(ARGUNUSED(ap))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#endif
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_pkt_txlate_t *spx;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ASSERT(pkt != NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx = (sata_pkt_txlate_t *)pkt->pkt_ha_private;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
b5fc475bca6525d8da80728128eefb7100aaf66bap sata_common_free_dma_rsrcs(spx);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Implementation of scsi tran_sync_pkt.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * The assumption below is that pkt is unique - there is no need to check ap
7a70ede882eacbae00c8d5209afb443e7755684cpawelw *
7a70ede882eacbae00c8d5209afb443e7755684cpawelw * Synchronize DMA buffer and, if the intermediate buffer is used, copy data
7a70ede882eacbae00c8d5209afb443e7755684cpawelw * into/from the real buffer.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_scsi_sync_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#ifndef __lock_lint
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf _NOTE(ARGUNUSED(ap))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#endif
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int rval;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_pkt_txlate_t *spx = (sata_pkt_txlate_t *)pkt->pkt_ha_private;
7a70ede882eacbae00c8d5209afb443e7755684cpawelw struct buf *bp;
7a70ede882eacbae00c8d5209afb443e7755684cpawelw int direction;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
7a70ede882eacbae00c8d5209afb443e7755684cpawelw ASSERT(spx != NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (spx->txlt_buf_dma_handle != NULL) {
7a70ede882eacbae00c8d5209afb443e7755684cpawelw direction = spx->txlt_sata_pkt->
7a70ede882eacbae00c8d5209afb443e7755684cpawelw satapkt_cmd.satacmd_flags.sata_data_direction;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (spx->txlt_sata_pkt != NULL &&
7a70ede882eacbae00c8d5209afb443e7755684cpawelw direction != SATA_DIR_NODATA_XFER) {
7a70ede882eacbae00c8d5209afb443e7755684cpawelw if (spx->txlt_tmp_buf != NULL) {
7a70ede882eacbae00c8d5209afb443e7755684cpawelw /* Intermediate DMA buffer used */
7a70ede882eacbae00c8d5209afb443e7755684cpawelw bp = spx->txlt_sata_pkt->satapkt_cmd.satacmd_bp;
7a70ede882eacbae00c8d5209afb443e7755684cpawelw
7a70ede882eacbae00c8d5209afb443e7755684cpawelw if (direction & SATA_DIR_WRITE) {
7a70ede882eacbae00c8d5209afb443e7755684cpawelw bcopy(bp->b_un.b_addr,
7a70ede882eacbae00c8d5209afb443e7755684cpawelw spx->txlt_tmp_buf, bp->b_bcount);
7a70ede882eacbae00c8d5209afb443e7755684cpawelw }
7a70ede882eacbae00c8d5209afb443e7755684cpawelw }
7a70ede882eacbae00c8d5209afb443e7755684cpawelw /* Sync the buffer for device or for CPU */
7a70ede882eacbae00c8d5209afb443e7755684cpawelw rval = ddi_dma_sync(spx->txlt_buf_dma_handle, 0, 0,
7a70ede882eacbae00c8d5209afb443e7755684cpawelw (direction & SATA_DIR_WRITE) ?
7a70ede882eacbae00c8d5209afb443e7755684cpawelw DDI_DMA_SYNC_FORDEV : DDI_DMA_SYNC_FORCPU);
7a70ede882eacbae00c8d5209afb443e7755684cpawelw ASSERT(rval == DDI_SUCCESS);
7a70ede882eacbae00c8d5209afb443e7755684cpawelw if (spx->txlt_tmp_buf != NULL &&
7a70ede882eacbae00c8d5209afb443e7755684cpawelw !(direction & SATA_DIR_WRITE)) {
7a70ede882eacbae00c8d5209afb443e7755684cpawelw /* Intermediate DMA buffer used for read */
7a70ede882eacbae00c8d5209afb443e7755684cpawelw bcopy(spx->txlt_tmp_buf,
7a70ede882eacbae00c8d5209afb443e7755684cpawelw bp->b_un.b_addr, bp->b_bcount);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
7a70ede882eacbae00c8d5209afb443e7755684cpawelw
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/* ******************* SATA - SCSI Translation functions **************** */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * SCSI to SATA pkt and command translation and SATA to SCSI status/error
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * translation.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Checks if a device exists and can be access and translates common
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * scsi_pkt data to sata_pkt data.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
5613bc2e005997fad3da93edffa0a790eda9d130pawelw * Returns TRAN_ACCEPT and scsi pkt_reason CMD_CMPLT if device exists and
5613bc2e005997fad3da93edffa0a790eda9d130pawelw * sata_pkt was set-up.
5613bc2e005997fad3da93edffa0a790eda9d130pawelw * Returns TRAN_ACCEPT and scsi pkt_reason CMD_DEV_GONE if device does not
5613bc2e005997fad3da93edffa0a790eda9d130pawelw * exist and pkt_comp callback was scheduled.
5613bc2e005997fad3da93edffa0a790eda9d130pawelw * Returns other TRAN_XXXXX values when error occured and command should be
5613bc2e005997fad3da93edffa0a790eda9d130pawelw * rejected with the returned TRAN_XXXXX value.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * This function should be called with port mutex held.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int
f39c049be37ba5b8f96704f41d6532332ae16318pawelwsata_txlt_generic_pkt_info(sata_pkt_txlate_t *spx, int *reason)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_drive_info_t *sdinfo;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device_t sata_device;
c03acfcad7780db4ddf763511a82026680b3b2c1ls const struct sata_cmd_flags sata_initial_cmd_flags = {
c03acfcad7780db4ddf763511a82026680b3b2c1ls SATA_DIR_NODATA_XFER,
c03acfcad7780db4ddf763511a82026680b3b2c1ls /* all other values to 0/FALSE */
c03acfcad7780db4ddf763511a82026680b3b2c1ls };
5613bc2e005997fad3da93edffa0a790eda9d130pawelw /*
5613bc2e005997fad3da93edffa0a790eda9d130pawelw * Pkt_reason has to be set if the pkt_comp callback is invoked,
5613bc2e005997fad3da93edffa0a790eda9d130pawelw * and that implies TRAN_ACCEPT return value. Any other returned value
5613bc2e005997fad3da93edffa0a790eda9d130pawelw * indicates that the scsi packet was not accepted (the reason will not
f39c049be37ba5b8f96704f41d6532332ae16318pawelw * be checked by the scsi target driver).
5613bc2e005997fad3da93edffa0a790eda9d130pawelw * To make debugging easier, we set pkt_reason to know value here.
5613bc2e005997fad3da93edffa0a790eda9d130pawelw * It may be changed later when different completion reason is
5613bc2e005997fad3da93edffa0a790eda9d130pawelw * determined.
5613bc2e005997fad3da93edffa0a790eda9d130pawelw */
5613bc2e005997fad3da93edffa0a790eda9d130pawelw spx->txlt_scsi_pkt->pkt_reason = CMD_TRAN_ERR;
f39c049be37ba5b8f96704f41d6532332ae16318pawelw *reason = CMD_TRAN_ERR;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Validate address */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf switch (sata_validate_scsi_address(spx->txlt_sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf &spx->txlt_scsi_pkt->pkt_address, &sata_device)) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case -1:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Invalid address or invalid device type */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (TRAN_BADPKT);
a9d5ae2e08c504913c088349c3d4c144f3c92be8Pawel Wojcik case 2:
a9d5ae2e08c504913c088349c3d4c144f3c92be8Pawel Wojcik /*
a9d5ae2e08c504913c088349c3d4c144f3c92be8Pawel Wojcik * Valid address but device type is unknown - Chack if it is
a9d5ae2e08c504913c088349c3d4c144f3c92be8Pawel Wojcik * in the reset state and therefore in an indeterminate state.
a9d5ae2e08c504913c088349c3d4c144f3c92be8Pawel Wojcik */
a9d5ae2e08c504913c088349c3d4c144f3c92be8Pawel Wojcik sdinfo = sata_get_device_info(spx->txlt_sata_hba_inst,
a9d5ae2e08c504913c088349c3d4c144f3c92be8Pawel Wojcik &spx->txlt_sata_pkt->satapkt_device);
a9d5ae2e08c504913c088349c3d4c144f3c92be8Pawel Wojcik if (sdinfo != NULL && (sdinfo->satadrv_event_flags &
a9d5ae2e08c504913c088349c3d4c144f3c92be8Pawel Wojcik (SATA_EVNT_DEVICE_RESET |
a9d5ae2e08c504913c088349c3d4c144f3c92be8Pawel Wojcik SATA_EVNT_INPROC_DEVICE_RESET)) != 0) {
a9d5ae2e08c504913c088349c3d4c144f3c92be8Pawel Wojcik if (!ddi_in_panic()) {
a9d5ae2e08c504913c088349c3d4c144f3c92be8Pawel Wojcik spx->txlt_scsi_pkt->pkt_reason = CMD_INCOMPLETE;
a9d5ae2e08c504913c088349c3d4c144f3c92be8Pawel Wojcik *reason = CMD_INCOMPLETE;
a9d5ae2e08c504913c088349c3d4c144f3c92be8Pawel Wojcik SATADBG1(SATA_DBG_SCSI_IF,
a9d5ae2e08c504913c088349c3d4c144f3c92be8Pawel Wojcik spx->txlt_sata_hba_inst,
a9d5ae2e08c504913c088349c3d4c144f3c92be8Pawel Wojcik "sata_scsi_start: rejecting command "
a9d5ae2e08c504913c088349c3d4c144f3c92be8Pawel Wojcik "because of device reset state\n", NULL);
a9d5ae2e08c504913c088349c3d4c144f3c92be8Pawel Wojcik return (TRAN_BUSY);
a9d5ae2e08c504913c088349c3d4c144f3c92be8Pawel Wojcik }
a9d5ae2e08c504913c088349c3d4c144f3c92be8Pawel Wojcik }
a9d5ae2e08c504913c088349c3d4c144f3c92be8Pawel Wojcik /* FALLTHROUGH */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case 1:
a9d5ae2e08c504913c088349c3d4c144f3c92be8Pawel Wojcik /* valid address but no valid device - it has disappeared */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_scsi_pkt->pkt_reason = CMD_DEV_GONE;
f39c049be37ba5b8f96704f41d6532332ae16318pawelw *reason = CMD_DEV_GONE;
4360436b3c604bc28d37be269ad152b4c38157c3pawelw /*
4360436b3c604bc28d37be269ad152b4c38157c3pawelw * The sd target driver is checking CMD_DEV_GONE pkt_reason
4360436b3c604bc28d37be269ad152b4c38157c3pawelw * only in callback function (for normal requests) and
4360436b3c604bc28d37be269ad152b4c38157c3pawelw * in the dump code path.
4360436b3c604bc28d37be269ad152b4c38157c3pawelw * So, if the callback is available, we need to do
4360436b3c604bc28d37be269ad152b4c38157c3pawelw * the callback rather than returning TRAN_FATAL_ERROR here.
4360436b3c604bc28d37be269ad152b4c38157c3pawelw */
4360436b3c604bc28d37be269ad152b4c38157c3pawelw if (spx->txlt_scsi_pkt->pkt_comp != NULL) {
4360436b3c604bc28d37be269ad152b4c38157c3pawelw /* scsi callback required */
4360436b3c604bc28d37be269ad152b4c38157c3pawelw if (taskq_dispatch(SATA_TXLT_TASKQ(spx),
4360436b3c604bc28d37be269ad152b4c38157c3pawelw (task_func_t *)spx->txlt_scsi_pkt->pkt_comp,
4360436b3c604bc28d37be269ad152b4c38157c3pawelw (void *)spx->txlt_scsi_pkt,
4360436b3c604bc28d37be269ad152b4c38157c3pawelw TQ_SLEEP) == NULL)
4360436b3c604bc28d37be269ad152b4c38157c3pawelw /* Scheduling the callback failed */
4360436b3c604bc28d37be269ad152b4c38157c3pawelw return (TRAN_BUSY);
4360436b3c604bc28d37be269ad152b4c38157c3pawelw
4360436b3c604bc28d37be269ad152b4c38157c3pawelw return (TRAN_ACCEPT);
4360436b3c604bc28d37be269ad152b4c38157c3pawelw }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (TRAN_FATAL_ERROR);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf default:
f39c049be37ba5b8f96704f41d6532332ae16318pawelw /* all OK; pkt reason will be overwritten later */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik /*
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik * If in an interrupt context, reject packet if it is to be
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik * executed in polling mode
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik */
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik if (servicing_interrupt() &&
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik (spx->txlt_scsi_pkt->pkt_flags & FLAG_NOINTR) != 0) {
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik SATADBG1(SATA_DBG_INTR_CTX, spx->txlt_sata_hba_inst,
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik "sata_scsi_start: rejecting synchronous command because "
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik "of interrupt context\n", NULL);
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik return (TRAN_BUSY);
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik }
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo = sata_get_device_info(spx->txlt_sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf &spx->txlt_sata_pkt->satapkt_device);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * If device is in reset condition, reject the packet with
4360436b3c604bc28d37be269ad152b4c38157c3pawelw * TRAN_BUSY, unless:
4360436b3c604bc28d37be269ad152b4c38157c3pawelw * 1. system is panicking (dumping)
4360436b3c604bc28d37be269ad152b4c38157c3pawelw * In such case only one thread is running and there is no way to
4360436b3c604bc28d37be269ad152b4c38157c3pawelw * process reset.
4360436b3c604bc28d37be269ad152b4c38157c3pawelw * 2. cfgadm operation is is progress (internal APCTL lock is set)
4360436b3c604bc28d37be269ad152b4c38157c3pawelw * Some cfgadm operations involve drive commands, so reset condition
4360436b3c604bc28d37be269ad152b4c38157c3pawelw * needs to be ignored for IOCTL operations.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
415e5120fdbacf132d1845300d92a6cd74eed2fayt if ((sdinfo->satadrv_event_flags &
4360436b3c604bc28d37be269ad152b4c38157c3pawelw (SATA_EVNT_DEVICE_RESET | SATA_EVNT_INPROC_DEVICE_RESET)) != 0) {
4360436b3c604bc28d37be269ad152b4c38157c3pawelw
4360436b3c604bc28d37be269ad152b4c38157c3pawelw if (!ddi_in_panic() &&
4360436b3c604bc28d37be269ad152b4c38157c3pawelw ((SATA_CPORT_EVENT_FLAGS(spx->txlt_sata_hba_inst,
4360436b3c604bc28d37be269ad152b4c38157c3pawelw sata_device.satadev_addr.cport) &
4360436b3c604bc28d37be269ad152b4c38157c3pawelw SATA_APCTL_LOCK_PORT_BUSY) == 0)) {
4360436b3c604bc28d37be269ad152b4c38157c3pawelw spx->txlt_scsi_pkt->pkt_reason = CMD_INCOMPLETE;
f39c049be37ba5b8f96704f41d6532332ae16318pawelw *reason = CMD_INCOMPLETE;
4360436b3c604bc28d37be269ad152b4c38157c3pawelw SATADBG1(SATA_DBG_SCSI_IF, spx->txlt_sata_hba_inst,
4360436b3c604bc28d37be269ad152b4c38157c3pawelw "sata_scsi_start: rejecting command because "
4360436b3c604bc28d37be269ad152b4c38157c3pawelw "of device reset state\n", NULL);
4360436b3c604bc28d37be269ad152b4c38157c3pawelw return (TRAN_BUSY);
4360436b3c604bc28d37be269ad152b4c38157c3pawelw }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Fix the dev_type in the sata_pkt->satapkt_device. It was not set by
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * sata_scsi_pkt_init() because pkt init had to work also with
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * non-existing devices.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Now we know that the packet was set-up for a real device, so its
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * type is known.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_sata_pkt->satapkt_device.satadev_type = sdinfo->satadrv_type;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
c03acfcad7780db4ddf763511a82026680b3b2c1ls spx->txlt_sata_pkt->satapkt_cmd.satacmd_flags = sata_initial_cmd_flags;
4360436b3c604bc28d37be269ad152b4c38157c3pawelw if ((SATA_CPORT_INFO(spx->txlt_sata_hba_inst,
4360436b3c604bc28d37be269ad152b4c38157c3pawelw sata_device.satadev_addr.cport)->cport_event_flags &
4360436b3c604bc28d37be269ad152b4c38157c3pawelw SATA_APCTL_LOCK_PORT_BUSY) != 0) {
4360436b3c604bc28d37be269ad152b4c38157c3pawelw spx->txlt_sata_pkt->satapkt_cmd.satacmd_flags.
4360436b3c604bc28d37be269ad152b4c38157c3pawelw sata_ignore_dev_reset = B_TRUE;
4360436b3c604bc28d37be269ad152b4c38157c3pawelw }
5613bc2e005997fad3da93edffa0a790eda9d130pawelw /*
5613bc2e005997fad3da93edffa0a790eda9d130pawelw * At this point the generic translation routine determined that the
5613bc2e005997fad3da93edffa0a790eda9d130pawelw * scsi packet should be accepted. Packet completion reason may be
5613bc2e005997fad3da93edffa0a790eda9d130pawelw * changed later when a different completion reason is determined.
5613bc2e005997fad3da93edffa0a790eda9d130pawelw */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_scsi_pkt->pkt_reason = CMD_CMPLT;
f39c049be37ba5b8f96704f41d6532332ae16318pawelw *reason = CMD_CMPLT;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((spx->txlt_scsi_pkt->pkt_flags & FLAG_NOINTR) != 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Synchronous execution */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_sata_pkt->satapkt_op_mode = SATA_OPMODE_SYNCH |
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_OPMODE_POLLING;
378040a149d10e2dec3b32b5cc4bb774c5952550ls spx->txlt_sata_pkt->satapkt_cmd.satacmd_flags.
378040a149d10e2dec3b32b5cc4bb774c5952550ls sata_ignore_dev_reset = ddi_in_panic();
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Asynchronous execution */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_sata_pkt->satapkt_op_mode = SATA_OPMODE_ASYNCH |
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_OPMODE_INTERRUPTS;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Convert queuing information */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (spx->txlt_scsi_pkt->pkt_flags & FLAG_STAG)
c03acfcad7780db4ddf763511a82026680b3b2c1ls spx->txlt_sata_pkt->satapkt_cmd.satacmd_flags.sata_queue_stag =
c03acfcad7780db4ddf763511a82026680b3b2c1ls B_TRUE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf else if (spx->txlt_scsi_pkt->pkt_flags &
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (FLAG_OTAG | FLAG_HTAG | FLAG_HEAD))
c03acfcad7780db4ddf763511a82026680b3b2c1ls spx->txlt_sata_pkt->satapkt_cmd.satacmd_flags.sata_queue_otag =
c03acfcad7780db4ddf763511a82026680b3b2c1ls B_TRUE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Always limit pkt time */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (spx->txlt_scsi_pkt->pkt_time == 0)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_sata_pkt->satapkt_time = sata_default_pkt_time;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf else
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Pass on scsi_pkt time */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_sata_pkt->satapkt_time =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_scsi_pkt->pkt_time;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (TRAN_ACCEPT);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Translate ATA Identify Device data to SCSI Inquiry data.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * This function may be called only for ATA devices.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * This function should not be called for ATAPI devices - they
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * respond directly to SCSI Inquiry command.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown *
2ce278eb5cbdc9cfe3f361f2144877964b5a35cbying tian - Beijing China * SATA Identify Device data has to be valid in sata_drive_info.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Buffer has to accomodate the inquiry length (36 bytes).
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * This function should be called with a port mutex held.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_identdev_to_inquiry(sata_hba_inst_t *sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_drive_info_t *sdinfo, uint8_t *buf)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf struct scsi_inquiry *inq = (struct scsi_inquiry *)buf;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf struct sata_id *sid = &sdinfo->satadrv_id;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
c03acfcad7780db4ddf763511a82026680b3b2c1ls /* Start with a nice clean slate */
c03acfcad7780db4ddf763511a82026680b3b2c1ls bzero((void *)inq, sizeof (struct scsi_inquiry));
c03acfcad7780db4ddf763511a82026680b3b2c1ls
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Rely on the dev_type for setting paripheral qualifier.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Assume that DTYPE_RODIRECT applies to CD/DVD R/W devices.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * It could be that DTYPE_OPTICAL could also qualify in the future.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * ATAPI Inquiry may provide more data to the target driver.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf inq->inq_dtype = sdinfo->satadrv_type == SATA_DTYPE_ATADISK ?
2038334ab26baaa43c9083f35def041511c3cc1fUnknown DTYPE_DIRECT : DTYPE_RODIRECT; /* DTYPE_UNKNOWN; */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2ce278eb5cbdc9cfe3f361f2144877964b5a35cbying tian - Beijing China /* CFA type device is not a removable media device */
2ce278eb5cbdc9cfe3f361f2144877964b5a35cbying tian - Beijing China inq->inq_rmb = ((sid->ai_config != SATA_CFA_TYPE) &&
2ce278eb5cbdc9cfe3f361f2144877964b5a35cbying tian - Beijing China (sid->ai_config & SATA_REM_MEDIA)) ? 1 : 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf inq->inq_qual = 0; /* Device type qualifier (obsolete in SCSI3? */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf inq->inq_iso = 0; /* ISO version */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf inq->inq_ecma = 0; /* ECMA version */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf inq->inq_ansi = 3; /* ANSI version - SCSI 3 */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf inq->inq_aenc = 0; /* Async event notification cap. */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown inq->inq_trmiop = 0; /* Supports TERMINATE I/O PROC msg - NO */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf inq->inq_normaca = 0; /* setting NACA bit supported - NO */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf inq->inq_rdf = RDF_SCSI2; /* Response data format- SPC-3 */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf inq->inq_len = 31; /* Additional length */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf inq->inq_dualp = 0; /* dual port device - NO */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf inq->inq_reladdr = 0; /* Supports relative addressing - NO */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf inq->inq_sync = 0; /* Supports synchronous data xfers - NO */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf inq->inq_linked = 0; /* Supports linked commands - NO */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Queuing support - controller has to
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * support some sort of command queuing.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (SATA_QDEPTH(sata_hba_inst) > 1)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf inq->inq_cmdque = 1; /* Supports command queueing - YES */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf else
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf inq->inq_cmdque = 0; /* Supports command queueing - NO */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf inq->inq_sftre = 0; /* Supports Soft Reset option - NO ??? */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf inq->inq_wbus32 = 0; /* Supports 32 bit wide data xfers - NO */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf inq->inq_wbus16 = 0; /* Supports 16 bit wide data xfers - NO */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
184cd04c26b064536977dfbb913a1240eaf6f708cth#ifdef _LITTLE_ENDIAN
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Swap text fields to match SCSI format */
c03acfcad7780db4ddf763511a82026680b3b2c1ls bcopy("ATA ", inq->inq_vid, 8); /* Vendor ID */
c03acfcad7780db4ddf763511a82026680b3b2c1ls swab(sid->ai_model, inq->inq_pid, 16); /* Product ID */
c03acfcad7780db4ddf763511a82026680b3b2c1ls if (strncmp(&sid->ai_fw[4], " ", 4) == 0)
c03acfcad7780db4ddf763511a82026680b3b2c1ls swab(sid->ai_fw, inq->inq_revision, 4); /* Revision level */
c03acfcad7780db4ddf763511a82026680b3b2c1ls else
c03acfcad7780db4ddf763511a82026680b3b2c1ls swab(&sid->ai_fw[4], inq->inq_revision, 4); /* Rev. level */
184cd04c26b064536977dfbb913a1240eaf6f708cth#else /* _LITTLE_ENDIAN */
184cd04c26b064536977dfbb913a1240eaf6f708cth bcopy("ATA ", inq->inq_vid, 8); /* Vendor ID */
184cd04c26b064536977dfbb913a1240eaf6f708cth bcopy(sid->ai_model, inq->inq_pid, 16); /* Product ID */
c03acfcad7780db4ddf763511a82026680b3b2c1ls if (strncmp(&sid->ai_fw[4], " ", 4) == 0)
c03acfcad7780db4ddf763511a82026680b3b2c1ls bcopy(sid->ai_fw, inq->inq_revision, 4); /* Revision level */
c03acfcad7780db4ddf763511a82026680b3b2c1ls else
c03acfcad7780db4ddf763511a82026680b3b2c1ls bcopy(&sid->ai_fw[4], inq->inq_revision, 4); /* Rev. level */
184cd04c26b064536977dfbb913a1240eaf6f708cth#endif /* _LITTLE_ENDIAN */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Scsi response set up for invalid command (command not supported)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Returns TRAN_ACCEPT and appropriate values in scsi_pkt fields.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_txlt_invalid_command(sata_pkt_txlate_t *spx)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf struct scsi_pkt *scsipkt = spx->txlt_scsi_pkt;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf struct scsi_extended_sense *sense;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsipkt->pkt_reason = CMD_CMPLT;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsipkt->pkt_state = STATE_GOT_BUS | STATE_GOT_TARGET |
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf STATE_SENT_CMD | STATE_GOT_STATUS;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *scsipkt->pkt_scbp = STATUS_CHECK;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense = sata_arq_sense(spx);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense->es_key = KEY_ILLEGAL_REQUEST;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sense->es_add_code = SD_SCSI_ASC_INVALID_COMMAND_CODE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG1(SATA_DBG_SCSI_IF, spx->txlt_sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "Scsi_pkt completion reason %x\n", scsipkt->pkt_reason);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((scsipkt->pkt_flags & FLAG_NOINTR) == 0 &&
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsipkt->pkt_comp != NULL)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* scsi callback required */
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw if (taskq_dispatch(SATA_TXLT_TASKQ(spx),
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw (task_func_t *)spx->txlt_scsi_pkt->pkt_comp,
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw (void *)spx->txlt_scsi_pkt,
4360436b3c604bc28d37be269ad152b4c38157c3pawelw TQ_SLEEP) == NULL)
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw /* Scheduling the callback failed */
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw return (TRAN_BUSY);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (TRAN_ACCEPT);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu/*
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu * Scsi response set up for check condition with special sense key
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu * and additional sense code.
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu *
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu * Returns TRAN_ACCEPT and appropriate values in scsi_pkt fields.
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu */
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chustatic int
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chusata_txlt_check_condition(sata_pkt_txlate_t *spx, uchar_t key, uchar_t code)
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu{
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sata_hba_inst_t *shi = SATA_TXLT_HBA_INST(spx);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu int cport = SATA_TXLT_CPORT(spx);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu struct scsi_pkt *scsipkt = spx->txlt_scsi_pkt;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu struct scsi_extended_sense *sense;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu mutex_enter(&SATA_CPORT_MUTEX(shi, cport));
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu scsipkt->pkt_reason = CMD_CMPLT;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu scsipkt->pkt_state = STATE_GOT_BUS | STATE_GOT_TARGET |
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu STATE_SENT_CMD | STATE_GOT_STATUS;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu *scsipkt->pkt_scbp = STATUS_CHECK;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sense = sata_arq_sense(spx);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sense->es_key = key;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sense->es_add_code = code;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu mutex_exit(&SATA_CPORT_MUTEX(shi, cport));
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu SATADBG1(SATA_DBG_SCSI_IF, spx->txlt_sata_hba_inst,
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu "Scsi_pkt completion reason %x\n", scsipkt->pkt_reason);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if ((scsipkt->pkt_flags & FLAG_NOINTR) == 0)
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu /* scsi callback required */
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if (taskq_dispatch(SATA_TXLT_TASKQ(spx),
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu (task_func_t *)scsi_hba_pkt_comp,
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu (void *)spx->txlt_scsi_pkt,
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu TQ_SLEEP) == NULL)
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu /* Scheduling the callback failed */
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu return (TRAN_BUSY);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu return (TRAN_ACCEPT);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu}
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Scsi response setup for
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * emulated non-data command that requires no action/return data
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Returns TRAN_ACCEPT and appropriate values in scsi_pkt fields.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chustatic int
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_txlt_nodata_cmd_immediate(sata_pkt_txlate_t *spx)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int rval;
f39c049be37ba5b8f96704f41d6532332ae16318pawelw int reason;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&(SATA_TXLT_CPORT_MUTEX(spx)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
f39c049be37ba5b8f96704f41d6532332ae16318pawelw if (((rval = sata_txlt_generic_pkt_info(spx, &reason)) !=
f39c049be37ba5b8f96704f41d6532332ae16318pawelw TRAN_ACCEPT) || (reason == CMD_DEV_GONE)) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&(SATA_TXLT_CPORT_MUTEX(spx)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (rval);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&(SATA_TXLT_CPORT_MUTEX(spx)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_scsi_pkt->pkt_state = STATE_GOT_BUS | STATE_GOT_TARGET |
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf STATE_SENT_CMD | STATE_GOT_STATUS;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_scsi_pkt->pkt_reason = CMD_CMPLT;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *(spx->txlt_scsi_pkt->pkt_scbp) = STATUS_GOOD;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG1(SATA_DBG_SCSI_IF, spx->txlt_sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "Scsi_pkt completion reason %x\n",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_scsi_pkt->pkt_reason);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((spx->txlt_scsi_pkt->pkt_flags & FLAG_NOINTR) == 0 &&
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_scsi_pkt->pkt_comp != NULL)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* scsi callback required */
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw if (taskq_dispatch(SATA_TXLT_TASKQ(spx),
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw (task_func_t *)spx->txlt_scsi_pkt->pkt_comp,
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw (void *)spx->txlt_scsi_pkt,
4360436b3c604bc28d37be269ad152b4c38157c3pawelw TQ_SLEEP) == NULL)
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw /* Scheduling the callback failed */
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw return (TRAN_BUSY);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (TRAN_ACCEPT);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * SATA translate command: Inquiry / Identify Device
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Use cached Identify Device data for now, rather than issuing actual
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Device Identify cmd request. If device is detached and re-attached,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * asynchronous event processing should fetch and refresh Identify Device
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * data.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Two VPD pages are supported now:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Vital Product Data page
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Unit Serial Number page
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Returns TRAN_ACCEPT and appropriate values in scsi_pkt fields.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#define EVPD 1 /* Extended Vital Product Data flag */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#define CMDDT 2 /* Command Support Data - Obsolete */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#define INQUIRY_SUP_VPD_PAGE 0 /* Supported VDP Pages Page COde */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#define INQUIRY_USN_PAGE 0x80 /* Unit Serial Number Page Code */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#define INQUIRY_DEV_IDENTIFICATION_PAGE 0x83 /* Not needed yet */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_txlt_inquiry(sata_pkt_txlate_t *spx)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf struct scsi_pkt *scsipkt = spx->txlt_scsi_pkt;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf struct buf *bp = spx->txlt_sata_pkt->satapkt_cmd.satacmd_bp;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_drive_info_t *sdinfo;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf struct scsi_extended_sense *sense;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int count;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf uint8_t *p;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int i, j;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf uint8_t page_buf[0xff]; /* Max length */
f39c049be37ba5b8f96704f41d6532332ae16318pawelw int rval, reason;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&(SATA_TXLT_CPORT_MUTEX(spx)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
f39c049be37ba5b8f96704f41d6532332ae16318pawelw if (((rval = sata_txlt_generic_pkt_info(spx, &reason)) !=
f39c049be37ba5b8f96704f41d6532332ae16318pawelw TRAN_ACCEPT) || (reason == CMD_DEV_GONE)) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&(SATA_TXLT_CPORT_MUTEX(spx)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (rval);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo = sata_get_device_info(spx->txlt_sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf &spx->txlt_sata_pkt->satapkt_device);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ASSERT(sdinfo != NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsipkt->pkt_reason = CMD_CMPLT;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsipkt->pkt_state = STATE_GOT_BUS | STATE_GOT_TARGET |
184cd04c26b064536977dfbb913a1240eaf6f708cth STATE_SENT_CMD | STATE_GOT_STATUS;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Reject not supported request */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (scsipkt->pkt_cdbp[1] & CMDDT) { /* No support for this bit */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *scsipkt->pkt_scbp = STATUS_CHECK;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense = sata_arq_sense(spx);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense->es_key = KEY_ILLEGAL_REQUEST;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sense->es_add_code = SD_SCSI_ASC_INVALID_FIELD_IN_CDB;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf goto done;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Valid Inquiry request */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *scsipkt->pkt_scbp = STATUS_GOOD;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (bp != NULL && bp->b_un.b_addr && bp->b_bcount) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
8d483882aa3390058094b043f3d62187b5d1de03mlf /*
8d483882aa3390058094b043f3d62187b5d1de03mlf * Because it is fully emulated command storing data
8d483882aa3390058094b043f3d62187b5d1de03mlf * programatically in the specified buffer, release
8d483882aa3390058094b043f3d62187b5d1de03mlf * preallocated DMA resources before storing data in the buffer,
8d483882aa3390058094b043f3d62187b5d1de03mlf * so no unwanted DMA sync would take place.
8d483882aa3390058094b043f3d62187b5d1de03mlf */
8d483882aa3390058094b043f3d62187b5d1de03mlf sata_scsi_dmafree(NULL, scsipkt);
8d483882aa3390058094b043f3d62187b5d1de03mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (!(scsipkt->pkt_cdbp[1] & EVPD)) {
8d483882aa3390058094b043f3d62187b5d1de03mlf /* Standard Inquiry Data request */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf struct scsi_inquiry inq;
c03acfcad7780db4ddf763511a82026680b3b2c1ls unsigned int bufsize;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_identdev_to_inquiry(spx->txlt_sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo, (uint8_t *)&inq);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Copy no more than requested */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf count = MIN(bp->b_bcount,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sizeof (struct scsi_inquiry));
c03acfcad7780db4ddf763511a82026680b3b2c1ls bufsize = scsipkt->pkt_cdbp[4];
c03acfcad7780db4ddf763511a82026680b3b2c1ls bufsize |= scsipkt->pkt_cdbp[3] << 8;
c03acfcad7780db4ddf763511a82026680b3b2c1ls count = MIN(count, bufsize);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf bcopy(&inq, bp->b_un.b_addr, count);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsipkt->pkt_state |= STATE_XFERRED_DATA;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsipkt->pkt_resid = scsipkt->pkt_cdbp[4] > count ?
c03acfcad7780db4ddf763511a82026680b3b2c1ls bufsize - count : 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * peripheral_qualifier = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * We are dealing only with HD and will be
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * dealing with CD/DVD devices soon
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf uint8_t peripheral_device_type =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_type == SATA_DTYPE_ATADISK ?
184cd04c26b064536977dfbb913a1240eaf6f708cth DTYPE_DIRECT : DTYPE_RODIRECT;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf switch ((uint_t)scsipkt->pkt_cdbp[2]) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case INQUIRY_SUP_VPD_PAGE:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Request for suported Vital Product Data
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * pages - assuming only 2 page codes
275e36bf470b114b8fe92ae8574f8db1a3d7c053Pawel Wojcik * supported.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf page_buf[0] = peripheral_device_type;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf page_buf[1] = INQUIRY_SUP_VPD_PAGE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf page_buf[2] = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf page_buf[3] = 2; /* page length */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf page_buf[4] = INQUIRY_SUP_VPD_PAGE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf page_buf[5] = INQUIRY_USN_PAGE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Copy no more than requested */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf count = MIN(bp->b_bcount, 6);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf bcopy(page_buf, bp->b_un.b_addr, count);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
275e36bf470b114b8fe92ae8574f8db1a3d7c053Pawel Wojcik
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case INQUIRY_USN_PAGE:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
275e36bf470b114b8fe92ae8574f8db1a3d7c053Pawel Wojcik * Request for Unit Serial Number page.
275e36bf470b114b8fe92ae8574f8db1a3d7c053Pawel Wojcik * Set-up the page.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf page_buf[0] = peripheral_device_type;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf page_buf[1] = INQUIRY_USN_PAGE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf page_buf[2] = 0;
275e36bf470b114b8fe92ae8574f8db1a3d7c053Pawel Wojcik /* remaining page length */
275e36bf470b114b8fe92ae8574f8db1a3d7c053Pawel Wojcik page_buf[3] = SATA_ID_SERIAL_LEN;
275e36bf470b114b8fe92ae8574f8db1a3d7c053Pawel Wojcik
275e36bf470b114b8fe92ae8574f8db1a3d7c053Pawel Wojcik /*
275e36bf470b114b8fe92ae8574f8db1a3d7c053Pawel Wojcik * Copy serial number from Identify Device data
275e36bf470b114b8fe92ae8574f8db1a3d7c053Pawel Wojcik * words into the inquiry page and swap bytes
275e36bf470b114b8fe92ae8574f8db1a3d7c053Pawel Wojcik * when necessary.
275e36bf470b114b8fe92ae8574f8db1a3d7c053Pawel Wojcik */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf p = (uint8_t *)(sdinfo->satadrv_id.ai_drvser);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#ifdef _LITTLE_ENDIAN
275e36bf470b114b8fe92ae8574f8db1a3d7c053Pawel Wojcik swab(p, &page_buf[4], SATA_ID_SERIAL_LEN);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#else
275e36bf470b114b8fe92ae8574f8db1a3d7c053Pawel Wojcik bcopy(p, &page_buf[4], SATA_ID_SERIAL_LEN);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#endif
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Least significant character of the serial
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * number shall appear as the last byte,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * according to SBC-3 spec.
275e36bf470b114b8fe92ae8574f8db1a3d7c053Pawel Wojcik * Count trailing spaces to determine the
275e36bf470b114b8fe92ae8574f8db1a3d7c053Pawel Wojcik * necessary shift length.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
275e36bf470b114b8fe92ae8574f8db1a3d7c053Pawel Wojcik p = &page_buf[SATA_ID_SERIAL_LEN + 4 - 1];
275e36bf470b114b8fe92ae8574f8db1a3d7c053Pawel Wojcik for (j = 0; j < SATA_ID_SERIAL_LEN; j++) {
275e36bf470b114b8fe92ae8574f8db1a3d7c053Pawel Wojcik if (*(p - j) != '\0' &&
275e36bf470b114b8fe92ae8574f8db1a3d7c053Pawel Wojcik *(p - j) != '\040')
275e36bf470b114b8fe92ae8574f8db1a3d7c053Pawel Wojcik break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
275e36bf470b114b8fe92ae8574f8db1a3d7c053Pawel Wojcik
275e36bf470b114b8fe92ae8574f8db1a3d7c053Pawel Wojcik /*
275e36bf470b114b8fe92ae8574f8db1a3d7c053Pawel Wojcik * Shift SN string right, so that the last
275e36bf470b114b8fe92ae8574f8db1a3d7c053Pawel Wojcik * non-blank character would appear in last
275e36bf470b114b8fe92ae8574f8db1a3d7c053Pawel Wojcik * byte of SN field in the page.
275e36bf470b114b8fe92ae8574f8db1a3d7c053Pawel Wojcik * 'j' is the shift length.
275e36bf470b114b8fe92ae8574f8db1a3d7c053Pawel Wojcik */
275e36bf470b114b8fe92ae8574f8db1a3d7c053Pawel Wojcik for (i = 0;
275e36bf470b114b8fe92ae8574f8db1a3d7c053Pawel Wojcik i < (SATA_ID_SERIAL_LEN - j) && j != 0;
275e36bf470b114b8fe92ae8574f8db1a3d7c053Pawel Wojcik i++, p--)
275e36bf470b114b8fe92ae8574f8db1a3d7c053Pawel Wojcik *p = *(p - j);
275e36bf470b114b8fe92ae8574f8db1a3d7c053Pawel Wojcik
275e36bf470b114b8fe92ae8574f8db1a3d7c053Pawel Wojcik /*
275e36bf470b114b8fe92ae8574f8db1a3d7c053Pawel Wojcik * Add leading spaces - same number as the
275e36bf470b114b8fe92ae8574f8db1a3d7c053Pawel Wojcik * shift size
275e36bf470b114b8fe92ae8574f8db1a3d7c053Pawel Wojcik */
275e36bf470b114b8fe92ae8574f8db1a3d7c053Pawel Wojcik for (; j > 0; j--)
275e36bf470b114b8fe92ae8574f8db1a3d7c053Pawel Wojcik page_buf[4 + j - 1] = '\040';
275e36bf470b114b8fe92ae8574f8db1a3d7c053Pawel Wojcik
275e36bf470b114b8fe92ae8574f8db1a3d7c053Pawel Wojcik count = MIN(bp->b_bcount,
275e36bf470b114b8fe92ae8574f8db1a3d7c053Pawel Wojcik SATA_ID_SERIAL_LEN + 4);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf bcopy(page_buf, bp->b_un.b_addr, count);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case INQUIRY_DEV_IDENTIFICATION_PAGE:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * We may want to implement this page, when
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * identifiers are common for SATA devices
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * But not now.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
4360436b3c604bc28d37be269ad152b4c38157c3pawelw /*FALLTHROUGH*/
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf default:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Request for unsupported VPD page */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *scsipkt->pkt_scbp = STATUS_CHECK;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense = sata_arq_sense(spx);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense->es_key = KEY_ILLEGAL_REQUEST;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense->es_add_code =
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SD_SCSI_ASC_INVALID_FIELD_IN_CDB;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf goto done;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsipkt->pkt_state |= STATE_XFERRED_DATA;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsipkt->pkt_resid = scsipkt->pkt_cdbp[4] > count ?
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsipkt->pkt_cdbp[4] - count : 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfdone:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&(SATA_TXLT_CPORT_MUTEX(spx)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG1(SATA_DBG_SCSI_IF, spx->txlt_sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "Scsi_pkt completion reason %x\n",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsipkt->pkt_reason);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((scsipkt->pkt_flags & FLAG_NOINTR) == 0 &&
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw scsipkt->pkt_comp != NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* scsi callback required */
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw if (taskq_dispatch(SATA_TXLT_TASKQ(spx),
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw (task_func_t *)scsipkt->pkt_comp, (void *) scsipkt,
4360436b3c604bc28d37be269ad152b4c38157c3pawelw TQ_SLEEP) == NULL)
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw /* Scheduling the callback failed */
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw return (TRAN_BUSY);
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (TRAN_ACCEPT);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * SATA translate command: Request Sense.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Returns TRAN_ACCEPT and appropriate values in scsi_pkt fields.
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu * At the moment this is an emulated command (ATA version for SATA hard disks).
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu * May be translated into Check Power Mode command in the future.
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik *
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik * Note: There is a mismatch between already implemented Informational
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik * Exception Mode Select page 0x1C and this function.
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik * When MRIE bit is set in page 0x1C, Request Sense is supposed to return
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik * NO SENSE and set additional sense code to the exception code - this is not
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik * implemented here.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_txlt_request_sense(sata_pkt_txlate_t *spx)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf struct scsi_pkt *scsipkt = spx->txlt_scsi_pkt;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf struct scsi_extended_sense sense;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf struct buf *bp = spx->txlt_sata_pkt->satapkt_cmd.satacmd_bp;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sata_drive_info_t *sdinfo;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sata_cmd_t *scmd = &spx->txlt_sata_pkt->satapkt_cmd;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu int rval, reason, power_state = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&(SATA_TXLT_CPORT_MUTEX(spx)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
f39c049be37ba5b8f96704f41d6532332ae16318pawelw if (((rval = sata_txlt_generic_pkt_info(spx, &reason)) !=
f39c049be37ba5b8f96704f41d6532332ae16318pawelw TRAN_ACCEPT) || (reason == CMD_DEV_GONE)) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&(SATA_TXLT_CPORT_MUTEX(spx)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (rval);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsipkt->pkt_reason = CMD_CMPLT;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsipkt->pkt_state = STATE_GOT_BUS | STATE_GOT_TARGET |
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf STATE_SENT_CMD | STATE_GOT_STATUS;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *scsipkt->pkt_scbp = STATUS_GOOD;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu /*
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu * when CONTROL field's NACA bit == 1
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu * return ILLEGAL_REQUEST
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu */
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if (scsipkt->pkt_cdbp[5] & CTL_BYTE_NACA_MASK) {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu mutex_exit(&(SATA_TXLT_CPORT_MUTEX(spx)));
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu return (sata_txlt_check_condition(spx, KEY_ILLEGAL_REQUEST,
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu SD_SCSI_ASC_CMD_SEQUENCE_ERR));
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu }
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sdinfo = sata_get_device_info(spx->txlt_sata_hba_inst,
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu &spx->txlt_sata_pkt->satapkt_device);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu ASSERT(sdinfo != NULL);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu
776955ed2c90dad066581c20700f1969e3c15f77Ada spx->txlt_sata_pkt->satapkt_op_mode |= SATA_OPMODE_SYNCH;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sata_build_generic_cmd(scmd, SATAC_CHECK_POWER_MODE);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu scmd->satacmd_flags.sata_copy_out_sec_count_lsb = B_TRUE;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu scmd->satacmd_flags.sata_copy_out_error_reg = B_TRUE;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if (sata_hba_start(spx, &rval) != 0) {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu mutex_exit(&(SATA_TXLT_CPORT_MUTEX(spx)));
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu return (rval);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu } else {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if (scmd->satacmd_error_reg != 0) {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu mutex_exit(&(SATA_TXLT_CPORT_MUTEX(spx)));
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu return (sata_txlt_check_condition(spx, KEY_NO_SENSE,
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu SD_SCSI_ASC_NO_ADD_SENSE));
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu }
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu }
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu switch (scmd->satacmd_sec_count_lsb) {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu case SATA_PWRMODE_STANDBY: /* device in standby mode */
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if (sdinfo->satadrv_power_level == SATA_POWER_STOPPED)
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu power_state = SATA_POWER_STOPPED;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu else {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu power_state = SATA_POWER_STANDBY;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sdinfo->satadrv_power_level = SATA_POWER_STANDBY;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu }
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu break;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu case SATA_PWRMODE_IDLE: /* device in idle mode */
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu power_state = SATA_POWER_IDLE;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sdinfo->satadrv_power_level = SATA_POWER_IDLE;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu break;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu case SATA_PWRMODE_ACTIVE: /* device in active or idle mode */
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu default: /* 0x40, 0x41 active mode */
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if (sdinfo->satadrv_power_level == SATA_POWER_IDLE)
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu power_state = SATA_POWER_IDLE;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu else {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu power_state = SATA_POWER_ACTIVE;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sdinfo->satadrv_power_level = SATA_POWER_ACTIVE;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu }
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu break;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu }
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu mutex_exit(&(SATA_TXLT_CPORT_MUTEX(spx)));
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (bp != NULL && bp->b_un.b_addr && bp->b_bcount) {
8d483882aa3390058094b043f3d62187b5d1de03mlf /*
8d483882aa3390058094b043f3d62187b5d1de03mlf * Because it is fully emulated command storing data
8d483882aa3390058094b043f3d62187b5d1de03mlf * programatically in the specified buffer, release
8d483882aa3390058094b043f3d62187b5d1de03mlf * preallocated DMA resources before storing data in the buffer,
8d483882aa3390058094b043f3d62187b5d1de03mlf * so no unwanted DMA sync would take place.
8d483882aa3390058094b043f3d62187b5d1de03mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int count = MIN(bp->b_bcount,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sizeof (struct scsi_extended_sense));
8d483882aa3390058094b043f3d62187b5d1de03mlf sata_scsi_dmafree(NULL, scsipkt);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf bzero(&sense, sizeof (struct scsi_extended_sense));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense.es_valid = 0; /* Valid LBA */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense.es_class = 7; /* Response code 0x70 - current err */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense.es_key = KEY_NO_SENSE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense.es_add_len = 6; /* Additional length */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Copy no more than requested */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf bcopy(&sense, bp->b_un.b_addr, count);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsipkt->pkt_state |= STATE_XFERRED_DATA;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsipkt->pkt_resid = 0;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu switch (power_state) {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu case SATA_POWER_IDLE:
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu case SATA_POWER_STANDBY:
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sense.es_add_code =
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu SD_SCSI_ASC_LOW_POWER_CONDITION_ON;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu break;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu case SATA_POWER_STOPPED:
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sense.es_add_code = SD_SCSI_ASC_NO_ADD_SENSE;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu break;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu case SATA_POWER_ACTIVE:
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu default:
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu break;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG1(SATA_DBG_SCSI_IF, spx->txlt_sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "Scsi_pkt completion reason %x\n",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsipkt->pkt_reason);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if ((scsipkt->pkt_flags & FLAG_NOINTR) == 0)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* scsi callback required */
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw if (taskq_dispatch(SATA_TXLT_TASKQ(spx),
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu (task_func_t *)scsi_hba_pkt_comp, (void *) scsipkt,
4360436b3c604bc28d37be269ad152b4c38157c3pawelw TQ_SLEEP) == NULL)
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw /* Scheduling the callback failed */
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw return (TRAN_BUSY);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (TRAN_ACCEPT);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * SATA translate command: Test Unit Ready
a9d5ae2e08c504913c088349c3d4c144f3c92be8Pawel Wojcik * (ATA version for SATA hard disks).
a9d5ae2e08c504913c088349c3d4c144f3c92be8Pawel Wojcik * It is translated into the Check Power Mode command.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Returns TRAN_ACCEPT and appropriate values in scsi_pkt fields.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_txlt_test_unit_ready(sata_pkt_txlate_t *spx)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf struct scsi_pkt *scsipkt = spx->txlt_scsi_pkt;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf struct scsi_extended_sense *sense;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sata_cmd_t *scmd = &spx->txlt_sata_pkt->satapkt_cmd;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sata_drive_info_t *sdinfo;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int power_state;
f39c049be37ba5b8f96704f41d6532332ae16318pawelw int rval, reason;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&(SATA_TXLT_CPORT_MUTEX(spx)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
f39c049be37ba5b8f96704f41d6532332ae16318pawelw if (((rval = sata_txlt_generic_pkt_info(spx, &reason)) !=
f39c049be37ba5b8f96704f41d6532332ae16318pawelw TRAN_ACCEPT) || (reason == CMD_DEV_GONE)) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&(SATA_TXLT_CPORT_MUTEX(spx)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (rval);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sdinfo = sata_get_device_info(spx->txlt_sata_hba_inst,
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu &spx->txlt_sata_pkt->satapkt_device);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu ASSERT(sdinfo != NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
776955ed2c90dad066581c20700f1969e3c15f77Ada spx->txlt_sata_pkt->satapkt_op_mode |= SATA_OPMODE_SYNCH;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu /* send CHECK POWER MODE command */
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sata_build_generic_cmd(scmd, SATAC_CHECK_POWER_MODE);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu scmd->satacmd_flags.sata_copy_out_sec_count_lsb = B_TRUE;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu scmd->satacmd_flags.sata_copy_out_error_reg = B_TRUE;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if (sata_hba_start(spx, &rval) != 0) {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu mutex_exit(&(SATA_TXLT_CPORT_MUTEX(spx)));
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu return (rval);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu } else {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if (scmd->satacmd_error_reg != 0) {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu mutex_exit(&(SATA_TXLT_CPORT_MUTEX(spx)));
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu return (sata_txlt_check_condition(spx, KEY_NOT_READY,
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu SD_SCSI_ASC_LU_NOT_RESPONSE));
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu }
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu }
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu power_state = scmd->satacmd_sec_count_lsb;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu /*
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu * return NOT READY when device in STOPPED mode
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu */
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if (power_state == SATA_PWRMODE_STANDBY &&
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sdinfo->satadrv_power_level == SATA_POWER_STOPPED) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *scsipkt->pkt_scbp = STATUS_CHECK;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense = sata_arq_sense(spx);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense->es_key = KEY_NOT_READY;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sense->es_add_code = SD_SCSI_ASC_LU_NOT_READY;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu } else {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu /*
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu * For other power mode, return GOOD status
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu */
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu *scsipkt->pkt_scbp = STATUS_GOOD;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu scsipkt->pkt_reason = CMD_CMPLT;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu scsipkt->pkt_state = STATE_GOT_BUS | STATE_GOT_TARGET |
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu STATE_SENT_CMD | STATE_GOT_STATUS;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu mutex_exit(&(SATA_TXLT_CPORT_MUTEX(spx)));
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG1(SATA_DBG_SCSI_IF, spx->txlt_sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "Scsi_pkt completion reason %x\n", scsipkt->pkt_reason);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if ((scsipkt->pkt_flags & FLAG_NOINTR) == 0)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* scsi callback required */
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw if (taskq_dispatch(SATA_TXLT_TASKQ(spx),
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu (task_func_t *)scsi_hba_pkt_comp, (void *) scsipkt,
4360436b3c604bc28d37be269ad152b4c38157c3pawelw TQ_SLEEP) == NULL)
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw /* Scheduling the callback failed */
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw return (TRAN_BUSY);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (TRAN_ACCEPT);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * SATA translate command: Start Stop Unit
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Translation depends on a command:
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu *
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu * Power condition bits will be supported
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu * and the power level should be maintained by SATL,
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu * When SATL received a command, it will check the
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu * power level firstly, and return the status according
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu * to SAT2 v2.6 and SAT-2 Standby Modifications
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu *
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu * SPC-4/SBC-3 SATL ATA power condition SATL SPC/SBC
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu * -----------------------------------------------------------------------
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu * SSU_PC1 Active <==> ATA Active <==> SSU:start_bit =1
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu * SSU_PC2 Idle <==> ATA Idle <==> N/A
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu * SSU_PC3 Standby <==> ATA Standby <==> N/A
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu * SSU_PC4 Stopped <==> ATA Standby <==> SSU:start_bit = 0
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Unload Media / NOT SUPPORTED YET
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Load Media / NOT SUPPROTED YET
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu * Immediate bit / NOT SUPPORTED YET (deferred error)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Returns TRAN_ACCEPT or code returned by sata_hba_start() and
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * appropriate values in scsi_pkt fields.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_txlt_start_stop_unit(sata_pkt_txlate_t *spx)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf struct scsi_pkt *scsipkt = spx->txlt_scsi_pkt;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_cmd_t *scmd = &spx->txlt_sata_pkt->satapkt_cmd;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst_t *shi = SATA_TXLT_HBA_INST(spx);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int cport = SATA_TXLT_CPORT(spx);
f39c049be37ba5b8f96704f41d6532332ae16318pawelw int rval, reason;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sata_drive_info_t *sdinfo;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sata_id_t *sata_id;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG1(SATA_DBG_SCSI_IF, spx->txlt_sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_txlt_start_stop_unit: %d\n", scsipkt->pkt_scbp[4] & 1);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&SATA_CPORT_MUTEX(shi, cport));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
f39c049be37ba5b8f96704f41d6532332ae16318pawelw if (((rval = sata_txlt_generic_pkt_info(spx, &reason)) !=
f39c049be37ba5b8f96704f41d6532332ae16318pawelw TRAN_ACCEPT) || (reason == CMD_DEV_GONE)) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&(SATA_TXLT_CPORT_MUTEX(spx)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (rval);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if (scsipkt->pkt_cdbp[1] & START_STOP_IMMED_MASK) {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu /* IMMED bit - not supported */
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu mutex_exit(&SATA_CPORT_MUTEX(shi, cport));
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu return (sata_txlt_check_condition(spx, KEY_ILLEGAL_REQUEST,
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu SD_SCSI_ASC_INVALID_FIELD_IN_CDB));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
776955ed2c90dad066581c20700f1969e3c15f77Ada spx->txlt_sata_pkt->satapkt_op_mode |= SATA_OPMODE_SYNCH;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu spx->txlt_sata_pkt->satapkt_comp = NULL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sdinfo = sata_get_device_info(spx->txlt_sata_hba_inst,
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu &spx->txlt_sata_pkt->satapkt_device);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu ASSERT(sdinfo != NULL);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sata_id = &sdinfo->satadrv_id;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu switch ((scsipkt->pkt_cdbp[4] & START_STOP_POWER_COND_MASK) >> 4) {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu case 0:
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if (scsipkt->pkt_cdbp[4] & START_STOP_LOEJ_MASK) {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu /* Load/Unload Media - invalid request */
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu goto err_out;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu }
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if (scsipkt->pkt_cdbp[4] & START_STOP_START_MASK) {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu /* Start Unit */
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sata_build_read_verify_cmd(scmd, 1, 5);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu scmd->satacmd_flags.sata_copy_out_error_reg = B_TRUE;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu /* Transfer command to HBA */
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if (sata_hba_start(spx, &rval) != 0) {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu /* Pkt not accepted for execution */
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu mutex_exit(&SATA_CPORT_MUTEX(shi, cport));
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu return (rval);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu } else {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if (scmd->satacmd_error_reg != 0) {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu goto err_out;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu }
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu }
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sdinfo->satadrv_power_level = SATA_POWER_ACTIVE;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu } else {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu /* Stop Unit */
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sata_build_generic_cmd(scmd, SATAC_FLUSH_CACHE);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu scmd->satacmd_flags.sata_copy_out_error_reg = B_TRUE;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if (sata_hba_start(spx, &rval) != 0) {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu mutex_exit(&SATA_CPORT_MUTEX(shi, cport));
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu return (rval);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu } else {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if (scmd->satacmd_error_reg != 0) {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu goto err_out;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu }
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu }
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu /* ata standby immediate command */
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sata_build_generic_cmd(scmd, SATAC_STANDBY_IM);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu scmd->satacmd_flags.sata_copy_out_error_reg = B_TRUE;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if (sata_hba_start(spx, &rval) != 0) {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu mutex_exit(&SATA_CPORT_MUTEX(shi, cport));
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu return (rval);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu } else {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if (scmd->satacmd_error_reg != 0) {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu goto err_out;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu }
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu }
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sdinfo->satadrv_power_level = SATA_POWER_STOPPED;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu }
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu break;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu case 0x1:
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sata_build_generic_cmd(scmd, SATAC_IDLE);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu scmd->satacmd_flags.sata_copy_out_error_reg = B_TRUE;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if (sata_hba_start(spx, &rval) != 0) {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu mutex_exit(&SATA_CPORT_MUTEX(shi, cport));
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu return (rval);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu } else {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if (scmd->satacmd_error_reg != 0) {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu goto err_out;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu }
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu }
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sata_build_read_verify_cmd(scmd, 1, 5);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu scmd->satacmd_flags.sata_copy_out_error_reg = B_TRUE;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu /* Transfer command to HBA */
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if (sata_hba_start(spx, &rval) != 0) {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu /* Pkt not accepted for execution */
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu mutex_exit(&SATA_CPORT_MUTEX(shi, cport));
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu return (rval);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu } else {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if (scmd->satacmd_error_reg != 0) {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu goto err_out;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu }
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu }
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sdinfo->satadrv_power_level = SATA_POWER_ACTIVE;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu break;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu case 0x2:
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sata_build_generic_cmd(scmd, SATAC_FLUSH_CACHE);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu scmd->satacmd_flags.sata_copy_out_error_reg = B_TRUE;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if (!(scsipkt->pkt_cdbp[4] & START_STOP_NOFLUSH_MASK)) {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if (sata_hba_start(spx, &rval) != 0) {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu mutex_exit(&SATA_CPORT_MUTEX(shi, cport));
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu return (rval);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu } else {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if (scmd->satacmd_error_reg != 0) {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu goto err_out;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu }
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu }
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu }
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sata_build_generic_cmd(scmd, SATAC_IDLE);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu scmd->satacmd_flags.sata_copy_out_error_reg = B_TRUE;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if (sata_hba_start(spx, &rval) != 0) {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu mutex_exit(&SATA_CPORT_MUTEX(shi, cport));
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu return (rval);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu } else {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if (scmd->satacmd_error_reg != 0) {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu goto err_out;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu }
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu }
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if ((scsipkt->pkt_cdbp[3] & START_STOP_MODIFIER_MASK)) {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu /*
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu * POWER CONDITION MODIFIER bit set
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu * to 0x1 or larger it will be handled
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu * on the same way as bit = 0x1
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu */
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if (!(sata_id->ai_cmdset84 &
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu SATA_IDLE_UNLOAD_SUPPORTED)) {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sdinfo->satadrv_power_level = SATA_POWER_IDLE;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu break;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu }
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sata_build_generic_cmd(scmd, SATAC_IDLE_IM);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu scmd->satacmd_features_reg = 0x44;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu scmd->satacmd_lba_low_lsb = 0x4c;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu scmd->satacmd_lba_mid_lsb = 0x4e;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu scmd->satacmd_lba_high_lsb = 0x55;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu scmd->satacmd_flags.sata_copy_out_error_reg = B_TRUE;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if (sata_hba_start(spx, &rval) != 0) {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu mutex_exit(&SATA_CPORT_MUTEX(shi, cport));
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu return (rval);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu } else {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if (scmd->satacmd_error_reg != 0) {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu goto err_out;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu }
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu }
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu }
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sdinfo->satadrv_power_level = SATA_POWER_IDLE;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu break;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu case 0x3:
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sata_build_generic_cmd(scmd, SATAC_FLUSH_CACHE);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu scmd->satacmd_flags.sata_copy_out_error_reg = B_TRUE;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if (!(scsipkt->pkt_cdbp[4] & START_STOP_NOFLUSH_MASK)) {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if (sata_hba_start(spx, &rval) != 0) {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu mutex_exit(&SATA_CPORT_MUTEX(shi, cport));
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu return (rval);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu } else {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if (scmd->satacmd_error_reg != 0) {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu goto err_out;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu }
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu }
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu }
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sata_build_generic_cmd(scmd, SATAC_STANDBY);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu scmd->satacmd_flags.sata_copy_out_error_reg = B_TRUE;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if (sata_hba_start(spx, &rval) != 0) {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu mutex_exit(&SATA_CPORT_MUTEX(shi, cport));
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu return (rval);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu } else {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if (scmd->satacmd_error_reg != 0) {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu goto err_out;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu }
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu }
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sdinfo->satadrv_power_level = SATA_POWER_STANDBY;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu break;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu case 0x7:
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sata_build_generic_cmd(scmd, SATAC_CHECK_POWER_MODE);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu scmd->satacmd_flags.sata_copy_out_sec_count_lsb = B_TRUE;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu scmd->satacmd_flags.sata_copy_out_error_reg = B_TRUE;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if (sata_hba_start(spx, &rval) != 0) {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu mutex_exit(&SATA_CPORT_MUTEX(shi, cport));
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu return (rval);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu } else {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if (scmd->satacmd_error_reg != 0) {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu goto err_out;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu }
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu }
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu switch (scmd->satacmd_sec_count_lsb) {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu case SATA_PWRMODE_STANDBY:
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sata_build_generic_cmd(scmd, SATAC_STANDBY);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu scmd->satacmd_sec_count_msb = sata_get_standby_timer(
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sdinfo->satadrv_standby_timer);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu scmd->satacmd_flags.sata_copy_out_error_reg = B_TRUE;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if (sata_hba_start(spx, &rval) != 0) {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu mutex_exit(&SATA_CPORT_MUTEX(shi, cport));
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu return (rval);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu } else {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if (scmd->satacmd_error_reg != 0) {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu goto err_out;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu }
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu }
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu break;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu case SATA_PWRMODE_IDLE:
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sata_build_generic_cmd(scmd, SATAC_IDLE);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu scmd->satacmd_sec_count_msb = sata_get_standby_timer(
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sdinfo->satadrv_standby_timer);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu scmd->satacmd_flags.sata_copy_out_error_reg = B_TRUE;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if (sata_hba_start(spx, &rval) != 0) {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu mutex_exit(&SATA_CPORT_MUTEX(shi, cport));
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu return (rval);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu } else {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if (scmd->satacmd_error_reg != 0) {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu goto err_out;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu }
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu }
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu break;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu case SATA_PWRMODE_ACTIVE_SPINDOWN:
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu case SATA_PWRMODE_ACTIVE_SPINUP:
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu case SATA_PWRMODE_ACTIVE:
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sata_build_generic_cmd(scmd, SATAC_IDLE);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu scmd->satacmd_sec_count_msb = sata_get_standby_timer(
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sdinfo->satadrv_standby_timer);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu scmd->satacmd_flags.sata_copy_out_error_reg = B_TRUE;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if (sata_hba_start(spx, &rval) != 0) {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu mutex_exit(&SATA_CPORT_MUTEX(shi, cport));
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu return (rval);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu } else {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if (scmd->satacmd_error_reg != 0) {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu goto err_out;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu }
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu }
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sata_build_read_verify_cmd(scmd, 1, 5);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu scmd->satacmd_flags.sata_copy_out_error_reg = B_TRUE;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if (sata_hba_start(spx, &rval) != 0) {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu mutex_exit(&SATA_CPORT_MUTEX(shi, cport));
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu return (rval);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu } else {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if (scmd->satacmd_error_reg != 0) {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu goto err_out;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu }
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu }
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu break;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu default:
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu goto err_out;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu }
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu break;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu case 0xb:
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if ((sata_get_standby_timer(sdinfo->satadrv_standby_timer) ==
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu 0) || (!(sata_id->ai_cap & SATA_STANDBYTIMER))) {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu mutex_exit(&SATA_CPORT_MUTEX(shi, cport));
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu return (sata_txlt_check_condition(spx,
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu KEY_ILLEGAL_REQUEST,
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu SD_SCSI_ASC_INVALID_FIELD_IN_CDB));
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu }
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sata_build_generic_cmd(scmd, SATAC_FLUSH_CACHE);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu scmd->satacmd_flags.sata_copy_out_error_reg = B_TRUE;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if (!(scsipkt->pkt_cdbp[4] & START_STOP_NOFLUSH_MASK)) {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if (sata_hba_start(spx, &rval) != 0) {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu mutex_exit(&SATA_CPORT_MUTEX(shi, cport));
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu return (rval);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu } else {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if (scmd->satacmd_error_reg != 0) {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu goto err_out;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu }
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu }
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sata_build_generic_cmd(scmd, SATAC_STANDBY_IM);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu scmd->satacmd_flags.sata_copy_out_error_reg = B_TRUE;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if (sata_hba_start(spx, &rval) != 0) {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu mutex_exit(&SATA_CPORT_MUTEX(shi, cport));
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu return (rval);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu } else {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if (scmd->satacmd_error_reg != 0) {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu goto err_out;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu }
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu }
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu }
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu bzero(sdinfo->satadrv_standby_timer, sizeof (uchar_t) * 4);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu break;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu default:
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chuerr_out:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&SATA_CPORT_MUTEX(shi, cport));
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu return (sata_txlt_check_condition(spx, KEY_ILLEGAL_REQUEST,
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu SD_SCSI_ASC_INVALID_FIELD_IN_CDB));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
a9d5ae2e08c504913c088349c3d4c144f3c92be8Pawel Wojcik * Since it was a synchronous command,
a9d5ae2e08c504913c088349c3d4c144f3c92be8Pawel Wojcik * a callback function will be called directly.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&SATA_CPORT_MUTEX(shi, cport));
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu SATADBG1(SATA_DBG_SCSI_IF, spx->txlt_sata_hba_inst,
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu "synchronous execution status %x\n",
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu spx->txlt_sata_pkt->satapkt_reason);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if ((scsipkt->pkt_flags & FLAG_NOINTR) == 0) {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sata_set_arq_data(spx->txlt_sata_pkt);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if (taskq_dispatch(SATA_TXLT_TASKQ(spx),
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu (task_func_t *)scsi_hba_pkt_comp, (void *) scsipkt,
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu TQ_SLEEP) == 0) {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu return (TRAN_BUSY);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu else
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sata_txlt_nodata_cmd_completion(spx->txlt_sata_pkt);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (TRAN_ACCEPT);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * SATA translate command: Read Capacity.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Emulated command for SATA disks.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Capacity is retrieved from cached Idenifty Device data.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Identify Device data shows effective disk capacity, not the native
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * capacity, which may be limitted by Set Max Address command.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * This is ATA version for SATA hard disks.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Returns TRAN_ACCEPT and appropriate values in scsi_pkt fields.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_txlt_read_capacity(sata_pkt_txlate_t *spx)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf struct scsi_pkt *scsipkt = spx->txlt_scsi_pkt;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf struct buf *bp = spx->txlt_sata_pkt->satapkt_cmd.satacmd_bp;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_drive_info_t *sdinfo;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf uint64_t val;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf uchar_t *rbuf;
f39c049be37ba5b8f96704f41d6532332ae16318pawelw int rval, reason;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG1(SATA_DBG_SCSI_IF, spx->txlt_sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_txlt_read_capacity: ", NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&(SATA_TXLT_CPORT_MUTEX(spx)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
f39c049be37ba5b8f96704f41d6532332ae16318pawelw if (((rval = sata_txlt_generic_pkt_info(spx, &reason)) !=
f39c049be37ba5b8f96704f41d6532332ae16318pawelw TRAN_ACCEPT) || (reason == CMD_DEV_GONE)) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&(SATA_TXLT_CPORT_MUTEX(spx)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (rval);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsipkt->pkt_reason = CMD_CMPLT;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsipkt->pkt_state = STATE_GOT_BUS | STATE_GOT_TARGET |
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf STATE_SENT_CMD | STATE_GOT_STATUS;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *scsipkt->pkt_scbp = STATUS_GOOD;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (bp != NULL && bp->b_un.b_addr && bp->b_bcount) {
8d483882aa3390058094b043f3d62187b5d1de03mlf /*
8d483882aa3390058094b043f3d62187b5d1de03mlf * Because it is fully emulated command storing data
8d483882aa3390058094b043f3d62187b5d1de03mlf * programatically in the specified buffer, release
8d483882aa3390058094b043f3d62187b5d1de03mlf * preallocated DMA resources before storing data in the buffer,
8d483882aa3390058094b043f3d62187b5d1de03mlf * so no unwanted DMA sync would take place.
8d483882aa3390058094b043f3d62187b5d1de03mlf */
8d483882aa3390058094b043f3d62187b5d1de03mlf sata_scsi_dmafree(NULL, scsipkt);
8d483882aa3390058094b043f3d62187b5d1de03mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo = sata_get_device_info(
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf &spx->txlt_sata_pkt->satapkt_device);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Last logical block address */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf val = sdinfo->satadrv_capacity - 1;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rbuf = (uchar_t *)bp->b_un.b_addr;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Need to swap endians to match scsi format */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rbuf[0] = (val >> 24) & 0xff;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rbuf[1] = (val >> 16) & 0xff;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rbuf[2] = (val >> 8) & 0xff;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rbuf[3] = val & 0xff;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* block size - always 512 bytes, for now */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rbuf[4] = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rbuf[5] = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rbuf[6] = 0x02;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rbuf[7] = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsipkt->pkt_state |= STATE_XFERRED_DATA;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsipkt->pkt_resid = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG1(SATA_DBG_SCSI_IF, spx->txlt_sata_hba_inst, "%d\n",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_capacity -1);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&(SATA_TXLT_CPORT_MUTEX(spx)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * If a callback was requested, do it now.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG1(SATA_DBG_SCSI_IF, spx->txlt_sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "Scsi_pkt completion reason %x\n", scsipkt->pkt_reason);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((scsipkt->pkt_flags & FLAG_NOINTR) == 0 &&
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsipkt->pkt_comp != NULL)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* scsi callback required */
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw if (taskq_dispatch(SATA_TXLT_TASKQ(spx),
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw (task_func_t *)scsipkt->pkt_comp, (void *) scsipkt,
4360436b3c604bc28d37be269ad152b4c38157c3pawelw TQ_SLEEP) == NULL)
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw /* Scheduling the callback failed */
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw return (TRAN_BUSY);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (TRAN_ACCEPT);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * SATA translate command: Mode Sense.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Translated into appropriate SATA command or emulated.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Saved Values Page Control (03) are not supported.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * NOTE: only caching mode sense page is currently implemented.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Returns TRAN_ACCEPT and appropriate values in scsi_pkt fields.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
20bc265b0a583202225a5621ab565fc73a34404dPhi Tran#define LLBAA 0x10 /* Long LBA Accepted */
20bc265b0a583202225a5621ab565fc73a34404dPhi Tran
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_txlt_mode_sense(sata_pkt_txlate_t *spx)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf struct scsi_pkt *scsipkt = spx->txlt_scsi_pkt;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf struct buf *bp = spx->txlt_sata_pkt->satapkt_cmd.satacmd_bp;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_drive_info_t *sdinfo;
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls sata_id_t *sata_id;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf struct scsi_extended_sense *sense;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int len, bdlen, count, alc_len;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int pc; /* Page Control code */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf uint8_t *buf; /* mode sense buffer */
f39c049be37ba5b8f96704f41d6532332ae16318pawelw int rval, reason;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG2(SATA_DBG_SCSI_IF, spx->txlt_sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_txlt_mode_sense, pc %x page code 0x%02x\n",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_scsi_pkt->pkt_cdbp[2] >> 6,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_scsi_pkt->pkt_cdbp[2] & 0x3f);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf buf = kmem_zalloc(1024, KM_SLEEP);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&(SATA_TXLT_CPORT_MUTEX(spx)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
f39c049be37ba5b8f96704f41d6532332ae16318pawelw if (((rval = sata_txlt_generic_pkt_info(spx, &reason)) !=
f39c049be37ba5b8f96704f41d6532332ae16318pawelw TRAN_ACCEPT) || (reason == CMD_DEV_GONE)) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&(SATA_TXLT_CPORT_MUTEX(spx)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf kmem_free(buf, 1024);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (rval);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsipkt->pkt_reason = CMD_CMPLT;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsipkt->pkt_state = STATE_GOT_BUS | STATE_GOT_TARGET |
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf STATE_SENT_CMD | STATE_GOT_STATUS;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf pc = scsipkt->pkt_cdbp[2] >> 6;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (bp != NULL && bp->b_un.b_addr && bp->b_bcount) {
8d483882aa3390058094b043f3d62187b5d1de03mlf /*
8d483882aa3390058094b043f3d62187b5d1de03mlf * Because it is fully emulated command storing data
8d483882aa3390058094b043f3d62187b5d1de03mlf * programatically in the specified buffer, release
8d483882aa3390058094b043f3d62187b5d1de03mlf * preallocated DMA resources before storing data in the buffer,
8d483882aa3390058094b043f3d62187b5d1de03mlf * so no unwanted DMA sync would take place.
8d483882aa3390058094b043f3d62187b5d1de03mlf */
8d483882aa3390058094b043f3d62187b5d1de03mlf sata_scsi_dmafree(NULL, scsipkt);
8d483882aa3390058094b043f3d62187b5d1de03mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf len = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf bdlen = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (!(scsipkt->pkt_cdbp[1] & 8)) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (scsipkt->pkt_cdbp[0] == SCMD_MODE_SENSE_G1 &&
20bc265b0a583202225a5621ab565fc73a34404dPhi Tran (scsipkt->pkt_cdbp[1] & LLBAA))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf bdlen = 16;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf else
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf bdlen = 8;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Build mode parameter header */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (spx->txlt_scsi_pkt->pkt_cdbp[0] == SCMD_MODE_SENSE) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* 4-byte mode parameter header */
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu buf[len++] = 0; /* mode data length */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf buf[len++] = 0; /* medium type */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf buf[len++] = 0; /* dev-specific param */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf buf[len++] = bdlen; /* Block Descriptor length */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* 8-byte mode parameter header */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf buf[len++] = 0; /* mode data length */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf buf[len++] = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf buf[len++] = 0; /* medium type */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf buf[len++] = 0; /* dev-specific param */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (bdlen == 16)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf buf[len++] = 1; /* long lba descriptor */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf else
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf buf[len++] = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf buf[len++] = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf buf[len++] = 0; /* Block Descriptor length */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf buf[len++] = bdlen;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo = sata_get_device_info(
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf &spx->txlt_sata_pkt->satapkt_device);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Build block descriptor only if not disabled (DBD) */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((scsipkt->pkt_cdbp[1] & 0x08) == 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Block descriptor - direct-access device format */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (bdlen == 8) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* build regular block descriptor */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf buf[len++] =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (sdinfo->satadrv_capacity >> 24) & 0xff;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf buf[len++] =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (sdinfo->satadrv_capacity >> 16) & 0xff;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf buf[len++] =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (sdinfo->satadrv_capacity >> 8) & 0xff;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf buf[len++] = sdinfo->satadrv_capacity & 0xff;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf buf[len++] = 0; /* density code */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf buf[len++] = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sdinfo->satadrv_type ==
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_DTYPE_ATADISK)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf buf[len++] = 2;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf else
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* ATAPI */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf buf[len++] = 8;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf buf[len++] = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else if (bdlen == 16) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Long LBA Accepted */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* build long lba block descriptor */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#ifndef __lock_lint
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf buf[len++] =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (sdinfo->satadrv_capacity >> 56) & 0xff;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf buf[len++] =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (sdinfo->satadrv_capacity >> 48) & 0xff;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf buf[len++] =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (sdinfo->satadrv_capacity >> 40) & 0xff;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf buf[len++] =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (sdinfo->satadrv_capacity >> 32) & 0xff;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#endif
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf buf[len++] =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (sdinfo->satadrv_capacity >> 24) & 0xff;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf buf[len++] =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (sdinfo->satadrv_capacity >> 16) & 0xff;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf buf[len++] =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (sdinfo->satadrv_capacity >> 8) & 0xff;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf buf[len++] = sdinfo->satadrv_capacity & 0xff;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf buf[len++] = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf buf[len++] = 0; /* density code */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf buf[len++] = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf buf[len++] = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sdinfo->satadrv_type ==
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_DTYPE_ATADISK)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf buf[len++] = 2;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf else
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* ATAPI */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf buf[len++] = 8;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf buf[len++] = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls sata_id = &sdinfo->satadrv_id;
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Add requested pages.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Page 3 and 4 are obsolete and we are not supporting them.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * We deal now with:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * caching (read/write cache control).
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * We should eventually deal with following mode pages:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * error recovery (0x01),
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * power condition (0x1a),
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * exception control page (enables SMART) (0x1c),
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * enclosure management (ses),
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * protocol-specific port mode (port control).
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf switch (scsipkt->pkt_cdbp[2] & 0x3f) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case MODEPAGE_RW_ERRRECOV:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* DAD_MODE_ERR_RECOV */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* R/W recovery */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf len += sata_build_msense_page_1(sdinfo, pc, buf+len);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case MODEPAGE_CACHING:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* DAD_MODE_CACHE */
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls /* Reject not supported request for saved parameters */
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls if (pc == 3) {
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls *scsipkt->pkt_scbp = STATUS_CHECK;
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls sense = sata_arq_sense(spx);
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls sense->es_key = KEY_ILLEGAL_REQUEST;
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls sense->es_add_code =
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SD_SCSI_ASC_SAVING_PARAMS_NOT_SUPPORTED;
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls goto done;
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls }
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* caching */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf len += sata_build_msense_page_8(sdinfo, pc, buf+len);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case MODEPAGE_INFO_EXCPT:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* exception cntrl */
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls if (sata_id->ai_cmdset82 & SATA_SMART_SUPPORTED) {
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls len += sata_build_msense_page_1c(sdinfo, pc,
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls buf+len);
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls }
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls else
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls goto err;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case MODEPAGE_POWER_COND:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* DAD_MODE_POWER_COND */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* power condition */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf len += sata_build_msense_page_1a(sdinfo, pc, buf+len);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls case MODEPAGE_ACOUSTIC_MANAG:
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls /* acoustic management */
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls len += sata_build_msense_page_30(sdinfo, pc, buf+len);
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case MODEPAGE_ALLPAGES:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* all pages */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf len += sata_build_msense_page_1(sdinfo, pc, buf+len);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf len += sata_build_msense_page_8(sdinfo, pc, buf+len);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf len += sata_build_msense_page_1a(sdinfo, pc, buf+len);
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls if (sata_id->ai_cmdset82 & SATA_SMART_SUPPORTED) {
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls len += sata_build_msense_page_1c(sdinfo, pc,
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls buf+len);
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls }
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls len += sata_build_msense_page_30(sdinfo, pc, buf+len);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf default:
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls err:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Invalid request */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *scsipkt->pkt_scbp = STATUS_CHECK;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense = sata_arq_sense(spx);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense->es_key = KEY_ILLEGAL_REQUEST;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sense->es_add_code = SD_SCSI_ASC_INVALID_FIELD_IN_CDB;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf goto done;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* fix total mode data length */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (spx->txlt_scsi_pkt->pkt_cdbp[0] == SCMD_MODE_SENSE) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* 4-byte mode parameter header */
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu buf[0] = len - 1; /* mode data length */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf buf[0] = (len -2) >> 8;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf buf[1] = (len -2) & 0xff;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Check allocation length */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (scsipkt->pkt_cdbp[0] == SCMD_MODE_SENSE) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf alc_len = scsipkt->pkt_cdbp[4];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf alc_len = scsipkt->pkt_cdbp[7];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf alc_len = (len << 8) | scsipkt->pkt_cdbp[8];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * We do not check for possible parameters truncation
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * (alc_len < len) assuming that the target driver works
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * correctly. Just avoiding overrun.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Copy no more than requested and possible, buffer-wise.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf count = MIN(alc_len, len);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf count = MIN(bp->b_bcount, count);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf bcopy(buf, bp->b_un.b_addr, count);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsipkt->pkt_state |= STATE_XFERRED_DATA;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsipkt->pkt_resid = alc_len > count ? alc_len - count : 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *scsipkt->pkt_scbp = STATUS_GOOD;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfdone:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&(SATA_TXLT_CPORT_MUTEX(spx)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (void) kmem_free(buf, 1024);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG1(SATA_DBG_SCSI_IF, spx->txlt_sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "Scsi_pkt completion reason %x\n", scsipkt->pkt_reason);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((scsipkt->pkt_flags & FLAG_NOINTR) == 0 &&
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsipkt->pkt_comp != NULL)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* scsi callback required */
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw if (taskq_dispatch(SATA_TXLT_TASKQ(spx),
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw (task_func_t *)scsipkt->pkt_comp, (void *) scsipkt,
4360436b3c604bc28d37be269ad152b4c38157c3pawelw TQ_SLEEP) == NULL)
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw /* Scheduling the callback failed */
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw return (TRAN_BUSY);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (TRAN_ACCEPT);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * SATA translate command: Mode Select.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Translated into appropriate SATA command or emulated.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Saving parameters is not supported.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Changing device capacity is not supported (although theoretically
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * possible by executing SET FEATURES/SET MAX ADDRESS)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Assumption is that the target driver is working correctly.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * More than one SATA command may be executed to perform operations specified
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * by mode select pages. The first error terminates further execution.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Operations performed successully are not backed-up in such case.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik * NOTE: Implemented pages:
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik * - caching page
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik * - informational exception page
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik * - acoustic management page
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu * - power condition page
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Caching setup is remembered so it could be re-stored in case of
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * an unexpected device reset.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik * Returns TRAN_XXXX.
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik * If TRAN_ACCEPT is returned, appropriate values are set in scsi_pkt fields.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_txlt_mode_select(sata_pkt_txlate_t *spx)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf struct scsi_pkt *scsipkt = spx->txlt_scsi_pkt;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf struct buf *bp = spx->txlt_sata_pkt->satapkt_cmd.satacmd_bp;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf struct scsi_extended_sense *sense;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int len, pagelen, count, pllen;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf uint8_t *buf; /* mode select buffer */
f39c049be37ba5b8f96704f41d6532332ae16318pawelw int rval, stat, reason;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf uint_t nointr_flag;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int dmod = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG2(SATA_DBG_SCSI_IF, spx->txlt_sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_txlt_mode_select, pc %x page code 0x%02x\n",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_scsi_pkt->pkt_cdbp[2] >> 6,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_scsi_pkt->pkt_cdbp[2] & 0x3f);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&(SATA_TXLT_CPORT_MUTEX(spx)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
f39c049be37ba5b8f96704f41d6532332ae16318pawelw if (((rval = sata_txlt_generic_pkt_info(spx, &reason)) !=
f39c049be37ba5b8f96704f41d6532332ae16318pawelw TRAN_ACCEPT) || (reason == CMD_DEV_GONE)) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&(SATA_TXLT_CPORT_MUTEX(spx)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (rval);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik /*
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik * If in interrupt context, reject this packet because it may result
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik * in issuing a synchronous command to HBA.
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik */
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik if (servicing_interrupt()) {
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik SATADBG1(SATA_DBG_INTR_CTX, spx->txlt_sata_hba_inst,
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik "sata_txlt_mode_select: rejecting command because "
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik "of interrupt context\n", NULL);
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik mutex_exit(&(SATA_TXLT_CPORT_MUTEX(spx)));
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik return (TRAN_BUSY);
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rval = TRAN_ACCEPT;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsipkt->pkt_reason = CMD_CMPLT;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsipkt->pkt_state = STATE_GOT_BUS | STATE_GOT_TARGET |
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf STATE_SENT_CMD | STATE_GOT_STATUS;
0d6e6b604e28d77cf288ed1fbe03b50a0ca103fbPawel Wojcik nointr_flag = scsipkt->pkt_flags & FLAG_NOINTR;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Reject not supported request */
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls if (! (scsipkt->pkt_cdbp[1] & 0x10)) { /* No support for PF bit = 0 */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *scsipkt->pkt_scbp = STATUS_CHECK;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense = sata_arq_sense(spx);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense->es_key = KEY_ILLEGAL_REQUEST;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sense->es_add_code = SD_SCSI_ASC_INVALID_FIELD_IN_CDB;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf goto done;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (scsipkt->pkt_cdbp[0] == SCMD_MODE_SELECT) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf pllen = scsipkt->pkt_cdbp[4];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf pllen = scsipkt->pkt_cdbp[7];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf pllen = (pllen << 8) | scsipkt->pkt_cdbp[7];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *scsipkt->pkt_scbp = STATUS_GOOD; /* Presumed outcome */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (bp != NULL && bp->b_un.b_addr && bp->b_bcount && pllen != 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf buf = (uint8_t *)bp->b_un.b_addr;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf count = MIN(bp->b_bcount, pllen);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsipkt->pkt_state |= STATE_XFERRED_DATA;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsipkt->pkt_resid = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf pllen = count;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Check the header to skip the block descriptor(s) - we
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * do not support setting device capacity.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Existing macros do not recognize long LBA dscriptor,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * hence manual calculation.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (scsipkt->pkt_cdbp[0] == SCMD_MODE_SELECT) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* 6-bytes CMD, 4 bytes header */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (count <= 4)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf goto done; /* header only */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf len = buf[3] + 4;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* 10-bytes CMD, 8 bytes header */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (count <= 8)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf goto done; /* header only */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf len = buf[6];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf len = (len << 8) + buf[7] + 8;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (len >= count)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf goto done; /* header + descriptor(s) only */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf pllen -= len; /* remaining data length */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * We may be executing SATA command and want to execute it
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * in SYNCH mode, regardless of scsi_pkt setting.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Save scsi_pkt setting and indicate SYNCH mode
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((scsipkt->pkt_flags & FLAG_NOINTR) == 0 &&
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsipkt->pkt_comp != NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsipkt->pkt_flags |= FLAG_NOINTR;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_sata_pkt->satapkt_op_mode = SATA_OPMODE_SYNCH;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * len is now the offset to a first mode select page
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Process all pages
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf while (pllen > 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf switch ((int)buf[len]) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case MODEPAGE_CACHING:
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls /* No support for SP (saving) */
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls if (scsipkt->pkt_cdbp[1] & 0x01) {
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls *scsipkt->pkt_scbp = STATUS_CHECK;
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls sense = sata_arq_sense(spx);
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls sense->es_key = KEY_ILLEGAL_REQUEST;
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls sense->es_add_code =
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SD_SCSI_ASC_INVALID_FIELD_IN_CDB;
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls goto done;
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf stat = sata_mode_select_page_8(spx,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (struct mode_cache_scsi3 *)&buf[len],
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf pllen, &pagelen, &rval, &dmod);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls * The pagelen value indicates the number of
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls * parameter bytes already processed.
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls * The rval is the return value from
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls * sata_tran_start().
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls * The stat indicates the overall status of
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls * the operation(s).
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls */
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls if (stat != SATA_SUCCESS)
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls /*
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls * Page processing did not succeed -
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls * all error info is already set-up,
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls * just return
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls */
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls pllen = 0; /* this breaks the loop */
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls else {
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls len += pagelen;
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls pllen -= pagelen;
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls }
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls break;
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls case MODEPAGE_INFO_EXCPT:
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls stat = sata_mode_select_page_1c(spx,
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls (struct mode_info_excpt_page *)&buf[len],
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls pllen, &pagelen, &rval, &dmod);
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls /*
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls * The pagelen value indicates the number of
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * parameter bytes already processed.
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls * The rval is the return value from
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * sata_tran_start().
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * The stat indicates the overall status of
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * the operation(s).
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (stat != SATA_SUCCESS)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Page processing did not succeed -
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * all error info is already set-up,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * just return
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf pllen = 0; /* this breaks the loop */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf len += pagelen;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf pllen -= pagelen;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls case MODEPAGE_ACOUSTIC_MANAG:
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls stat = sata_mode_select_page_30(spx,
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls (struct mode_acoustic_management *)
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls &buf[len], pllen, &pagelen, &rval, &dmod);
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls /*
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls * The pagelen value indicates the number of
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls * parameter bytes already processed.
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls * The rval is the return value from
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls * sata_tran_start().
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls * The stat indicates the overall status of
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls * the operation(s).
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls */
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls if (stat != SATA_SUCCESS)
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls /*
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls * Page processing did not succeed -
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls * all error info is already set-up,
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls * just return
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls */
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls pllen = 0; /* this breaks the loop */
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls else {
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls len += pagelen;
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls pllen -= pagelen;
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls }
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu break;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu case MODEPAGE_POWER_COND:
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu stat = sata_mode_select_page_1a(spx,
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu (struct mode_info_power_cond *)&buf[len],
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu pllen, &pagelen, &rval, &dmod);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu /*
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu * The pagelen value indicates the number of
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu * parameter bytes already processed.
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu * The rval is the return value from
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu * sata_tran_start().
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu * The stat indicates the overall status of
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu * the operation(s).
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu */
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if (stat != SATA_SUCCESS)
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu /*
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu * Page processing did not succeed -
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu * all error info is already set-up,
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu * just return
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu */
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu pllen = 0; /* this breaks the loop */
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu else {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu len += pagelen;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu pllen -= pagelen;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu }
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf default:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *scsipkt->pkt_scbp = STATUS_CHECK;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense = sata_arq_sense(spx);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense->es_key = KEY_ILLEGAL_REQUEST;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense->es_add_code =
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SD_SCSI_ASC_INVALID_FIELD_IN_PARAMS_LIST;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf goto done;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfdone:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&(SATA_TXLT_CPORT_MUTEX(spx)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * If device parameters were modified, fetch and store the new
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Identify Device data. Since port mutex could have been released
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * for accessing HBA driver, we need to re-check device existence.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (dmod != 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_drive_info_t new_sdinfo, *sdinfo;
c75976d12071ddd21443266260066ba036671682pawelw int rv = 0;
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw /*
c75976d12071ddd21443266260066ba036671682pawelw * Following statement has to be changed if this function is
c75976d12071ddd21443266260066ba036671682pawelw * used for devices other than SATA hard disks.
c75976d12071ddd21443266260066ba036671682pawelw */
c75976d12071ddd21443266260066ba036671682pawelw new_sdinfo.satadrv_type = SATA_DTYPE_ATADISK;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf new_sdinfo.satadrv_addr =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_sata_pkt->satapkt_device.satadev_addr;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rv = sata_fetch_device_identify_data(spx->txlt_sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf &new_sdinfo);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&(SATA_TXLT_CPORT_MUTEX(spx)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Since port mutex could have been released when
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * accessing HBA driver, we need to re-check that the
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * framework still holds the device info structure.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo = sata_get_device_info(spx->txlt_sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf &spx->txlt_sata_pkt->satapkt_device);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sdinfo != NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Device still has info structure in the
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * sata framework. Copy newly fetched info
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (rv == 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_id = new_sdinfo.satadrv_id;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_save_drive_settings(sdinfo);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Could not fetch new data - invalidate
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * sata_drive_info. That makes device
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * unusable.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_type = SATA_DTYPE_UNKNOWN;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_state = SATA_STATE_UNKNOWN;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (rv != 0 || sdinfo == NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * This changes the overall mode select completion
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * reason to a failed one !!!!!
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *scsipkt->pkt_scbp = STATUS_CHECK;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense = sata_arq_sense(spx);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsipkt->pkt_reason = CMD_INCOMPLETE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rval = TRAN_ACCEPT;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&(SATA_TXLT_CPORT_MUTEX(spx)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Restore the scsi pkt flags */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsipkt->pkt_flags &= ~FLAG_NOINTR;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsipkt->pkt_flags |= nointr_flag;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG1(SATA_DBG_SCSI_IF, spx->txlt_sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "Scsi_pkt completion reason %x\n", scsipkt->pkt_reason);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((scsipkt->pkt_flags & FLAG_NOINTR) == 0 &&
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsipkt->pkt_comp != NULL)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* scsi callback required */
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw if (taskq_dispatch(SATA_TXLT_TASKQ(spx),
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw (task_func_t *)scsipkt->pkt_comp, (void *) scsipkt,
4360436b3c604bc28d37be269ad152b4c38157c3pawelw TQ_SLEEP) == NULL)
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw /* Scheduling the callback failed */
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw return (TRAN_BUSY);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (rval);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Translate command: Log Sense
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_txlt_log_sense(sata_pkt_txlate_t *spx)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
c03acfcad7780db4ddf763511a82026680b3b2c1ls struct scsi_pkt *scsipkt = spx->txlt_scsi_pkt;
c03acfcad7780db4ddf763511a82026680b3b2c1ls struct buf *bp = spx->txlt_sata_pkt->satapkt_cmd.satacmd_bp;
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_drive_info_t *sdinfo;
c03acfcad7780db4ddf763511a82026680b3b2c1ls struct scsi_extended_sense *sense;
c03acfcad7780db4ddf763511a82026680b3b2c1ls int len, count, alc_len;
c03acfcad7780db4ddf763511a82026680b3b2c1ls int pc; /* Page Control code */
c03acfcad7780db4ddf763511a82026680b3b2c1ls int page_code; /* Page code */
c03acfcad7780db4ddf763511a82026680b3b2c1ls uint8_t *buf; /* log sense buffer */
f39c049be37ba5b8f96704f41d6532332ae16318pawelw int rval, reason;
c03acfcad7780db4ddf763511a82026680b3b2c1ls#define MAX_LOG_SENSE_PAGE_SIZE 512
c03acfcad7780db4ddf763511a82026680b3b2c1ls
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG2(SATA_DBG_SCSI_IF, spx->txlt_sata_hba_inst,
c03acfcad7780db4ddf763511a82026680b3b2c1ls "sata_txlt_log_sense, pc 0x%x, page code 0x%x\n",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_scsi_pkt->pkt_cdbp[2] >> 6,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_scsi_pkt->pkt_cdbp[2] & 0x3f);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
c03acfcad7780db4ddf763511a82026680b3b2c1ls buf = kmem_zalloc(MAX_LOG_SENSE_PAGE_SIZE, KM_SLEEP);
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls mutex_enter(&(SATA_TXLT_CPORT_MUTEX(spx)));
c03acfcad7780db4ddf763511a82026680b3b2c1ls
f39c049be37ba5b8f96704f41d6532332ae16318pawelw if (((rval = sata_txlt_generic_pkt_info(spx, &reason)) !=
f39c049be37ba5b8f96704f41d6532332ae16318pawelw TRAN_ACCEPT) || (reason == CMD_DEV_GONE)) {
c03acfcad7780db4ddf763511a82026680b3b2c1ls mutex_exit(&(SATA_TXLT_CPORT_MUTEX(spx)));
c03acfcad7780db4ddf763511a82026680b3b2c1ls kmem_free(buf, MAX_LOG_SENSE_PAGE_SIZE);
c03acfcad7780db4ddf763511a82026680b3b2c1ls return (rval);
c03acfcad7780db4ddf763511a82026680b3b2c1ls }
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik /*
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik * If in interrupt context, reject this packet because it may result
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik * in issuing a synchronous command to HBA.
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik */
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik if (servicing_interrupt()) {
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik SATADBG1(SATA_DBG_INTR_CTX, spx->txlt_sata_hba_inst,
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik "sata_log_sense: rejecting command because "
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik "of interrupt context\n", NULL);
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik mutex_exit(&(SATA_TXLT_CPORT_MUTEX(spx)));
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik kmem_free(buf, MAX_LOG_SENSE_PAGE_SIZE);
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik return (TRAN_BUSY);
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik }
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls scsipkt->pkt_reason = CMD_CMPLT;
c03acfcad7780db4ddf763511a82026680b3b2c1ls scsipkt->pkt_state = STATE_GOT_BUS | STATE_GOT_TARGET |
c03acfcad7780db4ddf763511a82026680b3b2c1ls STATE_SENT_CMD | STATE_GOT_STATUS;
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls pc = scsipkt->pkt_cdbp[2] >> 6;
c03acfcad7780db4ddf763511a82026680b3b2c1ls page_code = scsipkt->pkt_cdbp[2] & 0x3f;
c03acfcad7780db4ddf763511a82026680b3b2c1ls
37a077ef1920ee044b2887247b2a802e726d3368ls /* Reject not supported request for all but cumulative values */
c03acfcad7780db4ddf763511a82026680b3b2c1ls switch (pc) {
37a077ef1920ee044b2887247b2a802e726d3368ls case PC_CUMULATIVE_VALUES:
c03acfcad7780db4ddf763511a82026680b3b2c1ls break;
c03acfcad7780db4ddf763511a82026680b3b2c1ls default:
c03acfcad7780db4ddf763511a82026680b3b2c1ls *scsipkt->pkt_scbp = STATUS_CHECK;
c03acfcad7780db4ddf763511a82026680b3b2c1ls sense = sata_arq_sense(spx);
c03acfcad7780db4ddf763511a82026680b3b2c1ls sense->es_key = KEY_ILLEGAL_REQUEST;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sense->es_add_code = SD_SCSI_ASC_INVALID_FIELD_IN_CDB;
c03acfcad7780db4ddf763511a82026680b3b2c1ls goto done;
c03acfcad7780db4ddf763511a82026680b3b2c1ls }
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls switch (page_code) {
c03acfcad7780db4ddf763511a82026680b3b2c1ls case PAGE_CODE_GET_SUPPORTED_LOG_PAGES:
c03acfcad7780db4ddf763511a82026680b3b2c1ls case PAGE_CODE_SELF_TEST_RESULTS:
c03acfcad7780db4ddf763511a82026680b3b2c1ls case PAGE_CODE_INFORMATION_EXCEPTIONS:
c03acfcad7780db4ddf763511a82026680b3b2c1ls case PAGE_CODE_SMART_READ_DATA:
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu case PAGE_CODE_START_STOP_CYCLE_COUNTER:
c03acfcad7780db4ddf763511a82026680b3b2c1ls break;
c03acfcad7780db4ddf763511a82026680b3b2c1ls default:
c03acfcad7780db4ddf763511a82026680b3b2c1ls *scsipkt->pkt_scbp = STATUS_CHECK;
c03acfcad7780db4ddf763511a82026680b3b2c1ls sense = sata_arq_sense(spx);
c03acfcad7780db4ddf763511a82026680b3b2c1ls sense->es_key = KEY_ILLEGAL_REQUEST;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sense->es_add_code = SD_SCSI_ASC_INVALID_FIELD_IN_CDB;
c03acfcad7780db4ddf763511a82026680b3b2c1ls goto done;
c03acfcad7780db4ddf763511a82026680b3b2c1ls }
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls if (bp != NULL && bp->b_un.b_addr && bp->b_bcount) {
8d483882aa3390058094b043f3d62187b5d1de03mlf /*
8d483882aa3390058094b043f3d62187b5d1de03mlf * Because log sense uses local buffers for data retrieval from
8d483882aa3390058094b043f3d62187b5d1de03mlf * the devices and sets the data programatically in the
8d483882aa3390058094b043f3d62187b5d1de03mlf * original specified buffer, release preallocated DMA
8d483882aa3390058094b043f3d62187b5d1de03mlf * resources before storing data in the original buffer,
8d483882aa3390058094b043f3d62187b5d1de03mlf * so no unwanted DMA sync would take place.
8d483882aa3390058094b043f3d62187b5d1de03mlf */
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_id_t *sata_id;
8d483882aa3390058094b043f3d62187b5d1de03mlf
8d483882aa3390058094b043f3d62187b5d1de03mlf sata_scsi_dmafree(NULL, scsipkt);
8d483882aa3390058094b043f3d62187b5d1de03mlf
c03acfcad7780db4ddf763511a82026680b3b2c1ls len = 0;
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls /* Build log parameter header */
c03acfcad7780db4ddf763511a82026680b3b2c1ls buf[len++] = page_code; /* page code as in the CDB */
c03acfcad7780db4ddf763511a82026680b3b2c1ls buf[len++] = 0; /* reserved */
c03acfcad7780db4ddf763511a82026680b3b2c1ls buf[len++] = 0; /* Zero out page length for now (MSB) */
c03acfcad7780db4ddf763511a82026680b3b2c1ls buf[len++] = 0; /* (LSB) */
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls sdinfo = sata_get_device_info(
c03acfcad7780db4ddf763511a82026680b3b2c1ls spx->txlt_sata_hba_inst,
c03acfcad7780db4ddf763511a82026680b3b2c1ls &spx->txlt_sata_pkt->satapkt_device);
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls /*
c03acfcad7780db4ddf763511a82026680b3b2c1ls * Add requested pages.
c03acfcad7780db4ddf763511a82026680b3b2c1ls */
c03acfcad7780db4ddf763511a82026680b3b2c1ls switch (page_code) {
c03acfcad7780db4ddf763511a82026680b3b2c1ls case PAGE_CODE_GET_SUPPORTED_LOG_PAGES:
c03acfcad7780db4ddf763511a82026680b3b2c1ls len = sata_build_lsense_page_0(sdinfo, buf + len);
c03acfcad7780db4ddf763511a82026680b3b2c1ls break;
c03acfcad7780db4ddf763511a82026680b3b2c1ls case PAGE_CODE_SELF_TEST_RESULTS:
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_id = &sdinfo->satadrv_id;
c03acfcad7780db4ddf763511a82026680b3b2c1ls if ((! (sata_id->ai_cmdset84 &
c03acfcad7780db4ddf763511a82026680b3b2c1ls SATA_SMART_SELF_TEST_SUPPORTED)) ||
c03acfcad7780db4ddf763511a82026680b3b2c1ls (! (sata_id->ai_features87 &
c03acfcad7780db4ddf763511a82026680b3b2c1ls SATA_SMART_SELF_TEST_SUPPORTED))) {
c03acfcad7780db4ddf763511a82026680b3b2c1ls *scsipkt->pkt_scbp = STATUS_CHECK;
c03acfcad7780db4ddf763511a82026680b3b2c1ls sense = sata_arq_sense(spx);
c03acfcad7780db4ddf763511a82026680b3b2c1ls sense->es_key = KEY_ILLEGAL_REQUEST;
c03acfcad7780db4ddf763511a82026680b3b2c1ls sense->es_add_code =
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SD_SCSI_ASC_INVALID_FIELD_IN_CDB;
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls goto done;
c03acfcad7780db4ddf763511a82026680b3b2c1ls }
c03acfcad7780db4ddf763511a82026680b3b2c1ls len = sata_build_lsense_page_10(sdinfo, buf + len,
c03acfcad7780db4ddf763511a82026680b3b2c1ls spx->txlt_sata_hba_inst);
c03acfcad7780db4ddf763511a82026680b3b2c1ls break;
c03acfcad7780db4ddf763511a82026680b3b2c1ls case PAGE_CODE_INFORMATION_EXCEPTIONS:
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_id = &sdinfo->satadrv_id;
c03acfcad7780db4ddf763511a82026680b3b2c1ls if (! (sata_id->ai_cmdset82 & SATA_SMART_SUPPORTED)) {
c03acfcad7780db4ddf763511a82026680b3b2c1ls *scsipkt->pkt_scbp = STATUS_CHECK;
c03acfcad7780db4ddf763511a82026680b3b2c1ls sense = sata_arq_sense(spx);
c03acfcad7780db4ddf763511a82026680b3b2c1ls sense->es_key = KEY_ILLEGAL_REQUEST;
c03acfcad7780db4ddf763511a82026680b3b2c1ls sense->es_add_code =
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SD_SCSI_ASC_INVALID_FIELD_IN_CDB;
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls goto done;
c03acfcad7780db4ddf763511a82026680b3b2c1ls }
c03acfcad7780db4ddf763511a82026680b3b2c1ls if (! (sata_id->ai_features85 & SATA_SMART_ENABLED)) {
c03acfcad7780db4ddf763511a82026680b3b2c1ls *scsipkt->pkt_scbp = STATUS_CHECK;
c03acfcad7780db4ddf763511a82026680b3b2c1ls sense = sata_arq_sense(spx);
c03acfcad7780db4ddf763511a82026680b3b2c1ls sense->es_key = KEY_ABORTED_COMMAND;
c03acfcad7780db4ddf763511a82026680b3b2c1ls sense->es_add_code =
c03acfcad7780db4ddf763511a82026680b3b2c1ls SCSI_ASC_ATA_DEV_FEAT_NOT_ENABLED;
c03acfcad7780db4ddf763511a82026680b3b2c1ls sense->es_qual_code =
c03acfcad7780db4ddf763511a82026680b3b2c1ls SCSI_ASCQ_ATA_DEV_FEAT_NOT_ENABLED;
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls goto done;
c03acfcad7780db4ddf763511a82026680b3b2c1ls }
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls len = sata_build_lsense_page_2f(sdinfo, buf + len,
c03acfcad7780db4ddf763511a82026680b3b2c1ls spx->txlt_sata_hba_inst);
c03acfcad7780db4ddf763511a82026680b3b2c1ls break;
c03acfcad7780db4ddf763511a82026680b3b2c1ls case PAGE_CODE_SMART_READ_DATA:
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_id = &sdinfo->satadrv_id;
c03acfcad7780db4ddf763511a82026680b3b2c1ls if (! (sata_id->ai_cmdset82 & SATA_SMART_SUPPORTED)) {
c03acfcad7780db4ddf763511a82026680b3b2c1ls *scsipkt->pkt_scbp = STATUS_CHECK;
c03acfcad7780db4ddf763511a82026680b3b2c1ls sense = sata_arq_sense(spx);
c03acfcad7780db4ddf763511a82026680b3b2c1ls sense->es_key = KEY_ILLEGAL_REQUEST;
c03acfcad7780db4ddf763511a82026680b3b2c1ls sense->es_add_code =
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SD_SCSI_ASC_INVALID_FIELD_IN_CDB;
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls goto done;
c03acfcad7780db4ddf763511a82026680b3b2c1ls }
c03acfcad7780db4ddf763511a82026680b3b2c1ls if (! (sata_id->ai_features85 & SATA_SMART_ENABLED)) {
c03acfcad7780db4ddf763511a82026680b3b2c1ls *scsipkt->pkt_scbp = STATUS_CHECK;
c03acfcad7780db4ddf763511a82026680b3b2c1ls sense = sata_arq_sense(spx);
c03acfcad7780db4ddf763511a82026680b3b2c1ls sense->es_key = KEY_ABORTED_COMMAND;
c03acfcad7780db4ddf763511a82026680b3b2c1ls sense->es_add_code =
c03acfcad7780db4ddf763511a82026680b3b2c1ls SCSI_ASC_ATA_DEV_FEAT_NOT_ENABLED;
c03acfcad7780db4ddf763511a82026680b3b2c1ls sense->es_qual_code =
c03acfcad7780db4ddf763511a82026680b3b2c1ls SCSI_ASCQ_ATA_DEV_FEAT_NOT_ENABLED;
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls goto done;
c03acfcad7780db4ddf763511a82026680b3b2c1ls }
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls /* This page doesn't include a page header */
c03acfcad7780db4ddf763511a82026680b3b2c1ls len = sata_build_lsense_page_30(sdinfo, buf,
c03acfcad7780db4ddf763511a82026680b3b2c1ls spx->txlt_sata_hba_inst);
c03acfcad7780db4ddf763511a82026680b3b2c1ls goto no_header;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu case PAGE_CODE_START_STOP_CYCLE_COUNTER:
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sata_id = &sdinfo->satadrv_id;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if (! (sata_id->ai_cmdset82 & SATA_SMART_SUPPORTED)) {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu *scsipkt->pkt_scbp = STATUS_CHECK;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sense = sata_arq_sense(spx);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sense->es_key = KEY_ILLEGAL_REQUEST;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sense->es_add_code =
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu SD_SCSI_ASC_INVALID_FIELD_IN_CDB;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu goto done;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu }
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if (! (sata_id->ai_features85 & SATA_SMART_ENABLED)) {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu *scsipkt->pkt_scbp = STATUS_CHECK;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sense = sata_arq_sense(spx);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sense->es_key = KEY_ABORTED_COMMAND;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sense->es_add_code =
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu SCSI_ASC_ATA_DEV_FEAT_NOT_ENABLED;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sense->es_qual_code =
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu SCSI_ASCQ_ATA_DEV_FEAT_NOT_ENABLED;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu goto done;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu }
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu len = sata_build_lsense_page_0e(sdinfo, buf, spx);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu goto no_header;
c03acfcad7780db4ddf763511a82026680b3b2c1ls default:
c03acfcad7780db4ddf763511a82026680b3b2c1ls /* Invalid request */
c03acfcad7780db4ddf763511a82026680b3b2c1ls *scsipkt->pkt_scbp = STATUS_CHECK;
c03acfcad7780db4ddf763511a82026680b3b2c1ls sense = sata_arq_sense(spx);
c03acfcad7780db4ddf763511a82026680b3b2c1ls sense->es_key = KEY_ILLEGAL_REQUEST;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sense->es_add_code = SD_SCSI_ASC_INVALID_FIELD_IN_CDB;
c03acfcad7780db4ddf763511a82026680b3b2c1ls goto done;
c03acfcad7780db4ddf763511a82026680b3b2c1ls }
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls /* set parameter log sense data length */
c03acfcad7780db4ddf763511a82026680b3b2c1ls buf[2] = len >> 8; /* log sense length (MSB) */
c03acfcad7780db4ddf763511a82026680b3b2c1ls buf[3] = len & 0xff; /* log sense length (LSB) */
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls len += SCSI_LOG_PAGE_HDR_LEN;
c03acfcad7780db4ddf763511a82026680b3b2c1ls ASSERT(len <= MAX_LOG_SENSE_PAGE_SIZE);
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1lsno_header:
c03acfcad7780db4ddf763511a82026680b3b2c1ls /* Check allocation length */
c03acfcad7780db4ddf763511a82026680b3b2c1ls alc_len = scsipkt->pkt_cdbp[7];
c03acfcad7780db4ddf763511a82026680b3b2c1ls alc_len = (len << 8) | scsipkt->pkt_cdbp[8];
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls /*
c03acfcad7780db4ddf763511a82026680b3b2c1ls * We do not check for possible parameters truncation
c03acfcad7780db4ddf763511a82026680b3b2c1ls * (alc_len < len) assuming that the target driver works
c03acfcad7780db4ddf763511a82026680b3b2c1ls * correctly. Just avoiding overrun.
c03acfcad7780db4ddf763511a82026680b3b2c1ls * Copy no more than requested and possible, buffer-wise.
c03acfcad7780db4ddf763511a82026680b3b2c1ls */
c03acfcad7780db4ddf763511a82026680b3b2c1ls count = MIN(alc_len, len);
c03acfcad7780db4ddf763511a82026680b3b2c1ls count = MIN(bp->b_bcount, count);
c03acfcad7780db4ddf763511a82026680b3b2c1ls bcopy(buf, bp->b_un.b_addr, count);
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls scsipkt->pkt_state |= STATE_XFERRED_DATA;
c03acfcad7780db4ddf763511a82026680b3b2c1ls scsipkt->pkt_resid = alc_len > count ? alc_len - count : 0;
c03acfcad7780db4ddf763511a82026680b3b2c1ls }
c03acfcad7780db4ddf763511a82026680b3b2c1ls *scsipkt->pkt_scbp = STATUS_GOOD;
c03acfcad7780db4ddf763511a82026680b3b2c1lsdone:
c03acfcad7780db4ddf763511a82026680b3b2c1ls mutex_exit(&(SATA_TXLT_CPORT_MUTEX(spx)));
c03acfcad7780db4ddf763511a82026680b3b2c1ls (void) kmem_free(buf, MAX_LOG_SENSE_PAGE_SIZE);
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls SATADBG1(SATA_DBG_SCSI_IF, spx->txlt_sata_hba_inst,
c03acfcad7780db4ddf763511a82026680b3b2c1ls "Scsi_pkt completion reason %x\n", scsipkt->pkt_reason);
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls if ((scsipkt->pkt_flags & FLAG_NOINTR) == 0 &&
c03acfcad7780db4ddf763511a82026680b3b2c1ls scsipkt->pkt_comp != NULL)
c03acfcad7780db4ddf763511a82026680b3b2c1ls /* scsi callback required */
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw if (taskq_dispatch(SATA_TXLT_TASKQ(spx),
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw (task_func_t *)scsipkt->pkt_comp, (void *) scsipkt,
4360436b3c604bc28d37be269ad152b4c38157c3pawelw TQ_SLEEP) == NULL)
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw /* Scheduling the callback failed */
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw return (TRAN_BUSY);
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls return (TRAN_ACCEPT);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Translate command: Log Select
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Not implemented at this time - returns invalid command response.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chustatic int
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_txlt_log_select(sata_pkt_txlate_t *spx)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG1(SATA_DBG_SCSI_IF, spx->txlt_sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_txlt_log_select\n", NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (sata_txlt_invalid_command(spx));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Translate command: Read (various types).
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Translated into appropriate type of ATA READ command
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * for SATA hard disks.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Both the device capabilities and requested operation mode are
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * considered.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Following scsi cdb fields are ignored:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * rdprotect, dpo, fua, fua_nv, group_number.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * If SATA_ENABLE_QUEUING flag is set (in the global SATA HBA framework
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * enable variable sata_func_enable), the capability of the controller and
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * capability of a device are checked and if both support queueing, read
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * request will be translated to READ_DMA_QUEUEING or READ_DMA_QUEUEING_EXT
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * command rather than plain READ_XXX command.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * If SATA_ENABLE_NCQ flag is set in addition to SATA_ENABLE_QUEUING flag and
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * both the controller and device suport such functionality, the read
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * request will be translated to READ_FPDMA_QUEUED command.
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw * In both cases the maximum queue depth is derived as minimum of:
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw * HBA capability,device capability and sata_max_queue_depth variable setting.
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw * The value passed to HBA driver is decremented by 1, because only 5 bits are
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw * used to pass max queue depth value, and the maximum possible queue depth
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw * is 32.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Returns TRAN_ACCEPT or code returned by sata_hba_start() and
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * appropriate values in scsi_pkt fields.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_txlt_read(sata_pkt_txlate_t *spx)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf struct scsi_pkt *scsipkt = spx->txlt_scsi_pkt;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_cmd_t *scmd = &spx->txlt_sata_pkt->satapkt_cmd;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_drive_info_t *sdinfo;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst_t *shi = SATA_TXLT_HBA_INST(spx);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int cport = SATA_TXLT_CPORT(spx);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf uint16_t sec_count;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf uint64_t lba;
f39c049be37ba5b8f96704f41d6532332ae16318pawelw int rval, reason;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int synch;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&(SATA_TXLT_CPORT_MUTEX(spx)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
f39c049be37ba5b8f96704f41d6532332ae16318pawelw if (((rval = sata_txlt_generic_pkt_info(spx, &reason)) !=
f39c049be37ba5b8f96704f41d6532332ae16318pawelw TRAN_ACCEPT) || (reason == CMD_DEV_GONE)) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&(SATA_TXLT_CPORT_MUTEX(spx)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (rval);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo = sata_get_device_info(spx->txlt_sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf &spx->txlt_sata_pkt->satapkt_device);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_flags.sata_data_direction = SATA_DIR_READ;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
4360436b3c604bc28d37be269ad152b4c38157c3pawelw * Extract LBA and sector count from scsi CDB.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf switch ((uint_t)scsipkt->pkt_cdbp[0]) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SCMD_READ:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* 6-byte scsi read cmd : 0x08 */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf lba = (scsipkt->pkt_cdbp[1] & 0x1f);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf lba = (lba << 8) | scsipkt->pkt_cdbp[2];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf lba = (lba << 8) | scsipkt->pkt_cdbp[3];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sec_count = scsipkt->pkt_cdbp[4];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* sec_count 0 will be interpreted as 256 by a device */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SCMD_READ_G1:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* 10-bytes scsi read command : 0x28 */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf lba = scsipkt->pkt_cdbp[2];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf lba = (lba << 8) | scsipkt->pkt_cdbp[3];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf lba = (lba << 8) | scsipkt->pkt_cdbp[4];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf lba = (lba << 8) | scsipkt->pkt_cdbp[5];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sec_count = scsipkt->pkt_cdbp[7];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sec_count = (sec_count << 8) | scsipkt->pkt_cdbp[8];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SCMD_READ_G5:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* 12-bytes scsi read command : 0xA8 */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf lba = scsipkt->pkt_cdbp[2];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf lba = (lba << 8) | scsipkt->pkt_cdbp[3];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf lba = (lba << 8) | scsipkt->pkt_cdbp[4];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf lba = (lba << 8) | scsipkt->pkt_cdbp[5];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sec_count = scsipkt->pkt_cdbp[6];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sec_count = (sec_count << 8) | scsipkt->pkt_cdbp[7];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sec_count = (sec_count << 8) | scsipkt->pkt_cdbp[8];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sec_count = (sec_count << 8) | scsipkt->pkt_cdbp[9];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SCMD_READ_G4:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* 16-bytes scsi read command : 0x88 */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf lba = scsipkt->pkt_cdbp[2];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf lba = (lba << 8) | scsipkt->pkt_cdbp[3];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf lba = (lba << 8) | scsipkt->pkt_cdbp[4];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf lba = (lba << 8) | scsipkt->pkt_cdbp[5];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf lba = (lba << 8) | scsipkt->pkt_cdbp[6];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf lba = (lba << 8) | scsipkt->pkt_cdbp[7];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf lba = (lba << 8) | scsipkt->pkt_cdbp[8];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf lba = (lba << 8) | scsipkt->pkt_cdbp[9];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sec_count = scsipkt->pkt_cdbp[10];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sec_count = (sec_count << 8) | scsipkt->pkt_cdbp[11];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sec_count = (sec_count << 8) | scsipkt->pkt_cdbp[12];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sec_count = (sec_count << 8) | scsipkt->pkt_cdbp[13];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf default:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Unsupported command */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&(SATA_TXLT_CPORT_MUTEX(spx)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (sata_txlt_invalid_command(spx));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Check if specified address exceeds device capacity
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((lba >= sdinfo->satadrv_capacity) ||
4e1e976ddd007cda18e3ce61b2d9ff587a5fd4e7pawelw ((lba + sec_count) > sdinfo->satadrv_capacity)) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* LBA out of range */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&(SATA_TXLT_CPORT_MUTEX(spx)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (sata_txlt_lba_out_of_range(spx));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
4360436b3c604bc28d37be269ad152b4c38157c3pawelw /*
4360436b3c604bc28d37be269ad152b4c38157c3pawelw * For zero-length transfer, emulate good completion of the command
4360436b3c604bc28d37be269ad152b4c38157c3pawelw * (reasons for rejecting the command were already checked).
4360436b3c604bc28d37be269ad152b4c38157c3pawelw * No DMA resources were allocated.
4360436b3c604bc28d37be269ad152b4c38157c3pawelw */
4360436b3c604bc28d37be269ad152b4c38157c3pawelw if (spx->txlt_dma_cookie_list == NULL) {
4360436b3c604bc28d37be269ad152b4c38157c3pawelw mutex_exit(&(SATA_TXLT_CPORT_MUTEX(spx)));
4360436b3c604bc28d37be269ad152b4c38157c3pawelw return (sata_emul_rw_completion(spx));
4360436b3c604bc28d37be269ad152b4c38157c3pawelw }
4360436b3c604bc28d37be269ad152b4c38157c3pawelw
4360436b3c604bc28d37be269ad152b4c38157c3pawelw /*
4360436b3c604bc28d37be269ad152b4c38157c3pawelw * Build cmd block depending on the device capability and
4360436b3c604bc28d37be269ad152b4c38157c3pawelw * requested operation mode.
4360436b3c604bc28d37be269ad152b4c38157c3pawelw * Do not bother with non-dma mode - we are working only with
4360436b3c604bc28d37be269ad152b4c38157c3pawelw * devices supporting DMA.
4360436b3c604bc28d37be269ad152b4c38157c3pawelw */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_addr_type = ATA_ADDR_LBA;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_device_reg = SATA_ADH_LBA;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_cmd_reg = SATAC_READ_DMA;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sdinfo->satadrv_features_support & SATA_DEV_F_LBA48) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_addr_type = ATA_ADDR_LBA48;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_cmd_reg = SATAC_READ_DMA_EXT;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_sec_count_msb = sec_count >> 8;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#ifndef __lock_lint
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_lba_low_msb = (lba >> 24) & 0xff;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_lba_mid_msb = (lba >> 32) & 0xff;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_lba_high_msb = lba >> 40;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#endif
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else if (sdinfo->satadrv_features_support & SATA_DEV_F_LBA28) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_addr_type = ATA_ADDR_LBA28;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_device_reg = SATA_ADH_LBA | ((lba >> 24) & 0xf);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_sec_count_lsb = sec_count & 0xff;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_lba_low_lsb = lba & 0xff;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_lba_mid_lsb = (lba >> 8) & 0xff;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_lba_high_lsb = (lba >> 16) & 0xff;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_features_reg = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_status_reg = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_error_reg = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Check if queueing commands should be used and switch
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * to appropriate command if possible
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_func_enable & SATA_ENABLE_QUEUING) {
489f952b4388bd1ea1feff97164a4416e0c621eals boolean_t using_queuing;
489f952b4388bd1ea1feff97164a4416e0c621eals
489f952b4388bd1ea1feff97164a4416e0c621eals /* Queuing supported by controller and device? */
489f952b4388bd1ea1feff97164a4416e0c621eals if ((sata_func_enable & SATA_ENABLE_NCQ) &&
489f952b4388bd1ea1feff97164a4416e0c621eals (sdinfo->satadrv_features_support &
489f952b4388bd1ea1feff97164a4416e0c621eals SATA_DEV_F_NCQ) &&
489f952b4388bd1ea1feff97164a4416e0c621eals (SATA_FEATURES(spx->txlt_sata_hba_inst) &
489f952b4388bd1ea1feff97164a4416e0c621eals SATA_CTLF_NCQ)) {
489f952b4388bd1ea1feff97164a4416e0c621eals using_queuing = B_TRUE;
489f952b4388bd1ea1feff97164a4416e0c621eals
489f952b4388bd1ea1feff97164a4416e0c621eals /* NCQ supported - use FPDMA READ */
489f952b4388bd1ea1feff97164a4416e0c621eals scmd->satacmd_cmd_reg =
489f952b4388bd1ea1feff97164a4416e0c621eals SATAC_READ_FPDMA_QUEUED;
489f952b4388bd1ea1feff97164a4416e0c621eals scmd->satacmd_features_reg_ext =
489f952b4388bd1ea1feff97164a4416e0c621eals scmd->satacmd_sec_count_msb;
489f952b4388bd1ea1feff97164a4416e0c621eals scmd->satacmd_sec_count_msb = 0;
489f952b4388bd1ea1feff97164a4416e0c621eals } else if ((sdinfo->satadrv_features_support &
489f952b4388bd1ea1feff97164a4416e0c621eals SATA_DEV_F_TCQ) &&
489f952b4388bd1ea1feff97164a4416e0c621eals (SATA_FEATURES(spx->txlt_sata_hba_inst) &
489f952b4388bd1ea1feff97164a4416e0c621eals SATA_CTLF_QCMD)) {
489f952b4388bd1ea1feff97164a4416e0c621eals using_queuing = B_TRUE;
489f952b4388bd1ea1feff97164a4416e0c621eals
489f952b4388bd1ea1feff97164a4416e0c621eals /* Legacy queueing */
489f952b4388bd1ea1feff97164a4416e0c621eals if (sdinfo->satadrv_features_support &
489f952b4388bd1ea1feff97164a4416e0c621eals SATA_DEV_F_LBA48) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_cmd_reg =
489f952b4388bd1ea1feff97164a4416e0c621eals SATAC_READ_DMA_QUEUED_EXT;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_features_reg_ext =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_sec_count_msb;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_sec_count_msb = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
489f952b4388bd1ea1feff97164a4416e0c621eals scmd->satacmd_cmd_reg =
489f952b4388bd1ea1feff97164a4416e0c621eals SATAC_READ_DMA_QUEUED;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw } else /* NCQ nor legacy queuing not supported */
489f952b4388bd1ea1feff97164a4416e0c621eals using_queuing = B_FALSE;
489f952b4388bd1ea1feff97164a4416e0c621eals
489f952b4388bd1ea1feff97164a4416e0c621eals /*
489f952b4388bd1ea1feff97164a4416e0c621eals * If queuing, the sector count goes in the features register
489f952b4388bd1ea1feff97164a4416e0c621eals * and the secount count will contain the tag.
489f952b4388bd1ea1feff97164a4416e0c621eals */
489f952b4388bd1ea1feff97164a4416e0c621eals if (using_queuing) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_features_reg =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_sec_count_lsb;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_sec_count_lsb = 0;
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_flags.sata_queued = B_TRUE;
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw /* Set-up maximum queue depth */
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw scmd->satacmd_flags.sata_max_queue_depth =
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw sdinfo->satadrv_max_queue_depth - 1;
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw } else if (sdinfo->satadrv_features_enabled &
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw SATA_DEV_F_E_UNTAGGED_QING) {
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw /*
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw * Although NCQ/TCQ is not enabled, untagged queuing
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw * may be still used.
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw * Set-up the maximum untagged queue depth.
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw * Use controller's queue depth from sata_hba_tran.
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw * SATA HBA drivers may ignore this value and rely on
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw * the internal limits.For drivers that do not
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw * ignore untaged queue depth, limit the value to
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw * SATA_MAX_QUEUE_DEPTH (32), as this is the
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw * largest value that can be passed via
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw * satacmd_flags.sata_max_queue_depth.
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw */
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw scmd->satacmd_flags.sata_max_queue_depth =
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw SATA_QDEPTH(shi) <= SATA_MAX_QUEUE_DEPTH ?
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw SATA_QDEPTH(shi) - 1: SATA_MAX_QUEUE_DEPTH - 1;
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw } else {
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw scmd->satacmd_flags.sata_max_queue_depth = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw } else
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw scmd->satacmd_flags.sata_max_queue_depth = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG3(SATA_DBG_HBA_IF, spx->txlt_sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_txlt_read cmd 0x%2x, lba %llx, sec count %x\n",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_cmd_reg, lba, sec_count);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (!(spx->txlt_sata_pkt->satapkt_op_mode & SATA_OPMODE_SYNCH)) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Need callback function */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_sata_pkt->satapkt_comp = sata_txlt_rw_completion;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf synch = FALSE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf synch = TRUE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Transfer command to HBA */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_hba_start(spx, &rval) != 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Pkt not accepted for execution */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&SATA_CPORT_MUTEX(shi, cport));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (rval);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&SATA_CPORT_MUTEX(shi, cport));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * If execution is non-synchronous,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * a callback function will handle potential errors, translate
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * the response and will do a callback to a target driver.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * If it was synchronous, check execution status using the same
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * framework callback.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (synch) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG1(SATA_DBG_SCSI_IF, spx->txlt_sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "synchronous execution status %x\n",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_sata_pkt->satapkt_reason);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_txlt_rw_completion(spx->txlt_sata_pkt);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (TRAN_ACCEPT);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * SATA translate command: Write (various types)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Translated into appropriate type of ATA WRITE command
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * for SATA hard disks.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Both the device capabilities and requested operation mode are
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * considered.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Following scsi cdb fields are ignored:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * rwprotect, dpo, fua, fua_nv, group_number.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw * If SATA_ENABLE_QUEUING flag is set (in the global SATA HBA framework
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw * enable variable sata_func_enable), the capability of the controller and
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw * capability of a device are checked and if both support queueing, write
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw * request will be translated to WRITE_DMA_QUEUEING or WRITE_DMA_QUEUEING_EXT
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw * command rather than plain WRITE_XXX command.
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw * If SATA_ENABLE_NCQ flag is set in addition to SATA_ENABLE_QUEUING flag and
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw * both the controller and device suport such functionality, the write
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw * request will be translated to WRITE_FPDMA_QUEUED command.
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw * In both cases the maximum queue depth is derived as minimum of:
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw * HBA capability,device capability and sata_max_queue_depth variable setting.
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw * The value passed to HBA driver is decremented by 1, because only 5 bits are
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw * used to pass max queue depth value, and the maximum possible queue depth
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw * is 32.
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Returns TRAN_ACCEPT or code returned by sata_hba_start() and
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * appropriate values in scsi_pkt fields.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_txlt_write(sata_pkt_txlate_t *spx)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf struct scsi_pkt *scsipkt = spx->txlt_scsi_pkt;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_cmd_t *scmd = &spx->txlt_sata_pkt->satapkt_cmd;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_drive_info_t *sdinfo;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst_t *shi = SATA_TXLT_HBA_INST(spx);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int cport = SATA_TXLT_CPORT(spx);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf uint16_t sec_count;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf uint64_t lba;
f39c049be37ba5b8f96704f41d6532332ae16318pawelw int rval, reason;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int synch;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&(SATA_TXLT_CPORT_MUTEX(spx)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
f39c049be37ba5b8f96704f41d6532332ae16318pawelw if (((rval = sata_txlt_generic_pkt_info(spx, &reason)) !=
f39c049be37ba5b8f96704f41d6532332ae16318pawelw TRAN_ACCEPT) || (reason == CMD_DEV_GONE)) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&(SATA_TXLT_CPORT_MUTEX(spx)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (rval);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo = sata_get_device_info(spx->txlt_sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf &spx->txlt_sata_pkt->satapkt_device);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_flags.sata_data_direction = SATA_DIR_WRITE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
4360436b3c604bc28d37be269ad152b4c38157c3pawelw * Extract LBA and sector count from scsi CDB
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf switch ((uint_t)scsipkt->pkt_cdbp[0]) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SCMD_WRITE:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* 6-byte scsi read cmd : 0x0A */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf lba = (scsipkt->pkt_cdbp[1] & 0x1f);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf lba = (lba << 8) | scsipkt->pkt_cdbp[2];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf lba = (lba << 8) | scsipkt->pkt_cdbp[3];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sec_count = scsipkt->pkt_cdbp[4];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* sec_count 0 will be interpreted as 256 by a device */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SCMD_WRITE_G1:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* 10-bytes scsi write command : 0x2A */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf lba = scsipkt->pkt_cdbp[2];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf lba = (lba << 8) | scsipkt->pkt_cdbp[3];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf lba = (lba << 8) | scsipkt->pkt_cdbp[4];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf lba = (lba << 8) | scsipkt->pkt_cdbp[5];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sec_count = scsipkt->pkt_cdbp[7];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sec_count = (sec_count << 8) | scsipkt->pkt_cdbp[8];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SCMD_WRITE_G5:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* 12-bytes scsi read command : 0xAA */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf lba = scsipkt->pkt_cdbp[2];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf lba = (lba << 8) | scsipkt->pkt_cdbp[3];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf lba = (lba << 8) | scsipkt->pkt_cdbp[4];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf lba = (lba << 8) | scsipkt->pkt_cdbp[5];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sec_count = scsipkt->pkt_cdbp[6];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sec_count = (sec_count << 8) | scsipkt->pkt_cdbp[7];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sec_count = (sec_count << 8) | scsipkt->pkt_cdbp[8];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sec_count = (sec_count << 8) | scsipkt->pkt_cdbp[9];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SCMD_WRITE_G4:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* 16-bytes scsi write command : 0x8A */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf lba = scsipkt->pkt_cdbp[2];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf lba = (lba << 8) | scsipkt->pkt_cdbp[3];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf lba = (lba << 8) | scsipkt->pkt_cdbp[4];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf lba = (lba << 8) | scsipkt->pkt_cdbp[5];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf lba = (lba << 8) | scsipkt->pkt_cdbp[6];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf lba = (lba << 8) | scsipkt->pkt_cdbp[7];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf lba = (lba << 8) | scsipkt->pkt_cdbp[8];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf lba = (lba << 8) | scsipkt->pkt_cdbp[9];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sec_count = scsipkt->pkt_cdbp[10];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sec_count = (sec_count << 8) | scsipkt->pkt_cdbp[11];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sec_count = (sec_count << 8) | scsipkt->pkt_cdbp[12];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sec_count = (sec_count << 8) | scsipkt->pkt_cdbp[13];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf default:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Unsupported command */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&(SATA_TXLT_CPORT_MUTEX(spx)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (sata_txlt_invalid_command(spx));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Check if specified address and length exceeds device capacity
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((lba >= sdinfo->satadrv_capacity) ||
4e1e976ddd007cda18e3ce61b2d9ff587a5fd4e7pawelw ((lba + sec_count) > sdinfo->satadrv_capacity)) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* LBA out of range */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&(SATA_TXLT_CPORT_MUTEX(spx)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (sata_txlt_lba_out_of_range(spx));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
4360436b3c604bc28d37be269ad152b4c38157c3pawelw /*
4360436b3c604bc28d37be269ad152b4c38157c3pawelw * For zero-length transfer, emulate good completion of the command
4360436b3c604bc28d37be269ad152b4c38157c3pawelw * (reasons for rejecting the command were already checked).
4360436b3c604bc28d37be269ad152b4c38157c3pawelw * No DMA resources were allocated.
4360436b3c604bc28d37be269ad152b4c38157c3pawelw */
4360436b3c604bc28d37be269ad152b4c38157c3pawelw if (spx->txlt_dma_cookie_list == NULL) {
4360436b3c604bc28d37be269ad152b4c38157c3pawelw mutex_exit(&(SATA_TXLT_CPORT_MUTEX(spx)));
4360436b3c604bc28d37be269ad152b4c38157c3pawelw return (sata_emul_rw_completion(spx));
4360436b3c604bc28d37be269ad152b4c38157c3pawelw }
4360436b3c604bc28d37be269ad152b4c38157c3pawelw
4360436b3c604bc28d37be269ad152b4c38157c3pawelw /*
4360436b3c604bc28d37be269ad152b4c38157c3pawelw * Build cmd block depending on the device capability and
4360436b3c604bc28d37be269ad152b4c38157c3pawelw * requested operation mode.
4360436b3c604bc28d37be269ad152b4c38157c3pawelw * Do not bother with non-dma mode- we are working only with
4360436b3c604bc28d37be269ad152b4c38157c3pawelw * devices supporting DMA.
4360436b3c604bc28d37be269ad152b4c38157c3pawelw */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_addr_type = ATA_ADDR_LBA;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_device_reg = SATA_ADH_LBA;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_cmd_reg = SATAC_WRITE_DMA;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sdinfo->satadrv_features_support & SATA_DEV_F_LBA48) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_addr_type = ATA_ADDR_LBA48;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_cmd_reg = SATAC_WRITE_DMA_EXT;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_sec_count_msb = sec_count >> 8;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_lba_low_msb = (lba >> 24) & 0xff;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#ifndef __lock_lint
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_lba_mid_msb = (lba >> 32) & 0xff;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_lba_high_msb = lba >> 40;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#endif
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else if (sdinfo->satadrv_features_support & SATA_DEV_F_LBA28) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_addr_type = ATA_ADDR_LBA28;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_device_reg = SATA_ADH_LBA | ((lba >> 24) & 0xf);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_sec_count_lsb = sec_count & 0xff;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_lba_low_lsb = lba & 0xff;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_lba_mid_lsb = (lba >> 8) & 0xff;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_lba_high_lsb = (lba >> 16) & 0xff;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_features_reg = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_status_reg = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_error_reg = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Check if queueing commands should be used and switch
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * to appropriate command if possible
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_func_enable & SATA_ENABLE_QUEUING) {
489f952b4388bd1ea1feff97164a4416e0c621eals boolean_t using_queuing;
489f952b4388bd1ea1feff97164a4416e0c621eals
489f952b4388bd1ea1feff97164a4416e0c621eals /* Queuing supported by controller and device? */
489f952b4388bd1ea1feff97164a4416e0c621eals if ((sata_func_enable & SATA_ENABLE_NCQ) &&
489f952b4388bd1ea1feff97164a4416e0c621eals (sdinfo->satadrv_features_support &
489f952b4388bd1ea1feff97164a4416e0c621eals SATA_DEV_F_NCQ) &&
489f952b4388bd1ea1feff97164a4416e0c621eals (SATA_FEATURES(spx->txlt_sata_hba_inst) &
489f952b4388bd1ea1feff97164a4416e0c621eals SATA_CTLF_NCQ)) {
489f952b4388bd1ea1feff97164a4416e0c621eals using_queuing = B_TRUE;
489f952b4388bd1ea1feff97164a4416e0c621eals
489f952b4388bd1ea1feff97164a4416e0c621eals /* NCQ supported - use FPDMA WRITE */
489f952b4388bd1ea1feff97164a4416e0c621eals scmd->satacmd_cmd_reg =
489f952b4388bd1ea1feff97164a4416e0c621eals SATAC_WRITE_FPDMA_QUEUED;
489f952b4388bd1ea1feff97164a4416e0c621eals scmd->satacmd_features_reg_ext =
489f952b4388bd1ea1feff97164a4416e0c621eals scmd->satacmd_sec_count_msb;
489f952b4388bd1ea1feff97164a4416e0c621eals scmd->satacmd_sec_count_msb = 0;
489f952b4388bd1ea1feff97164a4416e0c621eals } else if ((sdinfo->satadrv_features_support &
489f952b4388bd1ea1feff97164a4416e0c621eals SATA_DEV_F_TCQ) &&
489f952b4388bd1ea1feff97164a4416e0c621eals (SATA_FEATURES(spx->txlt_sata_hba_inst) &
489f952b4388bd1ea1feff97164a4416e0c621eals SATA_CTLF_QCMD)) {
489f952b4388bd1ea1feff97164a4416e0c621eals using_queuing = B_TRUE;
489f952b4388bd1ea1feff97164a4416e0c621eals
489f952b4388bd1ea1feff97164a4416e0c621eals /* Legacy queueing */
489f952b4388bd1ea1feff97164a4416e0c621eals if (sdinfo->satadrv_features_support &
489f952b4388bd1ea1feff97164a4416e0c621eals SATA_DEV_F_LBA48) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_cmd_reg =
489f952b4388bd1ea1feff97164a4416e0c621eals SATAC_WRITE_DMA_QUEUED_EXT;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_features_reg_ext =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_sec_count_msb;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_sec_count_msb = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
489f952b4388bd1ea1feff97164a4416e0c621eals scmd->satacmd_cmd_reg =
489f952b4388bd1ea1feff97164a4416e0c621eals SATAC_WRITE_DMA_QUEUED;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw } else /* NCQ nor legacy queuing not supported */
489f952b4388bd1ea1feff97164a4416e0c621eals using_queuing = B_FALSE;
489f952b4388bd1ea1feff97164a4416e0c621eals
489f952b4388bd1ea1feff97164a4416e0c621eals if (using_queuing) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_features_reg =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_sec_count_lsb;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_sec_count_lsb = 0;
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_flags.sata_queued = B_TRUE;
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw /* Set-up maximum queue depth */
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw scmd->satacmd_flags.sata_max_queue_depth =
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw sdinfo->satadrv_max_queue_depth - 1;
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw } else if (sdinfo->satadrv_features_enabled &
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw SATA_DEV_F_E_UNTAGGED_QING) {
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw /*
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw * Although NCQ/TCQ is not enabled, untagged queuing
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw * may be still used.
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw * Set-up the maximum untagged queue depth.
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw * Use controller's queue depth from sata_hba_tran.
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw * SATA HBA drivers may ignore this value and rely on
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw * the internal limits. For drivera that do not
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw * ignore untaged queue depth, limit the value to
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw * SATA_MAX_QUEUE_DEPTH (32), as this is the
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw * largest value that can be passed via
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw * satacmd_flags.sata_max_queue_depth.
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw */
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw scmd->satacmd_flags.sata_max_queue_depth =
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw SATA_QDEPTH(shi) <= SATA_MAX_QUEUE_DEPTH ?
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw SATA_QDEPTH(shi) - 1: SATA_MAX_QUEUE_DEPTH - 1;
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw } else {
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw scmd->satacmd_flags.sata_max_queue_depth = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw } else
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw scmd->satacmd_flags.sata_max_queue_depth = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG3(SATA_DBG_SCSI_IF, spx->txlt_sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_txlt_write cmd 0x%2x, lba %llx, sec count %x\n",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_cmd_reg, lba, sec_count);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (!(spx->txlt_sata_pkt->satapkt_op_mode & SATA_OPMODE_SYNCH)) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Need callback function */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_sata_pkt->satapkt_comp = sata_txlt_rw_completion;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf synch = FALSE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf synch = TRUE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Transfer command to HBA */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_hba_start(spx, &rval) != 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Pkt not accepted for execution */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&SATA_CPORT_MUTEX(shi, cport));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (rval);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&SATA_CPORT_MUTEX(shi, cport));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * If execution is non-synchronous,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * a callback function will handle potential errors, translate
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * the response and will do a callback to a target driver.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * If it was synchronous, check execution status using the same
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * framework callback.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (synch) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG1(SATA_DBG_SCSI_IF, spx->txlt_sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "synchronous execution status %x\n",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_sata_pkt->satapkt_reason);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_txlt_rw_completion(spx->txlt_sata_pkt);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (TRAN_ACCEPT);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls/*
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls * Implements SCSI SBC WRITE BUFFER command download microcode option
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls */
a022fe3e0bc959fae460b8b5b818cd1265bf4c66lsstatic int
a022fe3e0bc959fae460b8b5b818cd1265bf4c66lssata_txlt_write_buffer(sata_pkt_txlate_t *spx)
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls{
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls#define WB_DOWNLOAD_MICROCODE_AND_REVERT_MODE 4
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls#define WB_DOWNLOAD_MICROCODE_AND_SAVE_MODE 5
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz sata_hba_inst_t *sata_hba_inst = SATA_TXLT_HBA_INST(spx);
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls struct scsi_pkt *scsipkt = spx->txlt_scsi_pkt;
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz struct sata_pkt *sata_pkt = spx->txlt_sata_pkt;
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls sata_cmd_t *scmd = &spx->txlt_sata_pkt->satapkt_cmd;
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls struct buf *bp = spx->txlt_sata_pkt->satapkt_cmd.satacmd_bp;
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls struct scsi_extended_sense *sense;
f39c049be37ba5b8f96704f41d6532332ae16318pawelw int rval, mode, sector_count, reason;
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls int cport = SATA_TXLT_CPORT(spx);
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls mode = scsipkt->pkt_cdbp[1] & 0x1f;
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls SATADBG1(SATA_DBG_SCSI_IF, spx->txlt_sata_hba_inst,
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls "sata_txlt_write_buffer, mode 0x%x\n", mode);
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls mutex_enter(&(SATA_TXLT_CPORT_MUTEX(spx)));
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls
f39c049be37ba5b8f96704f41d6532332ae16318pawelw if ((rval = sata_txlt_generic_pkt_info(spx, &reason)) != TRAN_ACCEPT) {
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls mutex_exit(&(SATA_TXLT_CPORT_MUTEX(spx)));
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls return (rval);
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls }
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik /*
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik * If in interrupt context, reject this packet because it would issue
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik * a synchronous command to HBA.
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik */
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik if (servicing_interrupt()) {
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik SATADBG1(SATA_DBG_INTR_CTX, spx->txlt_sata_hba_inst,
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik "sata_txlt_write_buffer: rejecting command because "
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik "of interrupt context\n", NULL);
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik mutex_exit(&(SATA_TXLT_CPORT_MUTEX(spx)));
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik return (TRAN_BUSY);
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik }
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz /* Use synchronous mode */
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz spx->txlt_sata_pkt->satapkt_op_mode
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz |= SATA_OPMODE_SYNCH | SATA_OPMODE_INTERRUPTS;
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls scmd->satacmd_flags.sata_data_direction = SATA_DIR_WRITE;
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls scsipkt->pkt_reason = CMD_CMPLT;
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls scsipkt->pkt_state = STATE_GOT_BUS | STATE_GOT_TARGET |
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls STATE_SENT_CMD | STATE_GOT_STATUS;
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls /*
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls * The SCSI to ATA translation specification only calls
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls * for WB_DOWNLOAD_MICROCODE_AND_SAVE_MODE.
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls * WB_DOWNLOAD_MICROC_AND_REVERT_MODE is implemented, but
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls * ATA 8 (draft) got rid of download microcode for temp
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls * and it is even optional for ATA 7, so it may be aborted.
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls * WB_DOWNLOAD_MICROCODE_WITH_OFFSET is not implemented as
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls * it is not specified and the buffer offset for SCSI is a 16-bit
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls * value in bytes, but for ATA it is a 16-bit offset in 512 byte
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls * sectors. Thus the offset really doesn't buy us anything.
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls * If and when ATA 8 is stabilized and the SCSI to ATA specification
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls * is revised, this can be revisisted.
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls */
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls /* Reject not supported request */
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls switch (mode) {
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls case WB_DOWNLOAD_MICROCODE_AND_REVERT_MODE:
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls scmd->satacmd_features_reg = SATA_DOWNLOAD_MCODE_TEMP;
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls break;
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls case WB_DOWNLOAD_MICROCODE_AND_SAVE_MODE:
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls scmd->satacmd_features_reg = SATA_DOWNLOAD_MCODE_SAVE;
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls break;
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls default:
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls goto bad_param;
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls }
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls *scsipkt->pkt_scbp = STATUS_GOOD; /* Presumed outcome */
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls scmd->satacmd_cmd_reg = SATAC_DOWNLOAD_MICROCODE;
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls if ((bp->b_bcount % SATA_DISK_SECTOR_SIZE) != 0)
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls goto bad_param;
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls sector_count = bp->b_bcount / SATA_DISK_SECTOR_SIZE;
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls scmd->satacmd_sec_count_lsb = (uint8_t)sector_count;
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls scmd->satacmd_lba_low_lsb = ((uint16_t)sector_count) >> 8;
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls scmd->satacmd_lba_mid_lsb = 0;
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls scmd->satacmd_lba_high_lsb = 0;
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls scmd->satacmd_device_reg = 0;
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz spx->txlt_sata_pkt->satapkt_comp = NULL;
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls scmd->satacmd_addr_type = 0;
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls /* Transfer command to HBA */
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls if (sata_hba_start(spx, &rval) != 0) {
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls /* Pkt not accepted for execution */
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz mutex_exit(&SATA_CPORT_MUTEX(sata_hba_inst, cport));
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls return (rval);
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls }
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz mutex_exit(&SATA_CPORT_MUTEX(sata_hba_inst, cport));
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz /* Then we need synchronous check the status of the disk */
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz scsipkt->pkt_state = STATE_GOT_BUS | STATE_GOT_TARGET |
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz STATE_SENT_CMD | STATE_XFERRED_DATA | STATE_GOT_STATUS;
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz if (sata_pkt->satapkt_reason == SATA_PKT_COMPLETED) {
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz scsipkt->pkt_reason = CMD_CMPLT;
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz /* Download commmand succeed, so probe and identify device */
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz sata_reidentify_device(spx);
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz } else {
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz /* Something went wrong, microcode download command failed */
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz scsipkt->pkt_reason = CMD_INCOMPLETE;
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz *scsipkt->pkt_scbp = STATUS_CHECK;
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz sense = sata_arq_sense(spx);
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz switch (sata_pkt->satapkt_reason) {
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz case SATA_PKT_PORT_ERROR:
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz /*
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz * We have no device data. Assume no data transfered.
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz */
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz sense->es_key = KEY_HARDWARE_ERROR;
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz break;
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz case SATA_PKT_DEV_ERROR:
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz if (sata_pkt->satapkt_cmd.satacmd_status_reg &
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz SATA_STATUS_ERR) {
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz /*
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz * determine dev error reason from error
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz * reg content
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz */
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz sata_decode_device_error(spx, sense);
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz break;
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz }
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz /* No extended sense key - no info available */
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz break;
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz case SATA_PKT_TIMEOUT:
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz scsipkt->pkt_reason = CMD_TIMEOUT;
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz scsipkt->pkt_statistics |=
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz STAT_TIMEOUT | STAT_DEV_RESET;
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz /* No extended sense key ? */
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz break;
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz case SATA_PKT_ABORTED:
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz scsipkt->pkt_reason = CMD_ABORTED;
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz scsipkt->pkt_statistics |= STAT_ABORTED;
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz /* No extended sense key ? */
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz break;
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz case SATA_PKT_RESET:
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz /* pkt aborted by an explicit reset from a host */
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz scsipkt->pkt_reason = CMD_RESET;
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz scsipkt->pkt_statistics |= STAT_DEV_RESET;
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz break;
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz default:
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz SATA_LOG_D((spx->txlt_sata_hba_inst, CE_WARN,
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz "sata_txlt_nodata_cmd_completion: "
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz "invalid packet completion reason %d",
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz sata_pkt->satapkt_reason));
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz scsipkt->pkt_reason = CMD_TRAN_ERR;
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz break;
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz }
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls SATADBG1(SATA_DBG_SCSI_IF, spx->txlt_sata_hba_inst,
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz "scsi_pkt completion reason %x\n", scsipkt->pkt_reason);
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz
9c57abc8d70cb139020be846baec0a9c4d9a73cdsrivijitha dugganapalli if ((scsipkt->pkt_flags & FLAG_NOINTR) == 0)
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz /* scsi callback required */
9c57abc8d70cb139020be846baec0a9c4d9a73cdsrivijitha dugganapalli scsi_hba_pkt_comp(scsipkt);
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls }
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls return (TRAN_ACCEPT);
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls
a022fe3e0bc959fae460b8b5b818cd1265bf4c66lsbad_param:
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls mutex_exit(&(SATA_TXLT_CPORT_MUTEX(spx)));
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls *scsipkt->pkt_scbp = STATUS_CHECK;
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls sense = sata_arq_sense(spx);
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls sense->es_key = KEY_ILLEGAL_REQUEST;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sense->es_add_code = SD_SCSI_ASC_INVALID_FIELD_IN_CDB;
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls if ((scsipkt->pkt_flags & FLAG_NOINTR) == 0 &&
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls scsipkt->pkt_comp != NULL) {
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls /* scsi callback required */
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls if (taskq_dispatch(SATA_TXLT_TASKQ(spx),
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls (task_func_t *)scsipkt->pkt_comp, (void *) scsipkt,
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls TQ_SLEEP) == 0) {
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls /* Scheduling the callback failed */
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls rval = TRAN_BUSY;
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls }
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls }
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls return (rval);
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls}
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls/*
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xz * Re-identify device after doing a firmware download.
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls */
a022fe3e0bc959fae460b8b5b818cd1265bf4c66lsstatic void
94cf82d0ee8fe71ca5efd060d6241bf36e66fee7xzsata_reidentify_device(sata_pkt_txlate_t *spx)
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls{
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls#define DOWNLOAD_WAIT_TIME_SECS 60
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls#define DOWNLOAD_WAIT_INTERVAL_SECS 1
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls int rval;
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls int retry_cnt;
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls struct scsi_pkt *scsipkt = spx->txlt_scsi_pkt;
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls sata_hba_inst_t *sata_hba_inst = spx->txlt_sata_hba_inst;
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls sata_device_t sata_device = spx->txlt_sata_pkt->satapkt_device;
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls sata_drive_info_t *sdinfo;
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls /*
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls * Before returning good status, probe device.
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls * Device probing will get IDENTIFY DEVICE data, if possible.
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls * The assumption is that the new microcode is applied by the
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls * device. It is a caller responsibility to verify this.
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls */
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls for (retry_cnt = 0;
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls retry_cnt < DOWNLOAD_WAIT_TIME_SECS / DOWNLOAD_WAIT_INTERVAL_SECS;
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls retry_cnt++) {
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls rval = sata_probe_device(sata_hba_inst, &sata_device);
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls if (rval == SATA_SUCCESS) { /* Set default features */
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls sdinfo = sata_get_device_info(sata_hba_inst,
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls &sata_device);
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls if (sata_initialize_device(sata_hba_inst, sdinfo) !=
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls SATA_SUCCESS) {
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls /* retry */
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik rval = sata_initialize_device(sata_hba_inst,
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls sdinfo);
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik if (rval == SATA_RETRY)
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik sata_log(sata_hba_inst, CE_WARN,
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik "SATA device at port %d pmport %d -"
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik " default device features could not"
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik " be set. Device may not operate "
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik "as expected.",
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik sata_device.satadev_addr.cport,
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik sata_device.satadev_addr.pmport);
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls }
9c57abc8d70cb139020be846baec0a9c4d9a73cdsrivijitha dugganapalli if ((scsipkt->pkt_flags & FLAG_NOINTR) == 0)
9c57abc8d70cb139020be846baec0a9c4d9a73cdsrivijitha dugganapalli scsi_hba_pkt_comp(scsipkt);
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls return;
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls } else if (rval == SATA_RETRY) {
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls delay(drv_usectohz(1000000 *
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls DOWNLOAD_WAIT_INTERVAL_SECS));
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls continue;
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls } else /* failed - no reason to retry */
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls break;
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls }
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls /*
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls * Something went wrong, device probing failed.
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls */
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls SATA_LOG_D((sata_hba_inst, CE_WARN,
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls "Cannot probe device after downloading microcode\n"));
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls /* Reset device to force retrying the probe. */
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls (void) (*SATA_RESET_DPORT_FUNC(sata_hba_inst))
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls (SATA_DIP(sata_hba_inst), &sata_device);
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls
9c57abc8d70cb139020be846baec0a9c4d9a73cdsrivijitha dugganapalli if ((scsipkt->pkt_flags & FLAG_NOINTR) == 0)
9c57abc8d70cb139020be846baec0a9c4d9a73cdsrivijitha dugganapalli scsi_hba_pkt_comp(scsipkt);
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls}
a022fe3e0bc959fae460b8b5b818cd1265bf4c66ls
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Translate command: Synchronize Cache.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Translates into Flush Cache command for SATA hard disks.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown *
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Returns TRAN_ACCEPT or code returned by sata_hba_start() and
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * appropriate values in scsi_pkt fields.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic int
2038334ab26baaa43c9083f35def041511c3cc1fUnknownsata_txlt_synchronize_cache(sata_pkt_txlate_t *spx)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_cmd_t *scmd = &spx->txlt_sata_pkt->satapkt_cmd;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst_t *shi = SATA_TXLT_HBA_INST(spx);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int cport = SATA_TXLT_CPORT(spx);
f39c049be37ba5b8f96704f41d6532332ae16318pawelw int rval, reason;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int synch;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&(SATA_TXLT_CPORT_MUTEX(spx)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
f39c049be37ba5b8f96704f41d6532332ae16318pawelw if (((rval = sata_txlt_generic_pkt_info(spx, &reason)) !=
f39c049be37ba5b8f96704f41d6532332ae16318pawelw TRAN_ACCEPT) || (reason == CMD_DEV_GONE)) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&(SATA_TXLT_CPORT_MUTEX(spx)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (rval);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_addr_type = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_cmd_reg = SATAC_FLUSH_CACHE;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_device_reg = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_sec_count_lsb = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_lba_low_lsb = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_lba_mid_lsb = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_lba_high_lsb = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_features_reg = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_status_reg = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_error_reg = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATADBG1(SATA_DBG_SCSI_IF, spx->txlt_sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "sata_txlt_synchronize_cache\n", NULL);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (!(spx->txlt_sata_pkt->satapkt_op_mode & SATA_OPMODE_SYNCH)) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Need to set-up a callback function */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_sata_pkt->satapkt_comp =
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_txlt_nodata_cmd_completion;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown synch = FALSE;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown } else
2038334ab26baaa43c9083f35def041511c3cc1fUnknown synch = TRUE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Transfer command to HBA */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sata_hba_start(spx, &rval) != 0) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Pkt not accepted for execution */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&SATA_CPORT_MUTEX(shi, cport));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (rval);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&SATA_CPORT_MUTEX(shi, cport));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * If execution non-synchronous, it had to be completed
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * a callback function will handle potential errors, translate
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * the response and will do a callback to a target driver.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * If it was synchronous, check status, using the same
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * framework callback.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (synch) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG1(SATA_DBG_SCSI_IF, spx->txlt_sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "synchronous execution status %x\n",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_sata_pkt->satapkt_reason);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_txlt_nodata_cmd_completion(spx->txlt_sata_pkt);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (TRAN_ACCEPT);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Send pkt to SATA HBA driver
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * This function may be called only if the operation is requested by scsi_pkt,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * i.e. scsi_pkt is not NULL.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * This function has to be called with cport mutex held. It does release
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * the mutex when it calls HBA driver sata_tran_start function and
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * re-acquires it afterwards.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * If return value is 0, pkt was accepted, -1 otherwise
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * rval is set to appropriate sata_scsi_start return value.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Note 1:If HBA driver returns value other than TRAN_ACCEPT, it should not
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * have called the sata_pkt callback function for this packet.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * The scsi callback has to be performed by the caller of this routine.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_hba_start(sata_pkt_txlate_t *spx, int *rval)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang int stat;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang uint8_t cport = SATA_TXLT_CPORT(spx);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang uint8_t pmport = SATA_TXLT_PMPORT(spx);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst_t *sata_hba_inst = spx->txlt_sata_hba_inst;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_drive_info_t *sdinfo;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_pmult_info_t *pminfo;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_pmport_info_t *pmportinfo = NULL;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device_t *sata_device = NULL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf uint8_t cmd;
c03acfcad7780db4ddf763511a82026680b3b2c1ls struct sata_cmd_flags cmd_flags;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ASSERT(spx->txlt_sata_pkt != NULL);
415e5120fdbacf132d1845300d92a6cd74eed2fayt
415e5120fdbacf132d1845300d92a6cd74eed2fayt ASSERT(mutex_owned(&SATA_CPORT_MUTEX(sata_hba_inst, cport)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo = sata_get_device_info(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf &spx->txlt_sata_pkt->satapkt_device);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ASSERT(sdinfo != NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Clear device reset state? */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* qual should be XXX_DPMPORT, but add XXX_PMPORT in case */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (sdinfo->satadrv_addr.qual == SATA_ADDR_DPMPORT ||
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sdinfo->satadrv_addr.qual == SATA_ADDR_PMPORT) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Get the pmult_info of the its parent port multiplier, all
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * sub-devices share a common device reset flags on in
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * pmult_info.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pminfo = SATA_PMULT_INFO(sata_hba_inst, cport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo = pminfo->pmult_dev_port[pmport];
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang ASSERT(pminfo != NULL);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (pminfo->pmult_event_flags & SATA_EVNT_CLEAR_DEVICE_RESET) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang spx->txlt_sata_pkt->satapkt_cmd.satacmd_flags.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_clear_dev_reset = B_TRUE;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pminfo->pmult_event_flags &=
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang ~SATA_EVNT_CLEAR_DEVICE_RESET;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATADBG1(SATA_DBG_EVENTS, sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "sata_hba_start: clearing device reset state"
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "on pmult.\n", NULL);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang } else {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (sdinfo->satadrv_event_flags &
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_EVNT_CLEAR_DEVICE_RESET) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang spx->txlt_sata_pkt->satapkt_cmd.satacmd_flags.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_clear_dev_reset = B_TRUE;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sdinfo->satadrv_event_flags &=
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang ~SATA_EVNT_CLEAR_DEVICE_RESET;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATADBG1(SATA_DBG_EVENTS, sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "sata_hba_start: clearing device reset state\n",
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang NULL);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cmd = spx->txlt_sata_pkt->satapkt_cmd.satacmd_cmd_reg;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cmd_flags = spx->txlt_sata_pkt->satapkt_cmd.satacmd_flags;
6ed1276fb5fe78fb1cce38682748a830ef8bd157pawelw sata_device = &spx->txlt_sata_pkt->satapkt_device;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
415e5120fdbacf132d1845300d92a6cd74eed2fayt mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst, cport)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG1(SATA_DBG_SCSI_IF, spx->txlt_sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "Sata cmd 0x%2x\n", cmd);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf stat = (*SATA_START_FUNC(sata_hba_inst))(SATA_DIP(sata_hba_inst),
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_sata_pkt);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
415e5120fdbacf132d1845300d92a6cd74eed2fayt mutex_enter(&(SATA_CPORT_MUTEX(sata_hba_inst, cport)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * If sata pkt was accepted and executed in asynchronous mode, i.e.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * with the sata callback, the sata_pkt could be already destroyed
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * by the time we check ther return status from the hba_start()
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * function, because sata_scsi_destroy_pkt() could have been already
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * called (perhaps in the interrupt context). So, in such case, there
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * should be no references to it. In other cases, sata_pkt still
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * exists.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
6a2bb0c23e183d064817bc0ab8bff3b8c346c967pawelw if (stat == SATA_TRAN_ACCEPTED) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * pkt accepted for execution.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * If it was executed synchronously, it is already completed
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * and pkt completion_reason indicates completion status.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *rval = TRAN_ACCEPT;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (0);
6a2bb0c23e183d064817bc0ab8bff3b8c346c967pawelw }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
6a2bb0c23e183d064817bc0ab8bff3b8c346c967pawelw sdinfo = sata_get_device_info(sata_hba_inst, sata_device);
6a2bb0c23e183d064817bc0ab8bff3b8c346c967pawelw switch (stat) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SATA_TRAN_QUEUE_FULL:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Controller detected queue full condition.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG1(SATA_DBG_HBA_IF, sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_hba_start: queue full\n", NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_scsi_pkt->pkt_reason = CMD_INCOMPLETE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *spx->txlt_scsi_pkt->pkt_scbp = STATUS_QFULL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *rval = TRAN_BUSY;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SATA_TRAN_PORT_ERROR:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Communication/link with device or general port error
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * detected before pkt execution begun.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (spx->txlt_sata_pkt->satapkt_device.satadev_addr.qual ==
6ed1276fb5fe78fb1cce38682748a830ef8bd157pawelw SATA_ADDR_CPORT ||
6ed1276fb5fe78fb1cce38682748a830ef8bd157pawelw spx->txlt_sata_pkt->satapkt_device.satadev_addr.qual ==
6ed1276fb5fe78fb1cce38682748a830ef8bd157pawelw SATA_ADDR_DCPORT)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_log(sata_hba_inst, CE_CONT,
4360436b3c604bc28d37be269ad152b4c38157c3pawelw "SATA port %d error",
6ed1276fb5fe78fb1cce38682748a830ef8bd157pawelw sata_device->satadev_addr.cport);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf else
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_log(sata_hba_inst, CE_CONT,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "SATA port %d:%d error\n",
6ed1276fb5fe78fb1cce38682748a830ef8bd157pawelw sata_device->satadev_addr.cport,
6ed1276fb5fe78fb1cce38682748a830ef8bd157pawelw sata_device->satadev_addr.pmport);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Update the port/device structure.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * sata_pkt should be still valid. Since port error is
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * returned, sata_device content should reflect port
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * state - it means, that sata address have been changed,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * because original packet's sata address refered to a device
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * attached to some port.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (sdinfo->satadrv_addr.qual == SATA_ADDR_DPMPORT ||
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sdinfo->satadrv_addr.qual == SATA_ADDR_PMPORT) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst, cport)));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_update_pmport_info(sata_hba_inst, sata_device);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&(SATA_CPORT_MUTEX(sata_hba_inst, cport)));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang } else {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_update_port_info(sata_hba_inst, sata_device);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_scsi_pkt->pkt_reason = CMD_TRAN_ERR;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *rval = TRAN_FATAL_ERROR;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SATA_TRAN_CMD_UNSUPPORTED:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Command rejected by HBA as unsupported. It was HBA driver
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * that rejected the command, command was not sent to
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * an attached device.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
415e5120fdbacf132d1845300d92a6cd74eed2fayt if ((sdinfo != NULL) &&
415e5120fdbacf132d1845300d92a6cd74eed2fayt (sdinfo->satadrv_state & SATA_DSTATE_RESET))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG1(SATA_DBG_EVENTS, sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sat_hba_start: cmd 0x%2x rejected "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "with SATA_TRAN_CMD_UNSUPPORTED status\n", cmd);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
415e5120fdbacf132d1845300d92a6cd74eed2fayt mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst, cport)));
415e5120fdbacf132d1845300d92a6cd74eed2fayt (void) sata_txlt_invalid_command(spx);
415e5120fdbacf132d1845300d92a6cd74eed2fayt mutex_enter(&(SATA_CPORT_MUTEX(sata_hba_inst, cport)));
415e5120fdbacf132d1845300d92a6cd74eed2fayt
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *rval = TRAN_ACCEPT;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SATA_TRAN_BUSY:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Command rejected by HBA because other operation prevents
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * accepting the packet, or device is in RESET condition.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sdinfo != NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_state =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_sata_pkt->satapkt_device.satadev_state;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sdinfo->satadrv_state & SATA_DSTATE_RESET) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG1(SATA_DBG_EVENTS, sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_hba_start: cmd 0x%2x rejected "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "because of device reset condition\n",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cmd);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG1(SATA_DBG_EVENTS, sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_hba_start: cmd 0x%2x rejected "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "with SATA_TRAN_BUSY status\n",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cmd);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_scsi_pkt->pkt_reason = CMD_INCOMPLETE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *rval = TRAN_BUSY;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf default:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Unrecognized HBA response */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_LOG_D((sata_hba_inst, CE_WARN,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_hba_start: unrecognized HBA response "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "to cmd : 0x%2x resp 0x%x", cmd, rval));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_scsi_pkt->pkt_reason = CMD_TRAN_ERR;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *rval = TRAN_FATAL_ERROR;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * If we got here, the packet was rejected.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Check if we need to remember reset state clearing request
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
c03acfcad7780db4ddf763511a82026680b3b2c1ls if (cmd_flags.sata_clear_dev_reset) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Check if device is still configured - it may have
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * disapeared from the configuration
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
6ed1276fb5fe78fb1cce38682748a830ef8bd157pawelw sdinfo = sata_get_device_info(sata_hba_inst, sata_device);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sdinfo != NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Restore the flag that requests clearing of
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * the device reset state,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * so the next sata packet may carry it to HBA.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (sdinfo->satadrv_addr.qual == SATA_ADDR_PMPORT ||
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sdinfo->satadrv_addr.qual == SATA_ADDR_DPMPORT) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pminfo->pmult_event_flags |=
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_EVNT_CLEAR_DEVICE_RESET;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang } else {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sdinfo->satadrv_event_flags |=
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_EVNT_CLEAR_DEVICE_RESET;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (-1);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Scsi response setup for invalid LBA
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Returns TRAN_ACCEPT and appropriate values in scsi_pkt fields.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_txlt_lba_out_of_range(sata_pkt_txlate_t *spx)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf struct scsi_pkt *scsipkt = spx->txlt_scsi_pkt;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf struct scsi_extended_sense *sense;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsipkt->pkt_reason = CMD_CMPLT;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsipkt->pkt_state = STATE_GOT_BUS | STATE_GOT_TARGET |
184cd04c26b064536977dfbb913a1240eaf6f708cth STATE_SENT_CMD | STATE_GOT_STATUS;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *scsipkt->pkt_scbp = STATUS_CHECK;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *scsipkt->pkt_scbp = STATUS_CHECK;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense = sata_arq_sense(spx);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense->es_key = KEY_ILLEGAL_REQUEST;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sense->es_add_code = SD_SCSI_ASC_LBA_OUT_OF_RANGE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG1(SATA_DBG_SCSI_IF, spx->txlt_sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "Scsi_pkt completion reason %x\n", scsipkt->pkt_reason);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((scsipkt->pkt_flags & FLAG_NOINTR) == 0 &&
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsipkt->pkt_comp != NULL)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* scsi callback required */
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw if (taskq_dispatch(SATA_TXLT_TASKQ(spx),
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw (task_func_t *)scsipkt->pkt_comp, (void *) scsipkt,
4360436b3c604bc28d37be269ad152b4c38157c3pawelw TQ_SLEEP) == NULL)
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw /* Scheduling the callback failed */
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw return (TRAN_BUSY);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (TRAN_ACCEPT);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Analyze device status and error registers and translate them into
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * appropriate scsi sense codes.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * NOTE: non-packet commands only for now
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_decode_device_error(sata_pkt_txlate_t *spx,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf struct scsi_extended_sense *sense)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf uint8_t err_reg = spx->txlt_sata_pkt->satapkt_cmd.satacmd_error_reg;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ASSERT(sense != NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ASSERT(spx->txlt_sata_pkt->satapkt_cmd.satacmd_status_reg &
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_STATUS_ERR);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (err_reg & SATA_ERROR_ICRC) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense->es_key = KEY_ABORTED_COMMAND;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense->es_add_code = 0x08; /* Communication failure */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (err_reg & SATA_ERROR_UNC) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense->es_key = KEY_MEDIUM_ERROR;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Information bytes (LBA) need to be set by a caller */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* ADD HERE: MC error bit handling for ATAPI CD/DVD */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (err_reg & (SATA_ERROR_MCR | SATA_ERROR_NM)) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense->es_key = KEY_UNIT_ATTENTION;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense->es_add_code = 0x3a; /* No media present */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (err_reg & SATA_ERROR_IDNF) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (err_reg & SATA_ERROR_ABORT) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense->es_key = KEY_ABORTED_COMMAND;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense->es_key = KEY_ILLEGAL_REQUEST;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense->es_add_code = 0x21; /* LBA out of range */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (err_reg & SATA_ERROR_ABORT) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ASSERT(spx->txlt_sata_pkt != NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense->es_key = KEY_ABORTED_COMMAND;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Extract error LBA from sata_pkt.satapkt_cmd register fields
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_extract_error_lba(sata_pkt_txlate_t *spx, uint64_t *lba)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_cmd_t *sata_cmd = &spx->txlt_sata_pkt->satapkt_cmd;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *lba = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_cmd->satacmd_addr_type == ATA_ADDR_LBA48) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *lba = sata_cmd->satacmd_lba_high_msb;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *lba = (*lba << 8) | sata_cmd->satacmd_lba_mid_msb;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *lba = (*lba << 8) | sata_cmd->satacmd_lba_low_msb;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else if (sata_cmd->satacmd_addr_type == ATA_ADDR_LBA28) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *lba = sata_cmd->satacmd_device_reg & 0xf;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *lba = (*lba << 8) | sata_cmd->satacmd_lba_high_lsb;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *lba = (*lba << 8) | sata_cmd->satacmd_lba_mid_lsb;
37a077ef1920ee044b2887247b2a802e726d3368ls *lba = (*lba << 8) | sata_cmd->satacmd_lba_low_lsb;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * This is fixed sense format - if LBA exceeds the info field size,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * no valid info will be returned (valid bit in extended sense will
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * be set to 0).
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic struct scsi_extended_sense *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_arq_sense(sata_pkt_txlate_t *spx)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf struct scsi_pkt *scsipkt = spx->txlt_scsi_pkt;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf struct scsi_arq_status *arqs;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf struct scsi_extended_sense *sense;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Fill ARQ sense data */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsipkt->pkt_state |= STATE_ARQ_DONE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf arqs = (struct scsi_arq_status *)scsipkt->pkt_scbp;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *(uchar_t *)&arqs->sts_status = STATUS_CHECK;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *(uchar_t *)&arqs->sts_rqpkt_status = STATUS_GOOD;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf arqs->sts_rqpkt_reason = CMD_CMPLT;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf arqs->sts_rqpkt_state = STATE_GOT_BUS | STATE_GOT_TARGET |
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf STATE_XFERRED_DATA | STATE_SENT_CMD | STATE_GOT_STATUS;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf arqs->sts_rqpkt_resid = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense = &arqs->sts_sensedata;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf bzero(sense, sizeof (struct scsi_extended_sense));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_fixed_sense_data_preset(sense);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (sense);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
4360436b3c604bc28d37be269ad152b4c38157c3pawelw/*
4360436b3c604bc28d37be269ad152b4c38157c3pawelw * Emulated SATA Read/Write command completion for zero-length requests.
4360436b3c604bc28d37be269ad152b4c38157c3pawelw * This request always succedes, so in synchronous mode it always returns
4360436b3c604bc28d37be269ad152b4c38157c3pawelw * TRAN_ACCEPT, and in non-synchronous mode it may return TRAN_BUSY if the
4360436b3c604bc28d37be269ad152b4c38157c3pawelw * callback cannot be scheduled.
4360436b3c604bc28d37be269ad152b4c38157c3pawelw */
4360436b3c604bc28d37be269ad152b4c38157c3pawelwstatic int
4360436b3c604bc28d37be269ad152b4c38157c3pawelwsata_emul_rw_completion(sata_pkt_txlate_t *spx)
4360436b3c604bc28d37be269ad152b4c38157c3pawelw{
4360436b3c604bc28d37be269ad152b4c38157c3pawelw struct scsi_pkt *scsipkt = spx->txlt_scsi_pkt;
4360436b3c604bc28d37be269ad152b4c38157c3pawelw
4360436b3c604bc28d37be269ad152b4c38157c3pawelw scsipkt->pkt_state = STATE_GOT_BUS | STATE_GOT_TARGET |
4360436b3c604bc28d37be269ad152b4c38157c3pawelw STATE_SENT_CMD | STATE_GOT_STATUS;
4360436b3c604bc28d37be269ad152b4c38157c3pawelw scsipkt->pkt_reason = CMD_CMPLT;
4360436b3c604bc28d37be269ad152b4c38157c3pawelw *scsipkt->pkt_scbp = STATUS_GOOD;
4360436b3c604bc28d37be269ad152b4c38157c3pawelw if (!(spx->txlt_sata_pkt->satapkt_op_mode & SATA_OPMODE_SYNCH)) {
4360436b3c604bc28d37be269ad152b4c38157c3pawelw /* scsi callback required - have to schedule it */
4360436b3c604bc28d37be269ad152b4c38157c3pawelw if (taskq_dispatch(SATA_TXLT_TASKQ(spx),
4360436b3c604bc28d37be269ad152b4c38157c3pawelw (task_func_t *)scsipkt->pkt_comp,
4360436b3c604bc28d37be269ad152b4c38157c3pawelw (void *)scsipkt, TQ_SLEEP) == NULL)
4360436b3c604bc28d37be269ad152b4c38157c3pawelw /* Scheduling the callback failed */
4360436b3c604bc28d37be269ad152b4c38157c3pawelw return (TRAN_BUSY);
4360436b3c604bc28d37be269ad152b4c38157c3pawelw }
4360436b3c604bc28d37be269ad152b4c38157c3pawelw return (TRAN_ACCEPT);
4360436b3c604bc28d37be269ad152b4c38157c3pawelw}
4360436b3c604bc28d37be269ad152b4c38157c3pawelw
4360436b3c604bc28d37be269ad152b4c38157c3pawelw
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Translate completion status of SATA read/write commands into scsi response.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * pkt completion_reason is checked to determine the completion status.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Do scsi callback if necessary.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Note: this function may be called also for synchronously executed
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * commands.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * This function may be used only if scsi_pkt is non-NULL.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_txlt_rw_completion(sata_pkt_t *sata_pkt)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_pkt_txlate_t *spx =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (sata_pkt_txlate_t *)sata_pkt->satapkt_framework_private;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_cmd_t *scmd = &sata_pkt->satapkt_cmd;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf struct scsi_pkt *scsipkt = spx->txlt_scsi_pkt;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf struct scsi_extended_sense *sense;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf uint64_t lba;
7a70ede882eacbae00c8d5209afb443e7755684cpawelw struct buf *bp;
7a70ede882eacbae00c8d5209afb443e7755684cpawelw int rval;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_pkt->satapkt_reason == SATA_PKT_COMPLETED) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Normal completion */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsipkt->pkt_state = STATE_GOT_BUS | STATE_GOT_TARGET |
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf STATE_SENT_CMD | STATE_XFERRED_DATA | STATE_GOT_STATUS;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsipkt->pkt_reason = CMD_CMPLT;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *scsipkt->pkt_scbp = STATUS_GOOD;
7a70ede882eacbae00c8d5209afb443e7755684cpawelw if (spx->txlt_tmp_buf != NULL) {
7a70ede882eacbae00c8d5209afb443e7755684cpawelw /* Temporary buffer was used */
7a70ede882eacbae00c8d5209afb443e7755684cpawelw bp = spx->txlt_sata_pkt->satapkt_cmd.satacmd_bp;
7a70ede882eacbae00c8d5209afb443e7755684cpawelw if (bp->b_flags & B_READ) {
7a70ede882eacbae00c8d5209afb443e7755684cpawelw rval = ddi_dma_sync(
7a70ede882eacbae00c8d5209afb443e7755684cpawelw spx->txlt_buf_dma_handle, 0, 0,
7a70ede882eacbae00c8d5209afb443e7755684cpawelw DDI_DMA_SYNC_FORCPU);
7a70ede882eacbae00c8d5209afb443e7755684cpawelw ASSERT(rval == DDI_SUCCESS);
7a70ede882eacbae00c8d5209afb443e7755684cpawelw bcopy(spx->txlt_tmp_buf, bp->b_un.b_addr,
7a70ede882eacbae00c8d5209afb443e7755684cpawelw bp->b_bcount);
7a70ede882eacbae00c8d5209afb443e7755684cpawelw }
7a70ede882eacbae00c8d5209afb443e7755684cpawelw }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Something went wrong - analyze return
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsipkt->pkt_state = STATE_GOT_BUS | STATE_GOT_TARGET |
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf STATE_SENT_CMD | STATE_GOT_STATUS;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsipkt->pkt_reason = CMD_INCOMPLETE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *scsipkt->pkt_scbp = STATUS_CHECK;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense = sata_arq_sense(spx);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ASSERT(sense != NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * SATA_PKT_DEV_ERROR is the only case where we may be able to
c03acfcad7780db4ddf763511a82026680b3b2c1ls * extract from device registers the failing LBA.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_pkt->satapkt_reason == SATA_PKT_DEV_ERROR) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((scmd->satacmd_addr_type == ATA_ADDR_LBA48) &&
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (scmd->satacmd_lba_mid_msb != 0 ||
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_lba_high_msb != 0)) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * We have problem reporting this cmd LBA
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * in fixed sense data format, because of
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * the size of the scsi LBA fields.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense->es_valid = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_extract_error_lba(spx, &lba);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense->es_info_1 = (lba & 0xFF000000) >> 24;
37a077ef1920ee044b2887247b2a802e726d3368ls sense->es_info_2 = (lba & 0xFF0000) >> 16;
37a077ef1920ee044b2887247b2a802e726d3368ls sense->es_info_3 = (lba & 0xFF00) >> 8;
37a077ef1920ee044b2887247b2a802e726d3368ls sense->es_info_4 = lba & 0xFF;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Invalid extended sense info */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense->es_valid = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf switch (sata_pkt->satapkt_reason) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SATA_PKT_PORT_ERROR:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* We may want to handle DEV GONE state as well */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * We have no device data. Assume no data transfered.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense->es_key = KEY_HARDWARE_ERROR;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SATA_PKT_DEV_ERROR:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_pkt->satapkt_cmd.satacmd_status_reg &
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_STATUS_ERR) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * determine dev error reason from error
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * reg content
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_decode_device_error(spx, sense);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sense->es_key == KEY_MEDIUM_ERROR) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf switch (scmd->satacmd_cmd_reg) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SATAC_READ_DMA:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SATAC_READ_DMA_EXT:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SATAC_READ_DMA_QUEUED:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SATAC_READ_DMA_QUEUED_EXT:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SATAC_READ_FPDMA_QUEUED:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Unrecovered read error */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense->es_add_code =
c75976d12071ddd21443266260066ba036671682pawelw SD_SCSI_ASC_UNREC_READ_ERR;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SATAC_WRITE_DMA:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SATAC_WRITE_DMA_EXT:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SATAC_WRITE_DMA_QUEUED:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SATAC_WRITE_DMA_QUEUED_EXT:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SATAC_WRITE_FPDMA_QUEUED:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Write error */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense->es_add_code =
c75976d12071ddd21443266260066ba036671682pawelw SD_SCSI_ASC_WRITE_ERR;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf default:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Internal error */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_LOG_D((
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf CE_WARN,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_txlt_rw_completion :"
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "internal error - invalid "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "command 0x%2x",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_cmd_reg));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* No extended sense key - no info available */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsipkt->pkt_reason = CMD_INCOMPLETE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SATA_PKT_TIMEOUT:
ae8faf9c0cd738ab78a672de5bf7e7f7d004ebb2ls scsipkt->pkt_reason = CMD_TIMEOUT;
ae8faf9c0cd738ab78a672de5bf7e7f7d004ebb2ls scsipkt->pkt_statistics |=
ae8faf9c0cd738ab78a672de5bf7e7f7d004ebb2ls STAT_TIMEOUT | STAT_DEV_RESET;
ae8faf9c0cd738ab78a672de5bf7e7f7d004ebb2ls sense->es_key = KEY_ABORTED_COMMAND;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SATA_PKT_ABORTED:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsipkt->pkt_reason = CMD_ABORTED;
ae8faf9c0cd738ab78a672de5bf7e7f7d004ebb2ls scsipkt->pkt_statistics |= STAT_ABORTED;
ae8faf9c0cd738ab78a672de5bf7e7f7d004ebb2ls sense->es_key = KEY_ABORTED_COMMAND;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SATA_PKT_RESET:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsipkt->pkt_reason = CMD_RESET;
ae8faf9c0cd738ab78a672de5bf7e7f7d004ebb2ls scsipkt->pkt_statistics |= STAT_DEV_RESET;
ae8faf9c0cd738ab78a672de5bf7e7f7d004ebb2ls sense->es_key = KEY_ABORTED_COMMAND;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf default:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_LOG_D((spx->txlt_sata_hba_inst, CE_WARN,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_txlt_rw_completion: "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "invalid packet completion reason"));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsipkt->pkt_reason = CMD_TRAN_ERR;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG1(SATA_DBG_SCSI_IF, spx->txlt_sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "Scsi_pkt completion reason %x\n", scsipkt->pkt_reason);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
9c57abc8d70cb139020be846baec0a9c4d9a73cdsrivijitha dugganapalli if ((scsipkt->pkt_flags & FLAG_NOINTR) == 0)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* scsi callback required */
9c57abc8d70cb139020be846baec0a9c4d9a73cdsrivijitha dugganapalli scsi_hba_pkt_comp(scsipkt);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Translate completion status of non-data commands (i.e. commands returning
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * no data).
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * pkt completion_reason is checked to determine the completion status.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Do scsi callback if necessary (FLAG_NOINTR == 0)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Note: this function may be called also for synchronously executed
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * commands.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * This function may be used only if scsi_pkt is non-NULL.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chustatic void
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_txlt_nodata_cmd_completion(sata_pkt_t *sata_pkt)
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu{
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sata_pkt_txlate_t *spx =
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu (sata_pkt_txlate_t *)sata_pkt->satapkt_framework_private;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu struct scsi_pkt *scsipkt = spx->txlt_scsi_pkt;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sata_set_arq_data(sata_pkt);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if ((scsipkt->pkt_flags & FLAG_NOINTR) == 0)
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu /* scsi callback required */
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu scsi_hba_pkt_comp(scsipkt);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu}
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chustatic void
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chusata_set_arq_data(sata_pkt_t *sata_pkt)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_pkt_txlate_t *spx =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (sata_pkt_txlate_t *)sata_pkt->satapkt_framework_private;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf struct scsi_pkt *scsipkt = spx->txlt_scsi_pkt;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf struct scsi_extended_sense *sense;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsipkt->pkt_state = STATE_GOT_BUS | STATE_GOT_TARGET |
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf STATE_SENT_CMD | STATE_GOT_STATUS;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_pkt->satapkt_reason == SATA_PKT_COMPLETED) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Normal completion */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsipkt->pkt_reason = CMD_CMPLT;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *scsipkt->pkt_scbp = STATUS_GOOD;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Something went wrong */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsipkt->pkt_reason = CMD_INCOMPLETE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *scsipkt->pkt_scbp = STATUS_CHECK;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense = sata_arq_sense(spx);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf switch (sata_pkt->satapkt_reason) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SATA_PKT_PORT_ERROR:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * We have no device data. Assume no data transfered.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense->es_key = KEY_HARDWARE_ERROR;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SATA_PKT_DEV_ERROR:
184cd04c26b064536977dfbb913a1240eaf6f708cth if (sata_pkt->satapkt_cmd.satacmd_status_reg &
184cd04c26b064536977dfbb913a1240eaf6f708cth SATA_STATUS_ERR) {
184cd04c26b064536977dfbb913a1240eaf6f708cth /*
184cd04c26b064536977dfbb913a1240eaf6f708cth * determine dev error reason from error
184cd04c26b064536977dfbb913a1240eaf6f708cth * reg content
184cd04c26b064536977dfbb913a1240eaf6f708cth */
184cd04c26b064536977dfbb913a1240eaf6f708cth sata_decode_device_error(spx, sense);
184cd04c26b064536977dfbb913a1240eaf6f708cth break;
184cd04c26b064536977dfbb913a1240eaf6f708cth }
184cd04c26b064536977dfbb913a1240eaf6f708cth /* No extended sense key - no info available */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SATA_PKT_TIMEOUT:
ae8faf9c0cd738ab78a672de5bf7e7f7d004ebb2ls scsipkt->pkt_reason = CMD_TIMEOUT;
ae8faf9c0cd738ab78a672de5bf7e7f7d004ebb2ls scsipkt->pkt_statistics |=
ae8faf9c0cd738ab78a672de5bf7e7f7d004ebb2ls STAT_TIMEOUT | STAT_DEV_RESET;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* No extended sense key ? */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SATA_PKT_ABORTED:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsipkt->pkt_reason = CMD_ABORTED;
ae8faf9c0cd738ab78a672de5bf7e7f7d004ebb2ls scsipkt->pkt_statistics |= STAT_ABORTED;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* No extended sense key ? */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SATA_PKT_RESET:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* pkt aborted by an explicit reset from a host */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsipkt->pkt_reason = CMD_RESET;
ae8faf9c0cd738ab78a672de5bf7e7f7d004ebb2ls scsipkt->pkt_statistics |= STAT_DEV_RESET;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf default:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_LOG_D((spx->txlt_sata_hba_inst, CE_WARN,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_txlt_nodata_cmd_completion: "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "invalid packet completion reason %d",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_pkt->satapkt_reason));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsipkt->pkt_reason = CMD_TRAN_ERR;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG1(SATA_DBG_SCSI_IF, spx->txlt_sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "Scsi_pkt completion reason %x\n", scsipkt->pkt_reason);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Build Mode sense R/W recovery page
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * NOT IMPLEMENTED
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_build_msense_page_1(sata_drive_info_t *sdinfo, int pcntrl, uint8_t *buf)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#ifndef __lock_lint
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf _NOTE(ARGUNUSED(sdinfo))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf _NOTE(ARGUNUSED(pcntrl))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf _NOTE(ARGUNUSED(buf))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#endif
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (0);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Build Mode sense caching page - scsi-3 implementation.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Page length distinguishes previous format from scsi-3 format.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * buf must have space for 0x12 bytes.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Only DRA (disable read ahead ) and WCE (write cache enable) are changeable.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_build_msense_page_8(sata_drive_info_t *sdinfo, int pcntrl, uint8_t *buf)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf struct mode_cache_scsi3 *page = (struct mode_cache_scsi3 *)buf;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_id_t *sata_id = &sdinfo->satadrv_id;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Most of the fields are set to 0, being not supported and/or disabled
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf bzero(buf, PAGELENGTH_DAD_MODE_CACHE_SCSI3);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls /* Saved paramters not supported */
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls if (pcntrl == 3)
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls return (0);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (pcntrl == 0 || pcntrl == 2) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * For now treat current and default parameters as same
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * That may have to change, if target driver will complain
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf page->mode_page.code = MODEPAGE_CACHING; /* PS = 0 */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf page->mode_page.length = PAGELENGTH_DAD_MODE_CACHE_SCSI3;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
7095af1983f107c8b16839f70101fdf710c4e620ying tian - Beijing China if (SATA_READ_AHEAD_SUPPORTED(*sata_id) &&
7095af1983f107c8b16839f70101fdf710c4e620ying tian - Beijing China !SATA_READ_AHEAD_ENABLED(*sata_id)) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf page->dra = 1; /* Read Ahead disabled */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf page->rcd = 1; /* Read Cache disabled */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
7095af1983f107c8b16839f70101fdf710c4e620ying tian - Beijing China if (SATA_WRITE_CACHE_SUPPORTED(*sata_id) &&
7095af1983f107c8b16839f70101fdf710c4e620ying tian - Beijing China SATA_WRITE_CACHE_ENABLED(*sata_id))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf page->wce = 1; /* Write Cache enabled */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Changeable parameters */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf page->mode_page.code = MODEPAGE_CACHING;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf page->mode_page.length = PAGELENGTH_DAD_MODE_CACHE_SCSI3;
7095af1983f107c8b16839f70101fdf710c4e620ying tian - Beijing China if (SATA_READ_AHEAD_SUPPORTED(*sata_id)) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf page->dra = 1;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf page->rcd = 1;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
7095af1983f107c8b16839f70101fdf710c4e620ying tian - Beijing China if (SATA_WRITE_CACHE_SUPPORTED(*sata_id))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf page->wce = 1;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (PAGELENGTH_DAD_MODE_CACHE_SCSI3 +
184cd04c26b064536977dfbb913a1240eaf6f708cth sizeof (struct mode_page));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Build Mode sense exception cntrl page
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_build_msense_page_1c(sata_drive_info_t *sdinfo, int pcntrl, uint8_t *buf)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls struct mode_info_excpt_page *page = (struct mode_info_excpt_page *)buf;
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls sata_id_t *sata_id = &sdinfo->satadrv_id;
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls /*
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls * Most of the fields are set to 0, being not supported and/or disabled
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls */
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls bzero(buf, PAGELENGTH_INFO_EXCPT);
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls page->mode_page.code = MODEPAGE_INFO_EXCPT;
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls page->mode_page.length = PAGELENGTH_INFO_EXCPT;
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls /* Indicate that this is page is saveable */
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls page->mode_page.ps = 1;
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls /*
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls * We will return the same data for default, current and saved page.
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls * The only changeable bit is dexcpt and that bit is required
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls * by the ATA specification to be preserved across power cycles.
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls */
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls if (pcntrl != 1) {
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls page->dexcpt = !(sata_id->ai_features85 & SATA_SMART_SUPPORTED);
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls page->mrie = MRIE_ONLY_ON_REQUEST;
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls }
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls else
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls page->dexcpt = 1; /* Only changeable parameter */
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls
20bc265b0a583202225a5621ab565fc73a34404dPhi Tran return (PAGELENGTH_INFO_EXCPT + sizeof (struct mode_page));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960lsstatic int
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960lssata_build_msense_page_30(sata_drive_info_t *sdinfo, int pcntrl, uint8_t *buf)
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls{
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls struct mode_acoustic_management *page =
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls (struct mode_acoustic_management *)buf;
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls sata_id_t *sata_id = &sdinfo->satadrv_id;
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls /*
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls * Most of the fields are set to 0, being not supported and/or disabled
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls */
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls bzero(buf, PAGELENGTH_DAD_MODE_ACOUSTIC_MANAGEMENT);
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls switch (pcntrl) {
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls case P_CNTRL_DEFAULT:
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls /* default paramters not supported */
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls return (0);
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls case P_CNTRL_CURRENT:
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls case P_CNTRL_SAVED:
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls /* Saved and current are supported and are identical */
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls page->mode_page.code = MODEPAGE_ACOUSTIC_MANAG;
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls page->mode_page.length =
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls PAGELENGTH_DAD_MODE_ACOUSTIC_MANAGEMENT;
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls page->mode_page.ps = 1;
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls /* Word 83 indicates if feature is supported */
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls /* If feature is not supported */
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls if (!(sata_id->ai_cmdset83 & SATA_ACOUSTIC_MGMT)) {
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls page->acoustic_manag_enable =
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls ACOUSTIC_DISABLED;
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls } else {
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls page->acoustic_manag_enable =
dbbe7b71d90bb93ec45e5c8d8585f98cc2848a30ls ((sata_id->ai_features86 & SATA_ACOUSTIC_MGMT)
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls != 0);
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls /* Word 94 inidicates the value */
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls#ifdef _LITTLE_ENDIAN
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls page->acoustic_manag_level =
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls (uchar_t)sata_id->ai_acoustic;
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls page->vendor_recommended_value =
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls sata_id->ai_acoustic >> 8;
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls#else
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls page->acoustic_manag_level =
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls sata_id->ai_acoustic >> 8;
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls page->vendor_recommended_value =
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls (uchar_t)sata_id->ai_acoustic;
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls#endif
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls }
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls break;
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls case P_CNTRL_CHANGEABLE:
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls page->mode_page.code = MODEPAGE_ACOUSTIC_MANAG;
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls page->mode_page.length =
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls PAGELENGTH_DAD_MODE_ACOUSTIC_MANAGEMENT;
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls page->mode_page.ps = 1;
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls /* Word 83 indicates if the feature is supported */
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls if (sata_id->ai_cmdset83 & SATA_ACOUSTIC_MGMT) {
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls page->acoustic_manag_enable =
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls ACOUSTIC_ENABLED;
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls page->acoustic_manag_level = 0xff;
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls }
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls break;
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls }
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls return (PAGELENGTH_DAD_MODE_ACOUSTIC_MANAGEMENT +
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls sizeof (struct mode_page));
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls}
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu * Build Mode sense power condition page.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_build_msense_page_1a(sata_drive_info_t *sdinfo, int pcntrl, uint8_t *buf)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu struct mode_info_power_cond *page = (struct mode_info_power_cond *)buf;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sata_id_t *sata_id = &sdinfo->satadrv_id;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu /*
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu * Most of the fields are set to 0, being not supported and/or disabled
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu * power condition page length was 0x0a
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu */
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu bzero(buf, sizeof (struct mode_info_power_cond));
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if (pcntrl == P_CNTRL_DEFAULT) {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu /* default paramters not supported */
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu return (0);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu }
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu page->mode_page.code = MODEPAGE_POWER_COND;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu page->mode_page.length = sizeof (struct mode_info_power_cond);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if (sata_id->ai_cap && SATA_STANDBYTIMER) {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu page->standby = 1;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu bcopy(sdinfo->satadrv_standby_timer, page->standby_cond_timer,
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sizeof (uchar_t) * 4);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu }
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu return (sizeof (struct mode_info_power_cond));
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Process mode select caching page 8 (scsi3 format only).
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Read Ahead (same as read cache) and Write Cache may be turned on and off
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * if these features are supported by the device. If these features are not
20bc265b0a583202225a5621ab565fc73a34404dPhi Tran * supported, the command will be terminated with STATUS_CHECK.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * This function fails only if the SET FEATURE command sent to
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * the device fails. The page format is not varified, assuming that the
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * target driver operates correctly - if parameters length is too short,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * we just drop the page.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Two command may be sent if both Read Cache/Read Ahead and Write Cache
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * setting have to be changed.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * SET FEATURE command is executed synchronously, i.e. we wait here until
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * it is completed, regardless of the scsi pkt directives.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Note: Mode Select Caching page RCD and DRA bits are tied together, i.e.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * changing DRA will change RCD.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * More than one SATA command may be executed to perform operations specified
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * by mode select pages. The first error terminates further execution.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Operations performed successully are not backed-up in such case.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Return SATA_SUCCESS if operation succeeded, SATA_FAILURE otherwise.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * If operation resulted in changing device setup, dmod flag should be set to
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * one (1). If parameters were not changed, dmod flag should be set to 0.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Upon return, if operation required sending command to the device, the rval
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * should be set to the value returned by sata_hba_start. If operation
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * did not require device access, rval should be set to TRAN_ACCEPT.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * The pagelen should be set to the length of the page.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * This function has to be called with a port mutex held.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Returns SATA_SUCCESS if operation was successful, SATA_FAILURE otherwise.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfint
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_mode_select_page_8(sata_pkt_txlate_t *spx, struct mode_cache_scsi3 *page,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int parmlen, int *pagelen, int *rval, int *dmod)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf struct scsi_pkt *scsipkt = spx->txlt_scsi_pkt;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_drive_info_t *sdinfo;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_cmd_t *scmd = &spx->txlt_sata_pkt->satapkt_cmd;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_id_t *sata_id;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf struct scsi_extended_sense *sense;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int wce, dra; /* Current settings */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo = sata_get_device_info(spx->txlt_sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf &spx->txlt_sata_pkt->satapkt_device);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_id = &sdinfo->satadrv_id;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *dmod = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Verify parameters length. If too short, drop it */
20bc265b0a583202225a5621ab565fc73a34404dPhi Tran if ((PAGELENGTH_DAD_MODE_CACHE_SCSI3 +
20bc265b0a583202225a5621ab565fc73a34404dPhi Tran sizeof (struct mode_page)) > parmlen) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *scsipkt->pkt_scbp = STATUS_CHECK;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense = sata_arq_sense(spx);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense->es_key = KEY_ILLEGAL_REQUEST;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sense->es_add_code = SD_SCSI_ASC_INVALID_FIELD_IN_PARAMS_LIST;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *pagelen = parmlen;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *rval = TRAN_ACCEPT;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (SATA_FAILURE);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *pagelen = PAGELENGTH_DAD_MODE_CACHE_SCSI3 + sizeof (struct mode_page);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Current setting of Read Ahead (and Read Cache) */
7095af1983f107c8b16839f70101fdf710c4e620ying tian - Beijing China if (SATA_READ_AHEAD_ENABLED(*sata_id))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf dra = 0; /* 0 == not disabled */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf else
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf dra = 1;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Current setting of Write Cache */
7095af1983f107c8b16839f70101fdf710c4e620ying tian - Beijing China if (SATA_WRITE_CACHE_ENABLED(*sata_id))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf wce = 1;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf else
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf wce = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (page->dra == dra && page->wce == wce && page->rcd == dra) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* nothing to do */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *rval = TRAN_ACCEPT;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (SATA_SUCCESS);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Need to flip some setting
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Set-up Internal SET FEATURES command(s)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_flags.sata_data_direction = SATA_DIR_NODATA_XFER;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_addr_type = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_device_reg = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_status_reg = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_error_reg = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_cmd_reg = SATAC_SET_FEATURES;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (page->dra != dra || page->rcd != dra) {
20bc265b0a583202225a5621ab565fc73a34404dPhi Tran if (SATA_READ_AHEAD_SUPPORTED(*sata_id)) {
20bc265b0a583202225a5621ab565fc73a34404dPhi Tran /* Need to flip read ahead setting */
20bc265b0a583202225a5621ab565fc73a34404dPhi Tran if (dra == 0)
20bc265b0a583202225a5621ab565fc73a34404dPhi Tran /* Disable read ahead / read cache */
20bc265b0a583202225a5621ab565fc73a34404dPhi Tran scmd->satacmd_features_reg =
20bc265b0a583202225a5621ab565fc73a34404dPhi Tran SATAC_SF_DISABLE_READ_AHEAD;
20bc265b0a583202225a5621ab565fc73a34404dPhi Tran else
20bc265b0a583202225a5621ab565fc73a34404dPhi Tran /* Enable read ahead / read cache */
20bc265b0a583202225a5621ab565fc73a34404dPhi Tran scmd->satacmd_features_reg =
20bc265b0a583202225a5621ab565fc73a34404dPhi Tran SATAC_SF_ENABLE_READ_AHEAD;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
20bc265b0a583202225a5621ab565fc73a34404dPhi Tran /* Transfer command to HBA */
20bc265b0a583202225a5621ab565fc73a34404dPhi Tran if (sata_hba_start(spx, rval) != 0)
20bc265b0a583202225a5621ab565fc73a34404dPhi Tran /*
20bc265b0a583202225a5621ab565fc73a34404dPhi Tran * Pkt not accepted for execution.
20bc265b0a583202225a5621ab565fc73a34404dPhi Tran */
20bc265b0a583202225a5621ab565fc73a34404dPhi Tran return (SATA_FAILURE);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
20bc265b0a583202225a5621ab565fc73a34404dPhi Tran *dmod = 1;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
20bc265b0a583202225a5621ab565fc73a34404dPhi Tran /* Now process return */
20bc265b0a583202225a5621ab565fc73a34404dPhi Tran if (spx->txlt_sata_pkt->satapkt_reason !=
20bc265b0a583202225a5621ab565fc73a34404dPhi Tran SATA_PKT_COMPLETED) {
20bc265b0a583202225a5621ab565fc73a34404dPhi Tran goto failure; /* Terminate */
20bc265b0a583202225a5621ab565fc73a34404dPhi Tran }
20bc265b0a583202225a5621ab565fc73a34404dPhi Tran } else {
20bc265b0a583202225a5621ab565fc73a34404dPhi Tran *scsipkt->pkt_scbp = STATUS_CHECK;
20bc265b0a583202225a5621ab565fc73a34404dPhi Tran sense = sata_arq_sense(spx);
20bc265b0a583202225a5621ab565fc73a34404dPhi Tran sense->es_key = KEY_ILLEGAL_REQUEST;
20bc265b0a583202225a5621ab565fc73a34404dPhi Tran sense->es_add_code =
20bc265b0a583202225a5621ab565fc73a34404dPhi Tran SD_SCSI_ASC_INVALID_FIELD_IN_PARAMS_LIST;
20bc265b0a583202225a5621ab565fc73a34404dPhi Tran *pagelen = parmlen;
20bc265b0a583202225a5621ab565fc73a34404dPhi Tran *rval = TRAN_ACCEPT;
20bc265b0a583202225a5621ab565fc73a34404dPhi Tran return (SATA_FAILURE);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Note that the packet is not removed, so it could be re-used */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (page->wce != wce) {
20bc265b0a583202225a5621ab565fc73a34404dPhi Tran if (SATA_WRITE_CACHE_SUPPORTED(*sata_id)) {
20bc265b0a583202225a5621ab565fc73a34404dPhi Tran /* Need to flip Write Cache setting */
20bc265b0a583202225a5621ab565fc73a34404dPhi Tran if (page->wce == 1)
20bc265b0a583202225a5621ab565fc73a34404dPhi Tran /* Enable write cache */
20bc265b0a583202225a5621ab565fc73a34404dPhi Tran scmd->satacmd_features_reg =
20bc265b0a583202225a5621ab565fc73a34404dPhi Tran SATAC_SF_ENABLE_WRITE_CACHE;
20bc265b0a583202225a5621ab565fc73a34404dPhi Tran else
20bc265b0a583202225a5621ab565fc73a34404dPhi Tran /* Disable write cache */
20bc265b0a583202225a5621ab565fc73a34404dPhi Tran scmd->satacmd_features_reg =
20bc265b0a583202225a5621ab565fc73a34404dPhi Tran SATAC_SF_DISABLE_WRITE_CACHE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
20bc265b0a583202225a5621ab565fc73a34404dPhi Tran /* Transfer command to HBA */
20bc265b0a583202225a5621ab565fc73a34404dPhi Tran if (sata_hba_start(spx, rval) != 0)
20bc265b0a583202225a5621ab565fc73a34404dPhi Tran /*
20bc265b0a583202225a5621ab565fc73a34404dPhi Tran * Pkt not accepted for execution.
20bc265b0a583202225a5621ab565fc73a34404dPhi Tran */
20bc265b0a583202225a5621ab565fc73a34404dPhi Tran return (SATA_FAILURE);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
20bc265b0a583202225a5621ab565fc73a34404dPhi Tran *dmod = 1;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
20bc265b0a583202225a5621ab565fc73a34404dPhi Tran /* Now process return */
20bc265b0a583202225a5621ab565fc73a34404dPhi Tran if (spx->txlt_sata_pkt->satapkt_reason !=
20bc265b0a583202225a5621ab565fc73a34404dPhi Tran SATA_PKT_COMPLETED) {
20bc265b0a583202225a5621ab565fc73a34404dPhi Tran goto failure;
20bc265b0a583202225a5621ab565fc73a34404dPhi Tran }
20bc265b0a583202225a5621ab565fc73a34404dPhi Tran } else {
20bc265b0a583202225a5621ab565fc73a34404dPhi Tran *scsipkt->pkt_scbp = STATUS_CHECK;
20bc265b0a583202225a5621ab565fc73a34404dPhi Tran sense = sata_arq_sense(spx);
20bc265b0a583202225a5621ab565fc73a34404dPhi Tran sense->es_key = KEY_ILLEGAL_REQUEST;
20bc265b0a583202225a5621ab565fc73a34404dPhi Tran sense->es_add_code =
20bc265b0a583202225a5621ab565fc73a34404dPhi Tran SD_SCSI_ASC_INVALID_FIELD_IN_PARAMS_LIST;
20bc265b0a583202225a5621ab565fc73a34404dPhi Tran *pagelen = parmlen;
20bc265b0a583202225a5621ab565fc73a34404dPhi Tran *rval = TRAN_ACCEPT;
20bc265b0a583202225a5621ab565fc73a34404dPhi Tran return (SATA_FAILURE);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (SATA_SUCCESS);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlffailure:
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls sata_xlate_errors(spx);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls return (SATA_FAILURE);
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls/*
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls * Process mode select informational exceptions control page 0x1c
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls *
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls * The only changeable bit is dexcpt (disable exceptions).
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls * MRIE (method of reporting informational exceptions) must be
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls * "only on request".
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik * This page applies to informational exceptions that report
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik * additional sense codes with the ADDITIONAL SENSE CODE field set to 5Dh
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik * (e.g.,FAILURE PREDICTION THRESHOLD EXCEEDED) or 0Bh (e.g., WARNING_).
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik * Informational exception conditions occur as the result of background scan
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik * errors, background self-test errors, or vendor specific events within a
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik * logical unit. An informational exception condition may occur asynchronous
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik * to any commands.
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik *
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik * Returns: SATA_SUCCESS if operation succeeded, SATA_FAILURE otherwise.
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls * If operation resulted in changing device setup, dmod flag should be set to
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls * one (1). If parameters were not changed, dmod flag should be set to 0.
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls * Upon return, if operation required sending command to the device, the rval
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls * should be set to the value returned by sata_hba_start. If operation
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls * did not require device access, rval should be set to TRAN_ACCEPT.
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls * The pagelen should be set to the length of the page.
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls *
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls * This function has to be called with a port mutex held.
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls *
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls * Returns SATA_SUCCESS if operation was successful, SATA_FAILURE otherwise.
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik *
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik * Cannot be called in the interrupt context.
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls */
2c9565cfcd87a2045c2e4b76f31ac4e978903589lsstatic int
2c9565cfcd87a2045c2e4b76f31ac4e978903589lssata_mode_select_page_1c(
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls sata_pkt_txlate_t *spx,
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls struct mode_info_excpt_page *page,
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls int parmlen,
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls int *pagelen,
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls int *rval,
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls int *dmod)
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls{
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls struct scsi_pkt *scsipkt = spx->txlt_scsi_pkt;
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls sata_cmd_t *scmd = &spx->txlt_sata_pkt->satapkt_cmd;
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls sata_drive_info_t *sdinfo;
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls sata_id_t *sata_id;
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls struct scsi_extended_sense *sense;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls sdinfo = sata_get_device_info(spx->txlt_sata_hba_inst,
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls &spx->txlt_sata_pkt->satapkt_device);
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls sata_id = &sdinfo->satadrv_id;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls *dmod = 0;
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls /* Verify parameters length. If too short, drop it */
20bc265b0a583202225a5621ab565fc73a34404dPhi Tran if (((PAGELENGTH_INFO_EXCPT + sizeof (struct mode_page)) > parmlen) ||
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls page->perf || page->test || (page->mrie != MRIE_ONLY_ON_REQUEST)) {
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls *scsipkt->pkt_scbp = STATUS_CHECK;
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls sense = sata_arq_sense(spx);
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls sense->es_key = KEY_ILLEGAL_REQUEST;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sense->es_add_code = SD_SCSI_ASC_INVALID_FIELD_IN_PARAMS_LIST;
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls *pagelen = parmlen;
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls *rval = TRAN_ACCEPT;
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls return (SATA_FAILURE);
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls }
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls *pagelen = PAGELENGTH_INFO_EXCPT + sizeof (struct mode_page);
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls if (! (sata_id->ai_cmdset82 & SATA_SMART_SUPPORTED)) {
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls *scsipkt->pkt_scbp = STATUS_CHECK;
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls sense = sata_arq_sense(spx);
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls sense->es_key = KEY_ILLEGAL_REQUEST;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sense->es_add_code = SD_SCSI_ASC_INVALID_FIELD_IN_CDB;
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls *pagelen = parmlen;
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls *rval = TRAN_ACCEPT;
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls return (SATA_FAILURE);
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls }
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls /* If already in the state requested, we are done */
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls if (page->dexcpt == ! (sata_id->ai_features85 & SATA_SMART_ENABLED)) {
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls /* nothing to do */
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls *rval = TRAN_ACCEPT;
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls return (SATA_SUCCESS);
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls }
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls scmd->satacmd_flags.sata_data_direction = SATA_DIR_NODATA_XFER;
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls /* Build SMART_ENABLE or SMART_DISABLE command */
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls scmd->satacmd_addr_type = 0; /* N/A */
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls scmd->satacmd_lba_mid_lsb = SMART_MAGIC_VAL_1;
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls scmd->satacmd_lba_high_lsb = SMART_MAGIC_VAL_2;
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls scmd->satacmd_features_reg = page->dexcpt ?
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls SATA_SMART_DISABLE_OPS : SATA_SMART_ENABLE_OPS;
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls scmd->satacmd_device_reg = 0; /* Always device 0 */
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls scmd->satacmd_cmd_reg = SATAC_SMART;
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls /* Transfer command to HBA */
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls if (sata_hba_start(spx, rval) != 0)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls * Pkt not accepted for execution.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls return (SATA_FAILURE);
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls *dmod = 1; /* At least may have been modified */
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls /* Now process return */
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls if (spx->txlt_sata_pkt->satapkt_reason == SATA_PKT_COMPLETED)
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls return (SATA_SUCCESS);
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls /* Packet did not complete successfully */
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls sata_xlate_errors(spx);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (SATA_FAILURE);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik/*
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik * Process mode select acoustic management control page 0x30
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik *
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik *
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik * This function has to be called with a port mutex held.
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik *
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik * Returns SATA_SUCCESS if operation was successful, SATA_FAILURE otherwise.
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik *
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik * Cannot be called in the interrupt context.
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik */
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960lsint
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960lssata_mode_select_page_30(sata_pkt_txlate_t *spx, struct
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls mode_acoustic_management *page, int parmlen, int *pagelen,
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls int *rval, int *dmod)
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls{
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls struct scsi_pkt *scsipkt = spx->txlt_scsi_pkt;
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls sata_drive_info_t *sdinfo;
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls sata_cmd_t *scmd = &spx->txlt_sata_pkt->satapkt_cmd;
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls sata_id_t *sata_id;
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls struct scsi_extended_sense *sense;
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls sdinfo = sata_get_device_info(spx->txlt_sata_hba_inst,
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls &spx->txlt_sata_pkt->satapkt_device);
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls sata_id = &sdinfo->satadrv_id;
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls *dmod = 0;
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls /* If parmlen is too short or the feature is not supported, drop it */
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls if (((PAGELENGTH_DAD_MODE_ACOUSTIC_MANAGEMENT +
20bc265b0a583202225a5621ab565fc73a34404dPhi Tran sizeof (struct mode_page)) > parmlen) ||
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls (! (sata_id->ai_cmdset83 & SATA_ACOUSTIC_MGMT))) {
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls *scsipkt->pkt_scbp = STATUS_CHECK;
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls sense = sata_arq_sense(spx);
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls sense->es_key = KEY_ILLEGAL_REQUEST;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sense->es_add_code = SD_SCSI_ASC_INVALID_FIELD_IN_PARAMS_LIST;
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls *pagelen = parmlen;
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls *rval = TRAN_ACCEPT;
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls return (SATA_FAILURE);
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls }
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls *pagelen = PAGELENGTH_DAD_MODE_ACOUSTIC_MANAGEMENT +
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls sizeof (struct mode_page);
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls /*
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls * We can enable and disable acoustice management and
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls * set the acoustic management level.
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls */
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls /*
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls * Set-up Internal SET FEATURES command(s)
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls */
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls scmd->satacmd_flags.sata_data_direction = SATA_DIR_NODATA_XFER;
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls scmd->satacmd_addr_type = 0;
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls scmd->satacmd_device_reg = 0;
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls scmd->satacmd_status_reg = 0;
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls scmd->satacmd_error_reg = 0;
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls scmd->satacmd_cmd_reg = SATAC_SET_FEATURES;
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls if (page->acoustic_manag_enable) {
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls scmd->satacmd_features_reg = SATAC_SF_ENABLE_ACOUSTIC;
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls scmd->satacmd_sec_count_lsb = page->acoustic_manag_level;
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls } else { /* disabling acoustic management */
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls scmd->satacmd_features_reg = SATAC_SF_DISABLE_ACOUSTIC;
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls }
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls /* Transfer command to HBA */
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls if (sata_hba_start(spx, rval) != 0)
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls /*
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls * Pkt not accepted for execution.
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls */
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls return (SATA_FAILURE);
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls /* Now process return */
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls if (spx->txlt_sata_pkt->satapkt_reason != SATA_PKT_COMPLETED) {
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls sata_xlate_errors(spx);
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls return (SATA_FAILURE);
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls }
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls *dmod = 1;
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls return (SATA_SUCCESS);
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls}
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu/*
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu * Process mode select power condition page 0x1a
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu *
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu * This function has to be called with a port mutex held.
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu *
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu * Returns SATA_SUCCESS if operation was successful, SATA_FAILURE otherwise.
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu *
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu * Cannot be called in the interrupt context.
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu */
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chuint
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chusata_mode_select_page_1a(sata_pkt_txlate_t *spx, struct
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu mode_info_power_cond *page, int parmlen, int *pagelen,
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu int *rval, int *dmod)
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu{
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu struct scsi_pkt *scsipkt = spx->txlt_scsi_pkt;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sata_drive_info_t *sdinfo;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sata_cmd_t *scmd = &spx->txlt_sata_pkt->satapkt_cmd;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sata_id_t *sata_id;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu struct scsi_extended_sense *sense;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu uint8_t ata_count;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu int i, len;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sdinfo = sata_get_device_info(spx->txlt_sata_hba_inst,
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu &spx->txlt_sata_pkt->satapkt_device);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sata_id = &sdinfo->satadrv_id;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu *dmod = 0;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu len = sizeof (struct mode_info_power_cond);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu len += sizeof (struct mode_page);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu /* If parmlen is too short or the feature is not supported, drop it */
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if ((len < parmlen) || (page->idle == 1) ||
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu (!(sata_id->ai_cap && SATA_STANDBYTIMER) && page->standby == 1)) {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu *scsipkt->pkt_scbp = STATUS_CHECK;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sense = sata_arq_sense(spx);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sense->es_key = KEY_ILLEGAL_REQUEST;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sense->es_add_code = SD_SCSI_ASC_INVALID_FIELD_IN_PARAMS_LIST;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu *pagelen = parmlen;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu *rval = TRAN_ACCEPT;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu return (SATA_FAILURE);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu }
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu *pagelen = len;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu /*
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu * Set-up Internal STANDBY command(s)
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu */
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if (page->standby == 0)
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu goto out;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu ata_count = sata_get_standby_timer(page->standby_cond_timer);
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu scmd->satacmd_addr_type = 0;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu scmd->satacmd_sec_count_lsb = ata_count;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu scmd->satacmd_lba_low_lsb = 0;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu scmd->satacmd_lba_mid_lsb = 0;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu scmd->satacmd_lba_high_lsb = 0;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu scmd->satacmd_features_reg = 0;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu scmd->satacmd_device_reg = 0;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu scmd->satacmd_status_reg = 0;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu scmd->satacmd_cmd_reg = SATAC_STANDBY;
776955ed2c90dad066581c20700f1969e3c15f77Ada scmd->satacmd_flags.sata_special_regs = B_TRUE;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu scmd->satacmd_flags.sata_copy_out_error_reg = B_TRUE;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu /* Transfer command to HBA */
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if (sata_hba_start(spx, rval) != 0) {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu return (SATA_FAILURE);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu } else {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if ((scmd->satacmd_error_reg != 0) ||
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu (spx->txlt_sata_pkt->satapkt_reason !=
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu SATA_PKT_COMPLETED)) {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sata_xlate_errors(spx);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu return (SATA_FAILURE);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu }
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu }
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu for (i = 0; i < 4; i++) {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sdinfo->satadrv_standby_timer[i] = page->standby_cond_timer[i];
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu }
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chuout:
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu *dmod = 1;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu return (SATA_SUCCESS);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu}
b8b2574e5d3933aeb12d6ab6efd4dcf9fe9a5960ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls/*
c03acfcad7780db4ddf763511a82026680b3b2c1ls * sata_build_lsense_page0() is used to create the
c03acfcad7780db4ddf763511a82026680b3b2c1ls * SCSI LOG SENSE page 0 (supported log pages)
c03acfcad7780db4ddf763511a82026680b3b2c1ls *
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu * Currently supported pages are 0, 0x10, 0x2f, 0x30 and 0x0e
c03acfcad7780db4ddf763511a82026680b3b2c1ls * (supported log pages, self-test results, informational exceptions
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu * Sun vendor specific ATA SMART data, and start stop cycle counter).
c03acfcad7780db4ddf763511a82026680b3b2c1ls *
c03acfcad7780db4ddf763511a82026680b3b2c1ls * Takes a sata_drive_info t * and the address of a buffer
c03acfcad7780db4ddf763511a82026680b3b2c1ls * in which to create the page information.
c03acfcad7780db4ddf763511a82026680b3b2c1ls *
c03acfcad7780db4ddf763511a82026680b3b2c1ls * Returns the number of bytes valid in the buffer.
c03acfcad7780db4ddf763511a82026680b3b2c1ls */
c03acfcad7780db4ddf763511a82026680b3b2c1lsstatic int
c03acfcad7780db4ddf763511a82026680b3b2c1lssata_build_lsense_page_0(sata_drive_info_t *sdinfo, uint8_t *buf)
c03acfcad7780db4ddf763511a82026680b3b2c1ls{
c03acfcad7780db4ddf763511a82026680b3b2c1ls struct log_parameter *lpp = (struct log_parameter *)buf;
c03acfcad7780db4ddf763511a82026680b3b2c1ls uint8_t *page_ptr = (uint8_t *)lpp->param_values;
c03acfcad7780db4ddf763511a82026680b3b2c1ls int num_pages_supported = 1; /* Always have GET_SUPPORTED_LOG_PAGES */
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_id_t *sata_id = &sdinfo->satadrv_id;
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls lpp->param_code[0] = 0;
c03acfcad7780db4ddf763511a82026680b3b2c1ls lpp->param_code[1] = 0;
c03acfcad7780db4ddf763511a82026680b3b2c1ls lpp->param_ctrl_flags = LOG_CTRL_LP | LOG_CTRL_LBIN;
c03acfcad7780db4ddf763511a82026680b3b2c1ls *page_ptr++ = PAGE_CODE_GET_SUPPORTED_LOG_PAGES;
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls if (sata_id->ai_cmdset82 & SATA_SMART_SUPPORTED) {
c03acfcad7780db4ddf763511a82026680b3b2c1ls if (sata_id->ai_cmdset84 & SATA_SMART_SELF_TEST_SUPPORTED) {
c03acfcad7780db4ddf763511a82026680b3b2c1ls *page_ptr++ = PAGE_CODE_SELF_TEST_RESULTS;
c03acfcad7780db4ddf763511a82026680b3b2c1ls ++num_pages_supported;
c03acfcad7780db4ddf763511a82026680b3b2c1ls }
c03acfcad7780db4ddf763511a82026680b3b2c1ls *page_ptr++ = PAGE_CODE_INFORMATION_EXCEPTIONS;
c03acfcad7780db4ddf763511a82026680b3b2c1ls ++num_pages_supported;
c03acfcad7780db4ddf763511a82026680b3b2c1ls *page_ptr++ = PAGE_CODE_SMART_READ_DATA;
c03acfcad7780db4ddf763511a82026680b3b2c1ls ++num_pages_supported;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu *page_ptr++ = PAGE_CODE_START_STOP_CYCLE_COUNTER;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu ++num_pages_supported;
c03acfcad7780db4ddf763511a82026680b3b2c1ls }
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls lpp->param_len = num_pages_supported;
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls return ((&lpp->param_values[0] - (uint8_t *)lpp) +
c03acfcad7780db4ddf763511a82026680b3b2c1ls num_pages_supported);
c03acfcad7780db4ddf763511a82026680b3b2c1ls}
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls/*
c03acfcad7780db4ddf763511a82026680b3b2c1ls * sata_build_lsense_page_10() is used to create the
c03acfcad7780db4ddf763511a82026680b3b2c1ls * SCSI LOG SENSE page 0x10 (self-test results)
c03acfcad7780db4ddf763511a82026680b3b2c1ls *
c03acfcad7780db4ddf763511a82026680b3b2c1ls * Takes a sata_drive_info t * and the address of a buffer
c03acfcad7780db4ddf763511a82026680b3b2c1ls * in which to create the page information as well as a sata_hba_inst_t *.
c03acfcad7780db4ddf763511a82026680b3b2c1ls *
c03acfcad7780db4ddf763511a82026680b3b2c1ls * Returns the number of bytes valid in the buffer.
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik *
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik * Note: Self test and SMART data is accessible in device log pages.
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik * The log pages can be accessed by SMART READ/WRITE LOG (up to 255 sectors
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik * of data can be transferred by a single command), or by the General Purpose
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik * Logging commands (GPL) READ LOG EXT and WRITE LOG EXT (up to 65,535 sectors
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik * - approximately 33MB - can be transferred by a single command.
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik * The SCT Command response (either error or command) is the same for both
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik * the SMART and GPL methods of issuing commands.
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik * This function uses READ LOG EXT command when drive supports LBA48, and
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik * SMART READ command otherwise.
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik *
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik * Since above commands are executed in a synchronous mode, this function
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik * should not be called in an interrupt context.
c03acfcad7780db4ddf763511a82026680b3b2c1ls */
c03acfcad7780db4ddf763511a82026680b3b2c1lsstatic int
c03acfcad7780db4ddf763511a82026680b3b2c1lssata_build_lsense_page_10(
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_drive_info_t *sdinfo,
c03acfcad7780db4ddf763511a82026680b3b2c1ls uint8_t *buf,
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_hba_inst_t *sata_hba_inst)
c03acfcad7780db4ddf763511a82026680b3b2c1ls{
c03acfcad7780db4ddf763511a82026680b3b2c1ls struct log_parameter *lpp = (struct log_parameter *)buf;
c03acfcad7780db4ddf763511a82026680b3b2c1ls int rval;
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls if (sdinfo->satadrv_features_support & SATA_DEV_F_LBA48) {
c03acfcad7780db4ddf763511a82026680b3b2c1ls struct smart_ext_selftest_log *ext_selftest_log;
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls ext_selftest_log = kmem_zalloc(
c03acfcad7780db4ddf763511a82026680b3b2c1ls sizeof (struct smart_ext_selftest_log), KM_SLEEP);
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls rval = sata_ext_smart_selftest_read_log(sata_hba_inst, sdinfo,
c03acfcad7780db4ddf763511a82026680b3b2c1ls ext_selftest_log, 0);
c03acfcad7780db4ddf763511a82026680b3b2c1ls if (rval == 0) {
489f952b4388bd1ea1feff97164a4416e0c621eals int index, start_index;
c03acfcad7780db4ddf763511a82026680b3b2c1ls struct smart_ext_selftest_log_entry *entry;
489f952b4388bd1ea1feff97164a4416e0c621eals static const struct smart_ext_selftest_log_entry empty =
489f952b4388bd1ea1feff97164a4416e0c621eals {0};
c03acfcad7780db4ddf763511a82026680b3b2c1ls uint16_t block_num;
c03acfcad7780db4ddf763511a82026680b3b2c1ls int count;
489f952b4388bd1ea1feff97164a4416e0c621eals boolean_t only_one_block = B_FALSE;
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls index = ext_selftest_log->
c03acfcad7780db4ddf763511a82026680b3b2c1ls smart_ext_selftest_log_index[0];
c03acfcad7780db4ddf763511a82026680b3b2c1ls index |= ext_selftest_log->
c03acfcad7780db4ddf763511a82026680b3b2c1ls smart_ext_selftest_log_index[1] << 8;
c03acfcad7780db4ddf763511a82026680b3b2c1ls if (index == 0)
c03acfcad7780db4ddf763511a82026680b3b2c1ls goto out;
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls --index; /* Correct for 0 origin */
489f952b4388bd1ea1feff97164a4416e0c621eals start_index = index; /* remember where we started */
c03acfcad7780db4ddf763511a82026680b3b2c1ls block_num = index / ENTRIES_PER_EXT_SELFTEST_LOG_BLK;
c03acfcad7780db4ddf763511a82026680b3b2c1ls if (block_num != 0) {
c03acfcad7780db4ddf763511a82026680b3b2c1ls rval = sata_ext_smart_selftest_read_log(
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_hba_inst, sdinfo, ext_selftest_log,
c03acfcad7780db4ddf763511a82026680b3b2c1ls block_num);
c03acfcad7780db4ddf763511a82026680b3b2c1ls if (rval != 0)
c03acfcad7780db4ddf763511a82026680b3b2c1ls goto out;
c03acfcad7780db4ddf763511a82026680b3b2c1ls }
c03acfcad7780db4ddf763511a82026680b3b2c1ls index %= ENTRIES_PER_EXT_SELFTEST_LOG_BLK;
c03acfcad7780db4ddf763511a82026680b3b2c1ls entry =
c03acfcad7780db4ddf763511a82026680b3b2c1ls &ext_selftest_log->
c03acfcad7780db4ddf763511a82026680b3b2c1ls smart_ext_selftest_log_entries[index];
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls for (count = 1;
c03acfcad7780db4ddf763511a82026680b3b2c1ls count <= SCSI_ENTRIES_IN_LOG_SENSE_SELFTEST_RESULTS;
c03acfcad7780db4ddf763511a82026680b3b2c1ls ++count) {
c03acfcad7780db4ddf763511a82026680b3b2c1ls uint8_t status;
c03acfcad7780db4ddf763511a82026680b3b2c1ls uint8_t code;
c03acfcad7780db4ddf763511a82026680b3b2c1ls uint8_t sense_key;
c03acfcad7780db4ddf763511a82026680b3b2c1ls uint8_t add_sense_code;
c03acfcad7780db4ddf763511a82026680b3b2c1ls uint8_t add_sense_code_qual;
c03acfcad7780db4ddf763511a82026680b3b2c1ls
489f952b4388bd1ea1feff97164a4416e0c621eals /* If this is an unused entry, we are done */
489f952b4388bd1ea1feff97164a4416e0c621eals if (bcmp(entry, &empty, sizeof (empty)) == 0) {
489f952b4388bd1ea1feff97164a4416e0c621eals /* Broken firmware on some disks */
489f952b4388bd1ea1feff97164a4416e0c621eals if (index + 1 ==
489f952b4388bd1ea1feff97164a4416e0c621eals ENTRIES_PER_EXT_SELFTEST_LOG_BLK) {
489f952b4388bd1ea1feff97164a4416e0c621eals --entry;
489f952b4388bd1ea1feff97164a4416e0c621eals --index;
489f952b4388bd1ea1feff97164a4416e0c621eals if (bcmp(entry, &empty,
489f952b4388bd1ea1feff97164a4416e0c621eals sizeof (empty)) == 0)
489f952b4388bd1ea1feff97164a4416e0c621eals goto out;
489f952b4388bd1ea1feff97164a4416e0c621eals } else
489f952b4388bd1ea1feff97164a4416e0c621eals goto out;
489f952b4388bd1ea1feff97164a4416e0c621eals }
489f952b4388bd1ea1feff97164a4416e0c621eals
489f952b4388bd1ea1feff97164a4416e0c621eals if (only_one_block &&
489f952b4388bd1ea1feff97164a4416e0c621eals start_index == index)
489f952b4388bd1ea1feff97164a4416e0c621eals goto out;
489f952b4388bd1ea1feff97164a4416e0c621eals
c03acfcad7780db4ddf763511a82026680b3b2c1ls lpp->param_code[0] = 0;
c03acfcad7780db4ddf763511a82026680b3b2c1ls lpp->param_code[1] = count;
489f952b4388bd1ea1feff97164a4416e0c621eals lpp->param_ctrl_flags =
489f952b4388bd1ea1feff97164a4416e0c621eals LOG_CTRL_LP | LOG_CTRL_LBIN;
c03acfcad7780db4ddf763511a82026680b3b2c1ls lpp->param_len =
c03acfcad7780db4ddf763511a82026680b3b2c1ls SCSI_LOG_SENSE_SELFTEST_PARAM_LEN;
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls status = entry->smart_ext_selftest_log_status;
c03acfcad7780db4ddf763511a82026680b3b2c1ls status >>= 4;
c03acfcad7780db4ddf763511a82026680b3b2c1ls switch (status) {
c03acfcad7780db4ddf763511a82026680b3b2c1ls case 0:
c03acfcad7780db4ddf763511a82026680b3b2c1ls default:
c03acfcad7780db4ddf763511a82026680b3b2c1ls sense_key = KEY_NO_SENSE;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown add_sense_code =
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SD_SCSI_ASC_NO_ADD_SENSE;
c03acfcad7780db4ddf763511a82026680b3b2c1ls add_sense_code_qual = 0;
c03acfcad7780db4ddf763511a82026680b3b2c1ls break;
c03acfcad7780db4ddf763511a82026680b3b2c1ls case 1:
c03acfcad7780db4ddf763511a82026680b3b2c1ls sense_key = KEY_ABORTED_COMMAND;
c03acfcad7780db4ddf763511a82026680b3b2c1ls add_sense_code =
c03acfcad7780db4ddf763511a82026680b3b2c1ls DIAGNOSTIC_FAILURE_ON_COMPONENT;
c03acfcad7780db4ddf763511a82026680b3b2c1ls add_sense_code_qual = SCSI_COMPONENT_81;
c03acfcad7780db4ddf763511a82026680b3b2c1ls break;
c03acfcad7780db4ddf763511a82026680b3b2c1ls case 2:
c03acfcad7780db4ddf763511a82026680b3b2c1ls sense_key = KEY_ABORTED_COMMAND;
c03acfcad7780db4ddf763511a82026680b3b2c1ls add_sense_code =
c03acfcad7780db4ddf763511a82026680b3b2c1ls DIAGNOSTIC_FAILURE_ON_COMPONENT;
c03acfcad7780db4ddf763511a82026680b3b2c1ls add_sense_code_qual = SCSI_COMPONENT_82;
c03acfcad7780db4ddf763511a82026680b3b2c1ls break;
c03acfcad7780db4ddf763511a82026680b3b2c1ls case 3:
c03acfcad7780db4ddf763511a82026680b3b2c1ls sense_key = KEY_ABORTED_COMMAND;
c03acfcad7780db4ddf763511a82026680b3b2c1ls add_sense_code =
c03acfcad7780db4ddf763511a82026680b3b2c1ls DIAGNOSTIC_FAILURE_ON_COMPONENT;
c03acfcad7780db4ddf763511a82026680b3b2c1ls add_sense_code_qual = SCSI_COMPONENT_83;
c03acfcad7780db4ddf763511a82026680b3b2c1ls break;
c03acfcad7780db4ddf763511a82026680b3b2c1ls case 4:
c03acfcad7780db4ddf763511a82026680b3b2c1ls sense_key = KEY_HARDWARE_ERROR;
c03acfcad7780db4ddf763511a82026680b3b2c1ls add_sense_code =
c03acfcad7780db4ddf763511a82026680b3b2c1ls DIAGNOSTIC_FAILURE_ON_COMPONENT;
c03acfcad7780db4ddf763511a82026680b3b2c1ls add_sense_code_qual = SCSI_COMPONENT_84;
c03acfcad7780db4ddf763511a82026680b3b2c1ls break;
c03acfcad7780db4ddf763511a82026680b3b2c1ls case 5:
c03acfcad7780db4ddf763511a82026680b3b2c1ls sense_key = KEY_HARDWARE_ERROR;
c03acfcad7780db4ddf763511a82026680b3b2c1ls add_sense_code =
c03acfcad7780db4ddf763511a82026680b3b2c1ls DIAGNOSTIC_FAILURE_ON_COMPONENT;
c03acfcad7780db4ddf763511a82026680b3b2c1ls add_sense_code_qual = SCSI_COMPONENT_85;
c03acfcad7780db4ddf763511a82026680b3b2c1ls break;
c03acfcad7780db4ddf763511a82026680b3b2c1ls case 6:
c03acfcad7780db4ddf763511a82026680b3b2c1ls sense_key = KEY_HARDWARE_ERROR;
c03acfcad7780db4ddf763511a82026680b3b2c1ls add_sense_code =
c03acfcad7780db4ddf763511a82026680b3b2c1ls DIAGNOSTIC_FAILURE_ON_COMPONENT;
c03acfcad7780db4ddf763511a82026680b3b2c1ls add_sense_code_qual = SCSI_COMPONENT_86;
c03acfcad7780db4ddf763511a82026680b3b2c1ls break;
c03acfcad7780db4ddf763511a82026680b3b2c1ls case 7:
c03acfcad7780db4ddf763511a82026680b3b2c1ls sense_key = KEY_MEDIUM_ERROR;
c03acfcad7780db4ddf763511a82026680b3b2c1ls add_sense_code =
c03acfcad7780db4ddf763511a82026680b3b2c1ls DIAGNOSTIC_FAILURE_ON_COMPONENT;
c03acfcad7780db4ddf763511a82026680b3b2c1ls add_sense_code_qual = SCSI_COMPONENT_87;
c03acfcad7780db4ddf763511a82026680b3b2c1ls break;
c03acfcad7780db4ddf763511a82026680b3b2c1ls case 8:
c03acfcad7780db4ddf763511a82026680b3b2c1ls sense_key = KEY_HARDWARE_ERROR;
c03acfcad7780db4ddf763511a82026680b3b2c1ls add_sense_code =
c03acfcad7780db4ddf763511a82026680b3b2c1ls DIAGNOSTIC_FAILURE_ON_COMPONENT;
c03acfcad7780db4ddf763511a82026680b3b2c1ls add_sense_code_qual = SCSI_COMPONENT_88;
c03acfcad7780db4ddf763511a82026680b3b2c1ls break;
c03acfcad7780db4ddf763511a82026680b3b2c1ls }
c03acfcad7780db4ddf763511a82026680b3b2c1ls code = 0; /* unspecified */
c03acfcad7780db4ddf763511a82026680b3b2c1ls status |= (code << 4);
c03acfcad7780db4ddf763511a82026680b3b2c1ls lpp->param_values[0] = status;
c03acfcad7780db4ddf763511a82026680b3b2c1ls lpp->param_values[1] = 0; /* unspecified */
c03acfcad7780db4ddf763511a82026680b3b2c1ls lpp->param_values[2] = entry->
c03acfcad7780db4ddf763511a82026680b3b2c1ls smart_ext_selftest_log_timestamp[1];
c03acfcad7780db4ddf763511a82026680b3b2c1ls lpp->param_values[3] = entry->
c03acfcad7780db4ddf763511a82026680b3b2c1ls smart_ext_selftest_log_timestamp[0];
489f952b4388bd1ea1feff97164a4416e0c621eals if (status != 0) {
489f952b4388bd1ea1feff97164a4416e0c621eals lpp->param_values[4] = 0;
489f952b4388bd1ea1feff97164a4416e0c621eals lpp->param_values[5] = 0;
489f952b4388bd1ea1feff97164a4416e0c621eals lpp->param_values[6] = entry->
489f952b4388bd1ea1feff97164a4416e0c621eals smart_ext_selftest_log_failing_lba
489f952b4388bd1ea1feff97164a4416e0c621eals [5];
489f952b4388bd1ea1feff97164a4416e0c621eals lpp->param_values[7] = entry->
489f952b4388bd1ea1feff97164a4416e0c621eals smart_ext_selftest_log_failing_lba
489f952b4388bd1ea1feff97164a4416e0c621eals [4];
489f952b4388bd1ea1feff97164a4416e0c621eals lpp->param_values[8] = entry->
489f952b4388bd1ea1feff97164a4416e0c621eals smart_ext_selftest_log_failing_lba
489f952b4388bd1ea1feff97164a4416e0c621eals [3];
489f952b4388bd1ea1feff97164a4416e0c621eals lpp->param_values[9] = entry->
489f952b4388bd1ea1feff97164a4416e0c621eals smart_ext_selftest_log_failing_lba
489f952b4388bd1ea1feff97164a4416e0c621eals [2];
489f952b4388bd1ea1feff97164a4416e0c621eals lpp->param_values[10] = entry->
489f952b4388bd1ea1feff97164a4416e0c621eals smart_ext_selftest_log_failing_lba
489f952b4388bd1ea1feff97164a4416e0c621eals [1];
489f952b4388bd1ea1feff97164a4416e0c621eals lpp->param_values[11] = entry->
489f952b4388bd1ea1feff97164a4416e0c621eals smart_ext_selftest_log_failing_lba
489f952b4388bd1ea1feff97164a4416e0c621eals [0];
489f952b4388bd1ea1feff97164a4416e0c621eals } else { /* No bad block address */
489f952b4388bd1ea1feff97164a4416e0c621eals lpp->param_values[4] = 0xff;
489f952b4388bd1ea1feff97164a4416e0c621eals lpp->param_values[5] = 0xff;
489f952b4388bd1ea1feff97164a4416e0c621eals lpp->param_values[6] = 0xff;
489f952b4388bd1ea1feff97164a4416e0c621eals lpp->param_values[7] = 0xff;
489f952b4388bd1ea1feff97164a4416e0c621eals lpp->param_values[8] = 0xff;
489f952b4388bd1ea1feff97164a4416e0c621eals lpp->param_values[9] = 0xff;
489f952b4388bd1ea1feff97164a4416e0c621eals lpp->param_values[10] = 0xff;
489f952b4388bd1ea1feff97164a4416e0c621eals lpp->param_values[11] = 0xff;
489f952b4388bd1ea1feff97164a4416e0c621eals }
489f952b4388bd1ea1feff97164a4416e0c621eals
c03acfcad7780db4ddf763511a82026680b3b2c1ls lpp->param_values[12] = sense_key;
c03acfcad7780db4ddf763511a82026680b3b2c1ls lpp->param_values[13] = add_sense_code;
c03acfcad7780db4ddf763511a82026680b3b2c1ls lpp->param_values[14] = add_sense_code_qual;
c03acfcad7780db4ddf763511a82026680b3b2c1ls lpp->param_values[15] = 0; /* undefined */
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls lpp = (struct log_parameter *)
c03acfcad7780db4ddf763511a82026680b3b2c1ls (((uint8_t *)lpp) +
c03acfcad7780db4ddf763511a82026680b3b2c1ls SCSI_LOG_PARAM_HDR_LEN +
c03acfcad7780db4ddf763511a82026680b3b2c1ls SCSI_LOG_SENSE_SELFTEST_PARAM_LEN);
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls --index; /* Back up to previous entry */
c03acfcad7780db4ddf763511a82026680b3b2c1ls if (index < 0) {
c03acfcad7780db4ddf763511a82026680b3b2c1ls if (block_num > 0) {
c03acfcad7780db4ddf763511a82026680b3b2c1ls --block_num;
c03acfcad7780db4ddf763511a82026680b3b2c1ls } else {
c03acfcad7780db4ddf763511a82026680b3b2c1ls struct read_log_ext_directory
c03acfcad7780db4ddf763511a82026680b3b2c1ls logdir;
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls rval =
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_read_log_ext_directory(
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_hba_inst, sdinfo,
c03acfcad7780db4ddf763511a82026680b3b2c1ls &logdir);
c03acfcad7780db4ddf763511a82026680b3b2c1ls if (rval == -1)
c03acfcad7780db4ddf763511a82026680b3b2c1ls goto out;
c03acfcad7780db4ddf763511a82026680b3b2c1ls if ((logdir.read_log_ext_vers
c03acfcad7780db4ddf763511a82026680b3b2c1ls [0] == 0) &&
c03acfcad7780db4ddf763511a82026680b3b2c1ls (logdir.read_log_ext_vers
c03acfcad7780db4ddf763511a82026680b3b2c1ls [1] == 0))
c03acfcad7780db4ddf763511a82026680b3b2c1ls goto out;
c03acfcad7780db4ddf763511a82026680b3b2c1ls block_num =
489f952b4388bd1ea1feff97164a4416e0c621eals logdir.read_log_ext_nblks
c03acfcad7780db4ddf763511a82026680b3b2c1ls [EXT_SMART_SELFTEST_LOG_PAGE
489f952b4388bd1ea1feff97164a4416e0c621eals - 1][0];
c03acfcad7780db4ddf763511a82026680b3b2c1ls block_num |= logdir.
489f952b4388bd1ea1feff97164a4416e0c621eals read_log_ext_nblks
c03acfcad7780db4ddf763511a82026680b3b2c1ls [EXT_SMART_SELFTEST_LOG_PAGE
489f952b4388bd1ea1feff97164a4416e0c621eals - 1][1] << 8;
c03acfcad7780db4ddf763511a82026680b3b2c1ls --block_num;
489f952b4388bd1ea1feff97164a4416e0c621eals only_one_block =
489f952b4388bd1ea1feff97164a4416e0c621eals (block_num == 0);
c03acfcad7780db4ddf763511a82026680b3b2c1ls }
c03acfcad7780db4ddf763511a82026680b3b2c1ls rval = sata_ext_smart_selftest_read_log(
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_hba_inst, sdinfo,
c03acfcad7780db4ddf763511a82026680b3b2c1ls ext_selftest_log, block_num);
c03acfcad7780db4ddf763511a82026680b3b2c1ls if (rval != 0)
c03acfcad7780db4ddf763511a82026680b3b2c1ls goto out;
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls index =
c03acfcad7780db4ddf763511a82026680b3b2c1ls ENTRIES_PER_EXT_SELFTEST_LOG_BLK -
c03acfcad7780db4ddf763511a82026680b3b2c1ls 1;
c03acfcad7780db4ddf763511a82026680b3b2c1ls }
c03acfcad7780db4ddf763511a82026680b3b2c1ls index %= ENTRIES_PER_EXT_SELFTEST_LOG_BLK;
c03acfcad7780db4ddf763511a82026680b3b2c1ls entry = &ext_selftest_log->
c03acfcad7780db4ddf763511a82026680b3b2c1ls smart_ext_selftest_log_entries[index];
c03acfcad7780db4ddf763511a82026680b3b2c1ls }
c03acfcad7780db4ddf763511a82026680b3b2c1ls }
c03acfcad7780db4ddf763511a82026680b3b2c1lsout:
c03acfcad7780db4ddf763511a82026680b3b2c1ls kmem_free(ext_selftest_log,
c03acfcad7780db4ddf763511a82026680b3b2c1ls sizeof (struct smart_ext_selftest_log));
c03acfcad7780db4ddf763511a82026680b3b2c1ls } else {
c03acfcad7780db4ddf763511a82026680b3b2c1ls struct smart_selftest_log *selftest_log;
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls selftest_log = kmem_zalloc(sizeof (struct smart_selftest_log),
c03acfcad7780db4ddf763511a82026680b3b2c1ls KM_SLEEP);
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls rval = sata_smart_selftest_log(sata_hba_inst, sdinfo,
c03acfcad7780db4ddf763511a82026680b3b2c1ls selftest_log);
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls if (rval == 0) {
c03acfcad7780db4ddf763511a82026680b3b2c1ls int index;
c03acfcad7780db4ddf763511a82026680b3b2c1ls int count;
c03acfcad7780db4ddf763511a82026680b3b2c1ls struct smart_selftest_log_entry *entry;
489f952b4388bd1ea1feff97164a4416e0c621eals static const struct smart_selftest_log_entry empty =
489f952b4388bd1ea1feff97164a4416e0c621eals { 0 };
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls index = selftest_log->smart_selftest_log_index;
c03acfcad7780db4ddf763511a82026680b3b2c1ls if (index == 0)
c03acfcad7780db4ddf763511a82026680b3b2c1ls goto done;
c03acfcad7780db4ddf763511a82026680b3b2c1ls --index; /* Correct for 0 origin */
c03acfcad7780db4ddf763511a82026680b3b2c1ls entry = &selftest_log->
c03acfcad7780db4ddf763511a82026680b3b2c1ls smart_selftest_log_entries[index];
c03acfcad7780db4ddf763511a82026680b3b2c1ls for (count = 1;
c03acfcad7780db4ddf763511a82026680b3b2c1ls count <= SCSI_ENTRIES_IN_LOG_SENSE_SELFTEST_RESULTS;
c03acfcad7780db4ddf763511a82026680b3b2c1ls ++count) {
c03acfcad7780db4ddf763511a82026680b3b2c1ls uint8_t status;
c03acfcad7780db4ddf763511a82026680b3b2c1ls uint8_t code;
c03acfcad7780db4ddf763511a82026680b3b2c1ls uint8_t sense_key;
c03acfcad7780db4ddf763511a82026680b3b2c1ls uint8_t add_sense_code;
c03acfcad7780db4ddf763511a82026680b3b2c1ls uint8_t add_sense_code_qual;
c03acfcad7780db4ddf763511a82026680b3b2c1ls
489f952b4388bd1ea1feff97164a4416e0c621eals if (bcmp(entry, &empty, sizeof (empty)) == 0)
489f952b4388bd1ea1feff97164a4416e0c621eals goto done;
489f952b4388bd1ea1feff97164a4416e0c621eals
c03acfcad7780db4ddf763511a82026680b3b2c1ls lpp->param_code[0] = 0;
c03acfcad7780db4ddf763511a82026680b3b2c1ls lpp->param_code[1] = count;
489f952b4388bd1ea1feff97164a4416e0c621eals lpp->param_ctrl_flags =
489f952b4388bd1ea1feff97164a4416e0c621eals LOG_CTRL_LP | LOG_CTRL_LBIN;
c03acfcad7780db4ddf763511a82026680b3b2c1ls lpp->param_len =
c03acfcad7780db4ddf763511a82026680b3b2c1ls SCSI_LOG_SENSE_SELFTEST_PARAM_LEN;
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls status = entry->smart_selftest_log_status;
c03acfcad7780db4ddf763511a82026680b3b2c1ls status >>= 4;
c03acfcad7780db4ddf763511a82026680b3b2c1ls switch (status) {
c03acfcad7780db4ddf763511a82026680b3b2c1ls case 0:
c03acfcad7780db4ddf763511a82026680b3b2c1ls default:
c03acfcad7780db4ddf763511a82026680b3b2c1ls sense_key = KEY_NO_SENSE;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown add_sense_code =
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SD_SCSI_ASC_NO_ADD_SENSE;
c03acfcad7780db4ddf763511a82026680b3b2c1ls break;
c03acfcad7780db4ddf763511a82026680b3b2c1ls case 1:
c03acfcad7780db4ddf763511a82026680b3b2c1ls sense_key = KEY_ABORTED_COMMAND;
c03acfcad7780db4ddf763511a82026680b3b2c1ls add_sense_code =
c03acfcad7780db4ddf763511a82026680b3b2c1ls DIAGNOSTIC_FAILURE_ON_COMPONENT;
c03acfcad7780db4ddf763511a82026680b3b2c1ls add_sense_code_qual = SCSI_COMPONENT_81;
c03acfcad7780db4ddf763511a82026680b3b2c1ls break;
c03acfcad7780db4ddf763511a82026680b3b2c1ls case 2:
c03acfcad7780db4ddf763511a82026680b3b2c1ls sense_key = KEY_ABORTED_COMMAND;
c03acfcad7780db4ddf763511a82026680b3b2c1ls add_sense_code =
c03acfcad7780db4ddf763511a82026680b3b2c1ls DIAGNOSTIC_FAILURE_ON_COMPONENT;
c03acfcad7780db4ddf763511a82026680b3b2c1ls add_sense_code_qual = SCSI_COMPONENT_82;
c03acfcad7780db4ddf763511a82026680b3b2c1ls break;
c03acfcad7780db4ddf763511a82026680b3b2c1ls case 3:
c03acfcad7780db4ddf763511a82026680b3b2c1ls sense_key = KEY_ABORTED_COMMAND;
c03acfcad7780db4ddf763511a82026680b3b2c1ls add_sense_code =
c03acfcad7780db4ddf763511a82026680b3b2c1ls DIAGNOSTIC_FAILURE_ON_COMPONENT;
c03acfcad7780db4ddf763511a82026680b3b2c1ls add_sense_code_qual = SCSI_COMPONENT_83;
c03acfcad7780db4ddf763511a82026680b3b2c1ls break;
c03acfcad7780db4ddf763511a82026680b3b2c1ls case 4:
c03acfcad7780db4ddf763511a82026680b3b2c1ls sense_key = KEY_HARDWARE_ERROR;
c03acfcad7780db4ddf763511a82026680b3b2c1ls add_sense_code =
c03acfcad7780db4ddf763511a82026680b3b2c1ls DIAGNOSTIC_FAILURE_ON_COMPONENT;
c03acfcad7780db4ddf763511a82026680b3b2c1ls add_sense_code_qual = SCSI_COMPONENT_84;
c03acfcad7780db4ddf763511a82026680b3b2c1ls break;
c03acfcad7780db4ddf763511a82026680b3b2c1ls case 5:
c03acfcad7780db4ddf763511a82026680b3b2c1ls sense_key = KEY_HARDWARE_ERROR;
c03acfcad7780db4ddf763511a82026680b3b2c1ls add_sense_code =
c03acfcad7780db4ddf763511a82026680b3b2c1ls DIAGNOSTIC_FAILURE_ON_COMPONENT;
c03acfcad7780db4ddf763511a82026680b3b2c1ls add_sense_code_qual = SCSI_COMPONENT_85;
c03acfcad7780db4ddf763511a82026680b3b2c1ls break;
c03acfcad7780db4ddf763511a82026680b3b2c1ls case 6:
c03acfcad7780db4ddf763511a82026680b3b2c1ls sense_key = KEY_HARDWARE_ERROR;
c03acfcad7780db4ddf763511a82026680b3b2c1ls add_sense_code =
c03acfcad7780db4ddf763511a82026680b3b2c1ls DIAGNOSTIC_FAILURE_ON_COMPONENT;
c03acfcad7780db4ddf763511a82026680b3b2c1ls add_sense_code_qual = SCSI_COMPONENT_86;
c03acfcad7780db4ddf763511a82026680b3b2c1ls break;
c03acfcad7780db4ddf763511a82026680b3b2c1ls case 7:
c03acfcad7780db4ddf763511a82026680b3b2c1ls sense_key = KEY_MEDIUM_ERROR;
c03acfcad7780db4ddf763511a82026680b3b2c1ls add_sense_code =
c03acfcad7780db4ddf763511a82026680b3b2c1ls DIAGNOSTIC_FAILURE_ON_COMPONENT;
c03acfcad7780db4ddf763511a82026680b3b2c1ls add_sense_code_qual = SCSI_COMPONENT_87;
c03acfcad7780db4ddf763511a82026680b3b2c1ls break;
c03acfcad7780db4ddf763511a82026680b3b2c1ls case 8:
c03acfcad7780db4ddf763511a82026680b3b2c1ls sense_key = KEY_HARDWARE_ERROR;
c03acfcad7780db4ddf763511a82026680b3b2c1ls add_sense_code =
c03acfcad7780db4ddf763511a82026680b3b2c1ls DIAGNOSTIC_FAILURE_ON_COMPONENT;
c03acfcad7780db4ddf763511a82026680b3b2c1ls add_sense_code_qual = SCSI_COMPONENT_88;
c03acfcad7780db4ddf763511a82026680b3b2c1ls break;
c03acfcad7780db4ddf763511a82026680b3b2c1ls }
c03acfcad7780db4ddf763511a82026680b3b2c1ls code = 0; /* unspecified */
c03acfcad7780db4ddf763511a82026680b3b2c1ls status |= (code << 4);
c03acfcad7780db4ddf763511a82026680b3b2c1ls lpp->param_values[0] = status;
c03acfcad7780db4ddf763511a82026680b3b2c1ls lpp->param_values[1] = 0; /* unspecified */
c03acfcad7780db4ddf763511a82026680b3b2c1ls lpp->param_values[2] = entry->
c03acfcad7780db4ddf763511a82026680b3b2c1ls smart_selftest_log_timestamp[1];
c03acfcad7780db4ddf763511a82026680b3b2c1ls lpp->param_values[3] = entry->
c03acfcad7780db4ddf763511a82026680b3b2c1ls smart_selftest_log_timestamp[0];
489f952b4388bd1ea1feff97164a4416e0c621eals if (status != 0) {
489f952b4388bd1ea1feff97164a4416e0c621eals lpp->param_values[4] = 0;
489f952b4388bd1ea1feff97164a4416e0c621eals lpp->param_values[5] = 0;
489f952b4388bd1ea1feff97164a4416e0c621eals lpp->param_values[6] = 0;
489f952b4388bd1ea1feff97164a4416e0c621eals lpp->param_values[7] = 0;
489f952b4388bd1ea1feff97164a4416e0c621eals lpp->param_values[8] = entry->
489f952b4388bd1ea1feff97164a4416e0c621eals smart_selftest_log_failing_lba[3];
489f952b4388bd1ea1feff97164a4416e0c621eals lpp->param_values[9] = entry->
489f952b4388bd1ea1feff97164a4416e0c621eals smart_selftest_log_failing_lba[2];
489f952b4388bd1ea1feff97164a4416e0c621eals lpp->param_values[10] = entry->
489f952b4388bd1ea1feff97164a4416e0c621eals smart_selftest_log_failing_lba[1];
489f952b4388bd1ea1feff97164a4416e0c621eals lpp->param_values[11] = entry->
489f952b4388bd1ea1feff97164a4416e0c621eals smart_selftest_log_failing_lba[0];
489f952b4388bd1ea1feff97164a4416e0c621eals } else { /* No block address */
489f952b4388bd1ea1feff97164a4416e0c621eals lpp->param_values[4] = 0xff;
489f952b4388bd1ea1feff97164a4416e0c621eals lpp->param_values[5] = 0xff;
489f952b4388bd1ea1feff97164a4416e0c621eals lpp->param_values[6] = 0xff;
489f952b4388bd1ea1feff97164a4416e0c621eals lpp->param_values[7] = 0xff;
489f952b4388bd1ea1feff97164a4416e0c621eals lpp->param_values[8] = 0xff;
489f952b4388bd1ea1feff97164a4416e0c621eals lpp->param_values[9] = 0xff;
489f952b4388bd1ea1feff97164a4416e0c621eals lpp->param_values[10] = 0xff;
489f952b4388bd1ea1feff97164a4416e0c621eals lpp->param_values[11] = 0xff;
489f952b4388bd1ea1feff97164a4416e0c621eals }
c03acfcad7780db4ddf763511a82026680b3b2c1ls lpp->param_values[12] = sense_key;
c03acfcad7780db4ddf763511a82026680b3b2c1ls lpp->param_values[13] = add_sense_code;
c03acfcad7780db4ddf763511a82026680b3b2c1ls lpp->param_values[14] = add_sense_code_qual;
c03acfcad7780db4ddf763511a82026680b3b2c1ls lpp->param_values[15] = 0; /* undefined */
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls lpp = (struct log_parameter *)
c03acfcad7780db4ddf763511a82026680b3b2c1ls (((uint8_t *)lpp) +
c03acfcad7780db4ddf763511a82026680b3b2c1ls SCSI_LOG_PARAM_HDR_LEN +
c03acfcad7780db4ddf763511a82026680b3b2c1ls SCSI_LOG_SENSE_SELFTEST_PARAM_LEN);
c03acfcad7780db4ddf763511a82026680b3b2c1ls --index; /* back up to previous entry */
c03acfcad7780db4ddf763511a82026680b3b2c1ls if (index < 0) {
c03acfcad7780db4ddf763511a82026680b3b2c1ls index =
c03acfcad7780db4ddf763511a82026680b3b2c1ls NUM_SMART_SELFTEST_LOG_ENTRIES - 1;
c03acfcad7780db4ddf763511a82026680b3b2c1ls }
c03acfcad7780db4ddf763511a82026680b3b2c1ls entry = &selftest_log->
184cd04c26b064536977dfbb913a1240eaf6f708cth smart_selftest_log_entries[index];
c03acfcad7780db4ddf763511a82026680b3b2c1ls }
c03acfcad7780db4ddf763511a82026680b3b2c1ls }
c03acfcad7780db4ddf763511a82026680b3b2c1lsdone:
c03acfcad7780db4ddf763511a82026680b3b2c1ls kmem_free(selftest_log, sizeof (struct smart_selftest_log));
c03acfcad7780db4ddf763511a82026680b3b2c1ls }
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls return ((SCSI_LOG_PARAM_HDR_LEN + SCSI_LOG_SENSE_SELFTEST_PARAM_LEN) *
c03acfcad7780db4ddf763511a82026680b3b2c1ls SCSI_ENTRIES_IN_LOG_SENSE_SELFTEST_RESULTS);
c03acfcad7780db4ddf763511a82026680b3b2c1ls}
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls/*
c03acfcad7780db4ddf763511a82026680b3b2c1ls * sata_build_lsense_page_2f() is used to create the
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik * SCSI LOG SENSE page 0x2f (informational exceptions)
c03acfcad7780db4ddf763511a82026680b3b2c1ls *
c03acfcad7780db4ddf763511a82026680b3b2c1ls * Takes a sata_drive_info t * and the address of a buffer
c03acfcad7780db4ddf763511a82026680b3b2c1ls * in which to create the page information as well as a sata_hba_inst_t *.
c03acfcad7780db4ddf763511a82026680b3b2c1ls *
c03acfcad7780db4ddf763511a82026680b3b2c1ls * Returns the number of bytes valid in the buffer.
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik *
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik * Because it invokes function(s) that send synchronously executed command
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik * to the HBA, it cannot be called in the interrupt context.
c03acfcad7780db4ddf763511a82026680b3b2c1ls */
c03acfcad7780db4ddf763511a82026680b3b2c1lsstatic int
c03acfcad7780db4ddf763511a82026680b3b2c1lssata_build_lsense_page_2f(
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_drive_info_t *sdinfo,
c03acfcad7780db4ddf763511a82026680b3b2c1ls uint8_t *buf,
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_hba_inst_t *sata_hba_inst)
c03acfcad7780db4ddf763511a82026680b3b2c1ls{
c03acfcad7780db4ddf763511a82026680b3b2c1ls struct log_parameter *lpp = (struct log_parameter *)buf;
c03acfcad7780db4ddf763511a82026680b3b2c1ls int rval;
c03acfcad7780db4ddf763511a82026680b3b2c1ls uint8_t *smart_data;
c03acfcad7780db4ddf763511a82026680b3b2c1ls uint8_t temp;
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_id_t *sata_id;
c03acfcad7780db4ddf763511a82026680b3b2c1ls#define SMART_NO_TEMP 0xff
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls lpp->param_code[0] = 0;
c03acfcad7780db4ddf763511a82026680b3b2c1ls lpp->param_code[1] = 0;
c03acfcad7780db4ddf763511a82026680b3b2c1ls lpp->param_ctrl_flags = LOG_CTRL_LP | LOG_CTRL_LBIN;
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls /* Now get the SMART status w.r.t. threshold exceeded */
c03acfcad7780db4ddf763511a82026680b3b2c1ls rval = sata_fetch_smart_return_status(sata_hba_inst, sdinfo);
c03acfcad7780db4ddf763511a82026680b3b2c1ls switch (rval) {
c03acfcad7780db4ddf763511a82026680b3b2c1ls case 1:
c03acfcad7780db4ddf763511a82026680b3b2c1ls lpp->param_values[0] = SCSI_PREDICTED_FAILURE;
c03acfcad7780db4ddf763511a82026680b3b2c1ls lpp->param_values[1] = SCSI_GENERAL_HD_FAILURE;
c03acfcad7780db4ddf763511a82026680b3b2c1ls break;
c03acfcad7780db4ddf763511a82026680b3b2c1ls case 0:
c03acfcad7780db4ddf763511a82026680b3b2c1ls case -1: /* failed to get data */
489f952b4388bd1ea1feff97164a4416e0c621eals lpp->param_values[0] = 0; /* No failure predicted */
c03acfcad7780db4ddf763511a82026680b3b2c1ls lpp->param_values[1] = 0;
c03acfcad7780db4ddf763511a82026680b3b2c1ls break;
c03acfcad7780db4ddf763511a82026680b3b2c1ls#if defined(SATA_DEBUG)
c03acfcad7780db4ddf763511a82026680b3b2c1ls default:
c03acfcad7780db4ddf763511a82026680b3b2c1ls cmn_err(CE_PANIC, "sata_build_lsense_page_2f bad return value");
c03acfcad7780db4ddf763511a82026680b3b2c1ls /* NOTREACHED */
c03acfcad7780db4ddf763511a82026680b3b2c1ls#endif
c03acfcad7780db4ddf763511a82026680b3b2c1ls }
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_id = &sdinfo->satadrv_id;
c03acfcad7780db4ddf763511a82026680b3b2c1ls if (! (sata_id->ai_sctsupport & SATA_SCT_CMD_TRANS_SUP))
c03acfcad7780db4ddf763511a82026680b3b2c1ls temp = SMART_NO_TEMP;
c03acfcad7780db4ddf763511a82026680b3b2c1ls else {
c03acfcad7780db4ddf763511a82026680b3b2c1ls /* Now get the temperature */
c03acfcad7780db4ddf763511a82026680b3b2c1ls smart_data = kmem_zalloc(512, KM_SLEEP);
c03acfcad7780db4ddf763511a82026680b3b2c1ls rval = sata_smart_read_log(sata_hba_inst, sdinfo, smart_data,
c03acfcad7780db4ddf763511a82026680b3b2c1ls SCT_STATUS_LOG_PAGE, 1);
c03acfcad7780db4ddf763511a82026680b3b2c1ls if (rval == -1)
c03acfcad7780db4ddf763511a82026680b3b2c1ls temp = SMART_NO_TEMP;
c03acfcad7780db4ddf763511a82026680b3b2c1ls else {
c03acfcad7780db4ddf763511a82026680b3b2c1ls temp = smart_data[200];
c03acfcad7780db4ddf763511a82026680b3b2c1ls if (temp & 0x80) {
c03acfcad7780db4ddf763511a82026680b3b2c1ls if (temp & 0x7f)
c03acfcad7780db4ddf763511a82026680b3b2c1ls temp = 0;
c03acfcad7780db4ddf763511a82026680b3b2c1ls else
c03acfcad7780db4ddf763511a82026680b3b2c1ls temp = SMART_NO_TEMP;
c03acfcad7780db4ddf763511a82026680b3b2c1ls }
c03acfcad7780db4ddf763511a82026680b3b2c1ls }
c03acfcad7780db4ddf763511a82026680b3b2c1ls kmem_free(smart_data, 512);
c03acfcad7780db4ddf763511a82026680b3b2c1ls }
c03acfcad7780db4ddf763511a82026680b3b2c1ls
489f952b4388bd1ea1feff97164a4416e0c621eals lpp->param_values[2] = temp; /* most recent temperature */
489f952b4388bd1ea1feff97164a4416e0c621eals lpp->param_values[3] = 0; /* required vendor specific byte */
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls lpp->param_len = SCSI_INFO_EXCEPTIONS_PARAM_LEN;
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls return (SCSI_INFO_EXCEPTIONS_PARAM_LEN + SCSI_LOG_PARAM_HDR_LEN);
c03acfcad7780db4ddf763511a82026680b3b2c1ls}
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls/*
c03acfcad7780db4ddf763511a82026680b3b2c1ls * sata_build_lsense_page_30() is used to create the
c03acfcad7780db4ddf763511a82026680b3b2c1ls * SCSI LOG SENSE page 0x30 (Sun's vendor specific page for ATA SMART data).
c03acfcad7780db4ddf763511a82026680b3b2c1ls *
c03acfcad7780db4ddf763511a82026680b3b2c1ls * Takes a sata_drive_info t * and the address of a buffer
c03acfcad7780db4ddf763511a82026680b3b2c1ls * in which to create the page information as well as a sata_hba_inst_t *.
c03acfcad7780db4ddf763511a82026680b3b2c1ls *
c03acfcad7780db4ddf763511a82026680b3b2c1ls * Returns the number of bytes valid in the buffer.
c03acfcad7780db4ddf763511a82026680b3b2c1ls */
c03acfcad7780db4ddf763511a82026680b3b2c1lsstatic int
c03acfcad7780db4ddf763511a82026680b3b2c1lssata_build_lsense_page_30(
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_drive_info_t *sdinfo,
c03acfcad7780db4ddf763511a82026680b3b2c1ls uint8_t *buf,
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_hba_inst_t *sata_hba_inst)
c03acfcad7780db4ddf763511a82026680b3b2c1ls{
c03acfcad7780db4ddf763511a82026680b3b2c1ls struct smart_data *smart_data = (struct smart_data *)buf;
c03acfcad7780db4ddf763511a82026680b3b2c1ls int rval;
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls /* Now do the SMART READ DATA */
c03acfcad7780db4ddf763511a82026680b3b2c1ls rval = sata_fetch_smart_data(sata_hba_inst, sdinfo, smart_data);
c03acfcad7780db4ddf763511a82026680b3b2c1ls if (rval == -1)
c03acfcad7780db4ddf763511a82026680b3b2c1ls return (0);
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls return (sizeof (struct smart_data));
c03acfcad7780db4ddf763511a82026680b3b2c1ls}
c03acfcad7780db4ddf763511a82026680b3b2c1ls
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu/*
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu * sata_build_lsense_page_0e() is used to create the
a9d5ae2e08c504913c088349c3d4c144f3c92be8Pawel Wojcik * SCSI LOG SENSE page 0e (start-stop cycle counter page)
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu *
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu * Date of Manufacture (0x0001)
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu * YEAR = "0000"
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu * WEEK = "00"
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu * Accounting Date (0x0002)
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu * 6 ASCII space character(20h)
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu * Specified cycle count over device lifetime
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu * VALUE - THRESH - the delta between max and min;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu * Accumulated start-stop cycles
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu * VALUE - WORST - the accumulated cycles;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu *
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu * ID FLAG THRESH VALUE WORST RAW on start/stop counter attribute
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu *
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu * Takes a sata_drive_info t * and the address of a buffer
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu * in which to create the page information as well as a sata_hba_inst_t *.
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu *
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu * Returns the number of bytes valid in the buffer.
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu */
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chustatic int
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chusata_build_lsense_page_0e(sata_drive_info_t *sdinfo, uint8_t *buf,
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu sata_pkt_txlate_t *spx)
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu{
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu struct start_stop_cycle_counter_log *log_page;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu int i, rval, index;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu uint8_t smart_data[512], id, value, worst, thresh;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu uint32_t max_count, cycles;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu /* Now do the SMART READ DATA */
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu rval = sata_fetch_smart_data(spx->txlt_sata_hba_inst, sdinfo,
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu (struct smart_data *)smart_data);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if (rval == -1)
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu return (0);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu for (i = 0, id = 0; i < SMART_START_STOP_COUNT_ID * 2; i++) {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu index = (i * 12) + 2;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu id = smart_data[index];
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if (id != SMART_START_STOP_COUNT_ID)
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu continue;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu else {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu thresh = smart_data[index + 2];
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu value = smart_data[index + 3];
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu worst = smart_data[index + 4];
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu break;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu }
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu }
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if (id != SMART_START_STOP_COUNT_ID)
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu return (0);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu max_count = value - thresh;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu cycles = value - worst;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu log_page = (struct start_stop_cycle_counter_log *)buf;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu bzero(log_page, sizeof (struct start_stop_cycle_counter_log));
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu log_page->code = 0x0e;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu log_page->page_len_low = 0x24;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu log_page->manufactor_date_low = 0x1;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu log_page->param_1.fmt_link = 0x1; /* 01b */
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu log_page->param_len_1 = 0x06;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu for (i = 0; i < 4; i++) {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu log_page->year_manu[i] = 0x30;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if (i < 2)
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu log_page->week_manu[i] = 0x30;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu }
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu log_page->account_date_low = 0x02;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu log_page->param_2.fmt_link = 0x01; /* 01b */
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu log_page->param_len_2 = 0x06;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu for (i = 0; i < 4; i++) {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu log_page->year_account[i] = 0x20;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if (i < 2)
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu log_page->week_account[i] = 0x20;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu }
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu log_page->lifetime_code_low = 0x03;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu log_page->param_3.fmt_link = 0x03; /* 11b */
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu log_page->param_len_3 = 0x04;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu /* VALUE - THRESH - the delta between max and min */
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu log_page->cycle_code_low = 0x04;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu log_page->param_4.fmt_link = 0x03; /* 11b */
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu log_page->param_len_4 = 0x04;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu /* WORST - THRESH - the distance from 'now' to min */
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu for (i = 0; i < 4; i++) {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu log_page->cycle_lifetime[i] =
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu (max_count >> (8 * (3 - i))) & 0xff;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu log_page->cycle_accumulated[i] =
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu (cycles >> (8 * (3 - i))) & 0xff;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu }
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu return (sizeof (struct start_stop_cycle_counter_log));
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu}
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu/*
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu * This function was used for build a ATA read verify sector command
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu */
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chustatic void
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chusata_build_read_verify_cmd(sata_cmd_t *scmd, uint16_t sec, uint64_t lba)
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu{
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu scmd->satacmd_cmd_reg = SATAC_RDVER;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu scmd->satacmd_addr_type = ATA_ADDR_LBA28;
776955ed2c90dad066581c20700f1969e3c15f77Ada scmd->satacmd_flags.sata_special_regs = B_TRUE;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu scmd->satacmd_sec_count_lsb = sec & 0xff;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu scmd->satacmd_lba_low_lsb = lba & 0xff;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu scmd->satacmd_lba_mid_lsb = (lba >> 8) & 0xff;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu scmd->satacmd_lba_high_lsb = (lba >> 16) & 0xff;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu scmd->satacmd_device_reg = (SATA_ADH_LBA | (lba >> 24) & 0xf);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu scmd->satacmd_features_reg = 0;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu scmd->satacmd_status_reg = 0;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu scmd->satacmd_error_reg = 0;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu}
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu/*
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu * This function was used for building an ATA
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu * command, and only command register need to
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu * be defined, other register will be zero or na.
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu */
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chustatic void
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chusata_build_generic_cmd(sata_cmd_t *scmd, uint8_t cmd)
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu{
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu scmd->satacmd_addr_type = 0;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu scmd->satacmd_cmd_reg = cmd;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu scmd->satacmd_device_reg = 0;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu scmd->satacmd_sec_count_lsb = 0;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu scmd->satacmd_lba_low_lsb = 0;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu scmd->satacmd_lba_mid_lsb = 0;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu scmd->satacmd_lba_high_lsb = 0;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu scmd->satacmd_features_reg = 0;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu scmd->satacmd_status_reg = 0;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu scmd->satacmd_error_reg = 0;
776955ed2c90dad066581c20700f1969e3c15f77Ada scmd->satacmd_flags.sata_special_regs = B_TRUE;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu}
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu/*
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu * This function was used for changing the standby
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu * timer format from SCSI to ATA.
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu */
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chustatic uint8_t
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chusata_get_standby_timer(uint8_t *timer)
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu{
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu uint32_t i = 0, count = 0;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu uint8_t ata_count;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu for (i = 0; i < 4; i++) {
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu count = count << 8 | timer[i];
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu }
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if (count == 0)
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu return (0);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu if (count >= 1 && count <= 12000)
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu ata_count = (count -1) / 50 + 1;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu else if (count > 12000 && count <= 12600)
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu ata_count = 0xfc;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu else if (count > 12601 && count <= 12750)
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu ata_count = 0xff;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu else if (count > 12750 && count <= 17999)
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu ata_count = 0xf1;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu else if (count > 18000 && count <= 198000)
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu ata_count = count / 18000 + 240;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu else
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu ata_count = 0xfd;
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu return (ata_count);
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu}
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu
2038334ab26baaa43c9083f35def041511c3cc1fUnknown/* ************************** ATAPI-SPECIFIC FUNCTIONS ********************** */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Start command for ATAPI device.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * This function processes scsi_pkt requests.
f8a673ad9145b262edb65a98fb3fb92027d23a05ying tian - Beijing China * Now CD/DVD, tape and ATAPI disk devices are supported.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Most commands are packet without any translation into Packet Command.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Some may be trapped and executed as SATA commands (not clear which one).
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Returns TRAN_ACCEPT if command is accepted for execution (or completed
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * execution).
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Returns other TRAN_XXXX codes if command is not accepted or completed
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * (see return values for sata_hba_start()).
2038334ab26baaa43c9083f35def041511c3cc1fUnknown *
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Note:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Inquiry cdb format differs between transport version 2 and 3.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * However, the transport version 3 devices that were checked did not adhere
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * to the specification (ignored MSB of the allocation length). Therefore,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * the transport version is not checked, but Inquiry allocation length is
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * truncated to 255 bytes if the original allocation length set-up by the
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * target driver is greater than 255 bytes.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int
2038334ab26baaa43c9083f35def041511c3cc1fUnknownsata_txlt_atapi(sata_pkt_txlate_t *spx)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
2038334ab26baaa43c9083f35def041511c3cc1fUnknown struct scsi_pkt *scsipkt = spx->txlt_scsi_pkt;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_cmd_t *scmd = &spx->txlt_sata_pkt->satapkt_cmd;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown struct buf *bp = spx->txlt_sata_pkt->satapkt_cmd.satacmd_bp;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_hba_inst_t *sata_hba = SATA_TXLT_HBA_INST(spx);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_drive_info_t *sdinfo = sata_get_device_info(sata_hba,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown &spx->txlt_sata_pkt->satapkt_device);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown int cport = SATA_TXLT_CPORT(spx);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown int cdblen;
f39c049be37ba5b8f96704f41d6532332ae16318pawelw int rval, reason;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown int synch;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown union scsi_cdb *cdbp = (union scsi_cdb *)scsipkt->pkt_cdbp;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_enter(&(SATA_TXLT_CPORT_MUTEX(spx)));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
f39c049be37ba5b8f96704f41d6532332ae16318pawelw if (((rval = sata_txlt_generic_pkt_info(spx, &reason)) !=
f39c049be37ba5b8f96704f41d6532332ae16318pawelw TRAN_ACCEPT) || (reason == CMD_DEV_GONE)) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&(SATA_TXLT_CPORT_MUTEX(spx)));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (rval);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China * ATAPI device executes some ATA commands in addition to those
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China * commands sent via PACKET command. These ATA commands may be
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China * executed by the regular SATA translation functions. None needs
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China * to be captured now.
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China *
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China * Commands sent via PACKET command include:
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China * MMC command set for ATAPI CD/DVD device
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China * SSC command set for ATAPI TAPE device
f8a673ad9145b262edb65a98fb3fb92027d23a05ying tian - Beijing China * SBC command set for ATAPI disk device
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China *
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Check the size of cdb */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cdblen = scsi_cdb_size[GETGROUP(cdbp)];
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (cdblen > sdinfo->satadrv_atapi_cdb_len) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_log(NULL, CE_WARN,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "sata: invalid ATAPI cdb length %d",
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scsipkt->pkt_cdblen);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&(SATA_TXLT_CPORT_MUTEX(spx)));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (TRAN_BADPKT);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATAATAPITRACE(spx, cdblen);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * For non-read/write commands we need to
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * map buffer
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown switch ((uint_t)scsipkt->pkt_cdbp[0]) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown case SCMD_READ:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown case SCMD_READ_G1:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown case SCMD_READ_G5:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown case SCMD_READ_G4:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown case SCMD_WRITE:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown case SCMD_WRITE_G1:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown case SCMD_WRITE_G5:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown case SCMD_WRITE_G4:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown break;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown default:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (bp != NULL) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (bp->b_flags & (B_PHYS | B_PAGEIO))
2038334ab26baaa43c9083f35def041511c3cc1fUnknown bp_mapin(bp);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown break;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * scmd->satacmd_flags.sata_data_direction default -
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * SATA_DIR_NODATA_XFER - is set by
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * sata_txlt_generic_pkt_info().
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (scmd->satacmd_bp) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (scmd->satacmd_bp->b_flags & B_READ) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_flags.sata_data_direction = SATA_DIR_READ;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown } else {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_flags.sata_data_direction =
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_DIR_WRITE;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Set up ATAPI packet command.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_atapi_packet_cmd_setup(scmd, sdinfo);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Copy cdb into sata_cmd */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_acdb_len = sdinfo->satadrv_atapi_cdb_len;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown bzero(scmd->satacmd_acdb, SATA_ATAPI_MAX_CDB_LEN);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown bcopy(cdbp, scmd->satacmd_acdb, cdblen);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* See note in the command header */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (scmd->satacmd_acdb[0] == SCMD_INQUIRY) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (scmd->satacmd_acdb[3] != 0)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_acdb[4] = 255;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#ifdef SATA_DEBUG
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sata_debug_flags & SATA_DBG_ATAPI) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown uint8_t *p = scmd->satacmd_acdb;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown char buf[3 * SATA_ATAPI_MAX_CDB_LEN];
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (void) snprintf(buf, SATA_ATAPI_MAX_CDB_LEN,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "%02x %02x %02x %02x %02x %02x %02x %02x "
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "%2x %02x %02x %02x %02x %02x %02x %02x",
2038334ab26baaa43c9083f35def041511c3cc1fUnknown p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],
2038334ab26baaa43c9083f35def041511c3cc1fUnknown p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown buf[(3 * SATA_ATAPI_MAX_CDB_LEN) - 1] = '\0';
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cmn_err(CE_NOTE, "ATAPI cdb: %s\n", buf);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#endif
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Preset request sense data to NO SENSE.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * If there is no way to get error information via Request Sense,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * the packet request sense data would not have to be modified by HBA,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * but it could be returned as is.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown bzero(scmd->satacmd_rqsense, SATA_ATAPI_RQSENSE_LEN);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_fixed_sense_data_preset(
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (struct scsi_extended_sense *)scmd->satacmd_rqsense);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (!(spx->txlt_sata_pkt->satapkt_op_mode & SATA_OPMODE_SYNCH)) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Need callback function */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_sata_pkt->satapkt_comp = sata_txlt_atapi_completion;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown synch = FALSE;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown } else
2038334ab26baaa43c9083f35def041511c3cc1fUnknown synch = TRUE;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Transfer command to HBA */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sata_hba_start(spx, &rval) != 0) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Pkt not accepted for execution */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&SATA_CPORT_MUTEX(sata_hba, cport));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (rval);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&SATA_CPORT_MUTEX(sata_hba, cport));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * If execution is non-synchronous,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * a callback function will handle potential errors, translate
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * the response and will do a callback to a target driver.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * If it was synchronous, use the same framework callback to check
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * an execution status.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (synch) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATADBG1(SATA_DBG_SCSI_IF, spx->txlt_sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "synchronous execution status %x\n",
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_sata_pkt->satapkt_reason);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_txlt_atapi_completion(spx->txlt_sata_pkt);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (TRAN_ACCEPT);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown/*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * ATAPI Packet command completion.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown *
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Failure of the command passed via Packet command are considered device
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * error. SATA HBA driver would have to retrieve error data (via Request
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Sense command delivered via error retrieval sata packet) and copy it
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * to satacmd_rqsense array. From there, it is moved into scsi pkt sense data.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic void
2038334ab26baaa43c9083f35def041511c3cc1fUnknownsata_txlt_atapi_completion(sata_pkt_t *sata_pkt)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown{
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_pkt_txlate_t *spx =
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (sata_pkt_txlate_t *)sata_pkt->satapkt_framework_private;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown struct scsi_pkt *scsipkt = spx->txlt_scsi_pkt;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown struct scsi_extended_sense *sense;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown struct buf *bp;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown int rval;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown#ifdef SATA_DEBUG
2038334ab26baaa43c9083f35def041511c3cc1fUnknown uint8_t *rqsp = sata_pkt->satapkt_cmd.satacmd_rqsense;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown#endif
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scsipkt->pkt_state = STATE_GOT_BUS | STATE_GOT_TARGET |
2038334ab26baaa43c9083f35def041511c3cc1fUnknown STATE_SENT_CMD | STATE_GOT_STATUS;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sata_pkt->satapkt_reason == SATA_PKT_COMPLETED) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Normal completion */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sata_pkt->satapkt_cmd.satacmd_bp != NULL)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scsipkt->pkt_state |= STATE_XFERRED_DATA;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scsipkt->pkt_reason = CMD_CMPLT;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown *scsipkt->pkt_scbp = STATUS_GOOD;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (spx->txlt_tmp_buf != NULL) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Temporary buffer was used */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown bp = spx->txlt_sata_pkt->satapkt_cmd.satacmd_bp;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (bp->b_flags & B_READ) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rval = ddi_dma_sync(
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_buf_dma_handle, 0, 0,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown DDI_DMA_SYNC_FORCPU);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ASSERT(rval == DDI_SUCCESS);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown bcopy(spx->txlt_tmp_buf, bp->b_un.b_addr,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown bp->b_bcount);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown } else {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Something went wrong - analyze return
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown *scsipkt->pkt_scbp = STATUS_CHECK;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sense = sata_arq_sense(spx);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sata_pkt->satapkt_reason == SATA_PKT_DEV_ERROR) {
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China /*
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China * pkt_reason should be CMD_CMPLT for DEVICE ERROR.
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China * Under this condition ERR bit is set for ATA command,
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China * and CHK bit set for ATAPI command.
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China *
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China * Please check st_intr & sdintr about how pkt_reason
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China * is used.
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China */
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China scsipkt->pkt_reason = CMD_CMPLT;
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * We may not have ARQ data if there was a double
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * error. But sense data in sata packet was pre-set
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * with NO SENSE so it is valid even if HBA could
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * not retrieve a real sense data.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Just copy this sense data into scsi pkt sense area.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown bcopy(sata_pkt->satapkt_cmd.satacmd_rqsense, sense,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_ATAPI_MIN_RQSENSE_LEN);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown#ifdef SATA_DEBUG
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sata_debug_flags & SATA_DBG_SCSI_IF) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_log(spx->txlt_sata_hba_inst, CE_WARN,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "sata_txlt_atapi_completion: %02x\n"
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "RQSENSE: %02x %02x %02x %02x %02x %02x "
2038334ab26baaa43c9083f35def041511c3cc1fUnknown " %02x %02x %02x %02x %02x %02x "
2038334ab26baaa43c9083f35def041511c3cc1fUnknown " %02x %02x %02x %02x %02x %02x\n",
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scsipkt->pkt_reason,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rqsp[0], rqsp[1], rqsp[2], rqsp[3],
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rqsp[4], rqsp[5], rqsp[6], rqsp[7],
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rqsp[8], rqsp[9], rqsp[10], rqsp[11],
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rqsp[12], rqsp[13], rqsp[14], rqsp[15],
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rqsp[16], rqsp[17]);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown#endif
2038334ab26baaa43c9083f35def041511c3cc1fUnknown } else {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown switch (sata_pkt->satapkt_reason) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown case SATA_PKT_PORT_ERROR:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * We have no device data.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scsipkt->pkt_reason = CMD_INCOMPLETE;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scsipkt->pkt_state &= ~(STATE_GOT_BUS |
2038334ab26baaa43c9083f35def041511c3cc1fUnknown STATE_GOT_TARGET | STATE_SENT_CMD |
2038334ab26baaa43c9083f35def041511c3cc1fUnknown STATE_GOT_STATUS);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sense->es_key = KEY_HARDWARE_ERROR;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown break;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown case SATA_PKT_TIMEOUT:
ae8faf9c0cd738ab78a672de5bf7e7f7d004ebb2ls scsipkt->pkt_reason = CMD_TIMEOUT;
ae8faf9c0cd738ab78a672de5bf7e7f7d004ebb2ls scsipkt->pkt_statistics |=
ae8faf9c0cd738ab78a672de5bf7e7f7d004ebb2ls STAT_TIMEOUT | STAT_DEV_RESET;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Need to check if HARDWARE_ERROR/
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * TIMEOUT_ON_LOGICAL_UNIT 4/3E/2 would be more
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * appropriate.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown break;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown case SATA_PKT_ABORTED:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scsipkt->pkt_reason = CMD_ABORTED;
ae8faf9c0cd738ab78a672de5bf7e7f7d004ebb2ls scsipkt->pkt_statistics |= STAT_ABORTED;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Should we set key COMMAND_ABPRTED? */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown break;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown case SATA_PKT_RESET:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scsipkt->pkt_reason = CMD_RESET;
ae8faf9c0cd738ab78a672de5bf7e7f7d004ebb2ls scsipkt->pkt_statistics |= STAT_DEV_RESET;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * May be we should set Unit Attention /
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Reset. Perhaps the same should be
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * returned for disks....
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sense->es_key = KEY_UNIT_ATTENTION;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sense->es_add_code = SD_SCSI_ASC_RESET;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown break;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown default:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_LOG_D((spx->txlt_sata_hba_inst, CE_WARN,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "sata_txlt_atapi_completion: "
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "invalid packet completion reason"));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scsipkt->pkt_reason = CMD_TRAN_ERR;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scsipkt->pkt_state &= ~(STATE_GOT_BUS |
2038334ab26baaa43c9083f35def041511c3cc1fUnknown STATE_GOT_TARGET | STATE_SENT_CMD |
2038334ab26baaa43c9083f35def041511c3cc1fUnknown STATE_GOT_STATUS);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown break;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATAATAPITRACE(spx, 0);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if ((scsipkt->pkt_flags & FLAG_NOINTR) == 0 &&
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scsipkt->pkt_comp != NULL) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* scsi callback required */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (*scsipkt->pkt_comp)(scsipkt);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Set up error retrieval sata command for ATAPI Packet Command error data
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * recovery.
6ed1276fb5fe78fb1cce38682748a830ef8bd157pawelw *
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Returns SATA_SUCCESS when data buffer is allocated and packet set-up,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * returns SATA_FAILURE otherwise.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic int
2038334ab26baaa43c9083f35def041511c3cc1fUnknownsata_atapi_err_ret_cmd_setup(sata_pkt_txlate_t *spx, sata_drive_info_t *sdinfo)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_pkt_t *spkt = spx->txlt_sata_pkt;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_cmd_t *scmd;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown struct buf *bp;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Allocate dma-able buffer error data.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Buffer allocation will take care of buffer alignment and other DMA
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * attributes.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown bp = sata_alloc_local_buffer(spx, SATA_ATAPI_MIN_RQSENSE_LEN);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (bp == NULL) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATADBG1(SATA_DBG_ATAPI, spx->txlt_sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "sata_get_err_retrieval_pkt: "
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "cannot allocate buffer for error data", NULL);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (SATA_FAILURE);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown bp_mapin(bp); /* make data buffer accessible */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Operation modes are up to the caller */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_op_mode = SATA_OPMODE_SYNCH | SATA_OPMODE_INTERRUPTS;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Synchronous mode, no callback - may be changed by the caller */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_comp = NULL;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_time = sata_default_pkt_time;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd = &spkt->satapkt_cmd;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_flags.sata_data_direction = SATA_DIR_READ;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_flags.sata_ignore_dev_reset = B_TRUE;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_atapi_packet_cmd_setup(scmd, sdinfo);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Set-up acdb. Request Sense CDB (packet command content) is
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * not in DMA-able buffer. Its handling is HBA-specific (how
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * it is transfered into packet FIS).
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_acdb_len = sdinfo->satadrv_atapi_cdb_len;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown bcopy(sata_rqsense_cdb, scmd->satacmd_acdb, SATA_ATAPI_RQSENSE_CDB_LEN);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Following zeroing of pad bytes may not be necessary */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown bzero(&scmd->satacmd_acdb[SATA_ATAPI_RQSENSE_CDB_LEN],
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_atapi_cdb_len - SATA_ATAPI_RQSENSE_CDB_LEN);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Set-up pointer to the buffer handle, so HBA can sync buffer
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * before accessing it. Handle is in usual place in translate struct.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_err_ret_buf_handle = &spx->txlt_buf_dma_handle;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Preset request sense data to NO SENSE.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Here it is redundant, only for a symetry with scsi-originated
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * packets. It should not be used for anything but debugging.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown bzero(scmd->satacmd_rqsense, SATA_ATAPI_RQSENSE_LEN);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_fixed_sense_data_preset(
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (struct scsi_extended_sense *)scmd->satacmd_rqsense);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ASSERT(scmd->satacmd_num_dma_cookies != 0);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ASSERT(scmd->satacmd_dma_cookie_list != NULL);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (SATA_SUCCESS);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown}
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown/*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Set-up ATAPI packet command.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Data transfer direction has to be set-up in sata_cmd structure prior to
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * calling this function.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown *
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Returns void
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic void
2038334ab26baaa43c9083f35def041511c3cc1fUnknownsata_atapi_packet_cmd_setup(sata_cmd_t *scmd, sata_drive_info_t *sdinfo)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown{
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_addr_type = 0; /* N/A */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_sec_count_lsb = 0; /* no tag */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_lba_low_lsb = 0; /* N/A */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_lba_mid_lsb = (uint8_t)SATA_ATAPI_MAX_BYTES_PER_DRQ;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_lba_high_lsb =
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (uint8_t)(SATA_ATAPI_MAX_BYTES_PER_DRQ >> 8);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_cmd_reg = SATAC_PACKET; /* Command */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * We want all data to be transfered via DMA.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * But specify it only if drive supports DMA and DMA mode is
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * selected - some drives are sensitive about it.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Hopefully it wil work for all drives....
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sdinfo->satadrv_settings & SATA_DEV_DMA)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_features_reg = SATA_ATAPI_F_DMA;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Features register requires special care for devices that use
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Serial ATA bridge - they need an explicit specification of
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * the data transfer direction for Packet DMA commands.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Setting this bit is harmless if DMA is not used.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown *
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Many drives do not implement word 80, specifying what ATA/ATAPI
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * spec they follow.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * We are arbitrarily following the latest SerialATA 2.6 spec,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * which uses ATA/ATAPI 6 specification for Identify Data, unless
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * ATA/ATAPI-7 support is explicitly indicated.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sdinfo->satadrv_id.ai_majorversion != 0 &&
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_id.ai_majorversion != 0xffff &&
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (sdinfo->satadrv_id.ai_majorversion & SATA_MAJVER_7) != 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Specification of major version is valid and version 7
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * is supported. It does automatically imply that all
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * spec features are supported. For now, we assume that
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * DMADIR setting is valid. ATA/ATAPI7 spec is incomplete.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if ((sdinfo->satadrv_id.ai_dirdma &
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_ATAPI_ID_DMADIR_REQ) != 0) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (scmd->satacmd_flags.sata_data_direction ==
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_DIR_READ)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_features_reg |=
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_ATAPI_F_DATA_DIR_READ;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown#ifdef SATA_DEBUG
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown/* Display 18 bytes of Inquiry data */
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic void
2038334ab26baaa43c9083f35def041511c3cc1fUnknownsata_show_inqry_data(uint8_t *buf)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown{
2038334ab26baaa43c9083f35def041511c3cc1fUnknown struct scsi_inquiry *inq = (struct scsi_inquiry *)buf;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown uint8_t *p;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cmn_err(CE_NOTE, "Inquiry data:");
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cmn_err(CE_NOTE, "device type %x", inq->inq_dtype);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cmn_err(CE_NOTE, "removable media %x", inq->inq_rmb);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cmn_err(CE_NOTE, "version %x", inq->inq_ansi);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cmn_err(CE_NOTE, "ATAPI transport version %d",
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_ATAPI_TRANS_VERSION(inq));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cmn_err(CE_NOTE, "response data format %d, aenc %d",
2038334ab26baaa43c9083f35def041511c3cc1fUnknown inq->inq_rdf, inq->inq_aenc);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cmn_err(CE_NOTE, " additional length %d", inq->inq_len);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cmn_err(CE_NOTE, "tpgs %d", inq->inq_tpgs);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown p = (uint8_t *)inq->inq_vid;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cmn_err(CE_NOTE, "vendor id (binary): %02x %02x %02x %02x "
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "%02x %02x %02x %02x",
2038334ab26baaa43c9083f35def041511c3cc1fUnknown p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown p = (uint8_t *)inq->inq_vid;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cmn_err(CE_NOTE, "vendor id: %c %c %c %c %c %c %c %c",
2038334ab26baaa43c9083f35def041511c3cc1fUnknown p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown p = (uint8_t *)inq->inq_pid;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cmn_err(CE_NOTE, "product id (binary): %02x %02x %02x %02x "
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
2038334ab26baaa43c9083f35def041511c3cc1fUnknown p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],
2038334ab26baaa43c9083f35def041511c3cc1fUnknown p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown p = (uint8_t *)inq->inq_pid;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cmn_err(CE_NOTE, "product id: %c %c %c %c %c %c %c %c "
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "%c %c %c %c %c %c %c %c",
2038334ab26baaa43c9083f35def041511c3cc1fUnknown p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],
2038334ab26baaa43c9083f35def041511c3cc1fUnknown p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown p = (uint8_t *)inq->inq_revision;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cmn_err(CE_NOTE, "revision (binary): %02x %02x %02x %02x",
2038334ab26baaa43c9083f35def041511c3cc1fUnknown p[0], p[1], p[2], p[3]);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown p = (uint8_t *)inq->inq_revision;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cmn_err(CE_NOTE, "revision: %c %c %c %c",
2038334ab26baaa43c9083f35def041511c3cc1fUnknown p[0], p[1], p[2], p[3]);
6ed1276fb5fe78fb1cce38682748a830ef8bd157pawelw
2038334ab26baaa43c9083f35def041511c3cc1fUnknown}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
6ed1276fb5fe78fb1cce38682748a830ef8bd157pawelw
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic void
2038334ab26baaa43c9083f35def041511c3cc1fUnknownsata_save_atapi_trace(sata_pkt_txlate_t *spx, int count)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown{
2038334ab26baaa43c9083f35def041511c3cc1fUnknown struct scsi_pkt *scsi_pkt = spx->txlt_scsi_pkt;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (scsi_pkt == NULL)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (count != 0) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* saving cdb */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown bzero(sata_atapi_trace[sata_atapi_trace_index].acdb,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_ATAPI_MAX_CDB_LEN);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown bcopy(scsi_pkt->pkt_cdbp,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_atapi_trace[sata_atapi_trace_index].acdb, count);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown } else {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown bcopy(&((struct scsi_arq_status *)scsi_pkt->pkt_scbp)->
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sts_sensedata,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_atapi_trace[sata_atapi_trace_index].arqs,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_ATAPI_MIN_RQSENSE_LEN);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_atapi_trace[sata_atapi_trace_index].scsi_pkt_reason =
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scsi_pkt->pkt_reason;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_atapi_trace[sata_atapi_trace_index].sata_pkt_reason =
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_sata_pkt->satapkt_reason;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (++sata_atapi_trace_index >= 64)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_atapi_trace_index = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown}
6ed1276fb5fe78fb1cce38682748a830ef8bd157pawelw
2038334ab26baaa43c9083f35def041511c3cc1fUnknown#endif
6ed1276fb5fe78fb1cce38682748a830ef8bd157pawelw
2038334ab26baaa43c9083f35def041511c3cc1fUnknown/*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Fetch inquiry data from ATAPI device
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Returns SATA_SUCCESS if operation was successfull, SATA_FAILURE otherwise.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown *
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw * Note:
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw * inqb pointer does not point to a DMA-able buffer. It is a local buffer
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * where the caller expects to see the inquiry data.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown *
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
6ed1276fb5fe78fb1cce38682748a830ef8bd157pawelw
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic int
2038334ab26baaa43c9083f35def041511c3cc1fUnknownsata_get_atapi_inquiry_data(sata_hba_inst_t *sata_hba,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_address_t *saddr, struct scsi_inquiry *inq)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown{
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_pkt_txlate_t *spx;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_pkt_t *spkt;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown struct buf *bp;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_drive_info_t *sdinfo;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_cmd_t *scmd;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown int rval;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown uint8_t *rqsp;
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw#ifdef SATA_DEBUG
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw char msg_buf[MAXPATHLEN];
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw#endif
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ASSERT(sata_hba != NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx = kmem_zalloc(sizeof (sata_pkt_txlate_t), KM_SLEEP);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_sata_hba_inst = sata_hba;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_scsi_pkt = NULL; /* No scsi pkt involved */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt = sata_pkt_alloc(spx, NULL);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (spkt == NULL) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown kmem_free(spx, sizeof (sata_pkt_txlate_t));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (SATA_FAILURE);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* address is needed now */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_device.satadev_addr = *saddr;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* scsi_inquiry size buffer */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown bp = sata_alloc_local_buffer(spx, sizeof (struct scsi_inquiry));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (bp == NULL) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_pkt_free(spx);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown kmem_free(spx, sizeof (sata_pkt_txlate_t));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_LOG_D((sata_hba, CE_WARN,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "sata_get_atapi_inquiry_data: "
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "cannot allocate data buffer"));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (SATA_FAILURE);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown bp_mapin(bp); /* make data buffer accessible */
6ed1276fb5fe78fb1cce38682748a830ef8bd157pawelw
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd = &spkt->satapkt_cmd;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ASSERT(scmd->satacmd_num_dma_cookies != 0);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ASSERT(scmd->satacmd_dma_cookie_list != NULL);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Use synchronous mode */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_op_mode = SATA_OPMODE_SYNCH | SATA_OPMODE_INTERRUPTS;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_comp = NULL;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_time = sata_default_pkt_time;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Issue inquiry command - 6 bytes cdb, data transfer, read */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_flags.sata_data_direction = SATA_DIR_READ;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_flags.sata_ignore_dev_reset = B_TRUE;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_enter(&(SATA_TXLT_CPORT_MUTEX(spx)));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo = sata_get_device_info(sata_hba,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown &spx->txlt_sata_pkt->satapkt_device);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sdinfo == NULL) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* we have to be carefull about the disapearing device */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&(SATA_TXLT_CPORT_MUTEX(spx)));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rval = SATA_FAILURE;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown goto cleanup;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_atapi_packet_cmd_setup(scmd, sdinfo);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Set-up acdb. This works for atapi transport version 2 and later.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_acdb_len = sdinfo->satadrv_atapi_cdb_len;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown bzero(scmd->satacmd_acdb, SATA_ATAPI_MAX_CDB_LEN);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_acdb[0] = 0x12; /* Inquiry */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_acdb[1] = 0x00;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_acdb[2] = 0x00;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_acdb[3] = 0x00;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_acdb[4] = sizeof (struct scsi_inquiry);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_acdb[5] = 0x00;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_fixed_sense_data_preset(
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (struct scsi_extended_sense *)scmd->satacmd_rqsense);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Transfer command to HBA */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sata_hba_start(spx, &rval) != 0) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Pkt not accepted for execution */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATADBG1(SATA_DBG_ATAPI, sata_hba,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "sata_get_atapi_inquiry_data: "
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "Packet not accepted for execution - ret: %02x", rval);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&(SATA_TXLT_CPORT_MUTEX(spx)));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rval = SATA_FAILURE;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown goto cleanup;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&(SATA_TXLT_CPORT_MUTEX(spx)));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (spkt->satapkt_reason == SATA_PKT_COMPLETED) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATADBG1(SATA_DBG_ATAPI, sata_hba,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "sata_get_atapi_inquiry_data: "
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "Packet completed successfully - ret: %02x", rval);
b5fc475bca6525d8da80728128eefb7100aaf66bap if (spx->txlt_buf_dma_handle != NULL) {
b5fc475bca6525d8da80728128eefb7100aaf66bap /*
b5fc475bca6525d8da80728128eefb7100aaf66bap * Sync buffer. Handle is in usual place in translate
b5fc475bca6525d8da80728128eefb7100aaf66bap * struct.
b5fc475bca6525d8da80728128eefb7100aaf66bap */
b5fc475bca6525d8da80728128eefb7100aaf66bap rval = ddi_dma_sync(spx->txlt_buf_dma_handle, 0, 0,
b5fc475bca6525d8da80728128eefb7100aaf66bap DDI_DMA_SYNC_FORCPU);
b5fc475bca6525d8da80728128eefb7100aaf66bap ASSERT(rval == DDI_SUCCESS);
b5fc475bca6525d8da80728128eefb7100aaf66bap }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Normal completion - copy data into caller's buffer
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown bcopy(bp->b_un.b_addr, (uint8_t *)inq,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sizeof (struct scsi_inquiry));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown#ifdef SATA_DEBUG
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sata_debug_flags & SATA_DBG_ATAPI) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_show_inqry_data((uint8_t *)inq);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown#endif
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rval = SATA_SUCCESS;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown } else {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Something went wrong - analyze return - check rqsense data
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rval = SATA_FAILURE;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (spkt->satapkt_reason == SATA_PKT_DEV_ERROR) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * ARQ data hopefull show something other than NO SENSE
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rqsp = scmd->satacmd_rqsense;
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw#ifdef SATA_DEBUG
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw if (sata_debug_flags & SATA_DBG_ATAPI) {
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw msg_buf[0] = '\0';
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw (void) snprintf(msg_buf, MAXPATHLEN,
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw "ATAPI packet completion reason: %02x\n"
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw "RQSENSE: %02x %02x %02x %02x %02x %02x\n"
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw " %02x %02x %02x %02x %02x %02x\n"
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw " %02x %02x %02x %02x %02x %02x",
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw spkt->satapkt_reason,
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw rqsp[0], rqsp[1], rqsp[2], rqsp[3],
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw rqsp[4], rqsp[5], rqsp[6], rqsp[7],
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw rqsp[8], rqsp[9], rqsp[10], rqsp[11],
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw rqsp[12], rqsp[13], rqsp[14], rqsp[15],
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw rqsp[16], rqsp[17]);
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw sata_log(spx->txlt_sata_hba_inst, CE_WARN,
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw "%s", msg_buf);
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw }
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw#endif
2038334ab26baaa43c9083f35def041511c3cc1fUnknown } else {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown switch (spkt->satapkt_reason) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown case SATA_PKT_PORT_ERROR:
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw SATADBG1(SATA_DBG_ATAPI, sata_hba,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "sata_get_atapi_inquiry_data: "
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw "packet reason: port error", NULL);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown break;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown case SATA_PKT_TIMEOUT:
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw SATADBG1(SATA_DBG_ATAPI, sata_hba,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "sata_get_atapi_inquiry_data: "
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw "packet reason: timeout", NULL);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown break;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown case SATA_PKT_ABORTED:
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw SATADBG1(SATA_DBG_ATAPI, sata_hba,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "sata_get_atapi_inquiry_data: "
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw "packet reason: aborted", NULL);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown break;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown case SATA_PKT_RESET:
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw SATADBG1(SATA_DBG_ATAPI, sata_hba,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "sata_get_atapi_inquiry_data: "
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw "packet reason: reset\n", NULL);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown break;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown default:
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw SATADBG1(SATA_DBG_ATAPI, sata_hba,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "sata_get_atapi_inquiry_data: "
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "invalid packet reason: %02x\n",
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_reason);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
2038334ab26baaa43c9083f35def041511c3cc1fUnknowncleanup:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_free_local_buffer(spx);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_pkt_free(spx);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown kmem_free(spx, sizeof (sata_pkt_txlate_t));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (rval);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown#if 0
2038334ab26baaa43c9083f35def041511c3cc1fUnknown#ifdef SATA_DEBUG
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Test ATAPI packet command.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Single threaded test: send packet command in synch mode, process completion
6ed1276fb5fe78fb1cce38682748a830ef8bd157pawelw *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic void
2038334ab26baaa43c9083f35def041511c3cc1fUnknownsata_test_atapi_packet_command(sata_hba_inst_t *sata_hba_inst, int cport)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_pkt_txlate_t *spx;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_pkt_t *spkt;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown struct buf *bp;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_device_t sata_device;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_drive_info_t *sdinfo;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_cmd_t *scmd;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown int rval;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown uint8_t *rqsp;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ASSERT(sata_hba_inst != NULL);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_device.satadev_addr.cport = cport;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_device.satadev_addr.pmport = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_device.satadev_addr.qual = SATA_ADDR_DCPORT;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_device.satadev_rev = SATA_DEVICE_REV;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_enter(&SATA_CPORT_INFO(sata_hba_inst, cport)->cport_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo = sata_get_device_info(sata_hba_inst, &sata_device);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, cport)->cport_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sdinfo == NULL) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_log(sata_hba_inst, CE_WARN,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "sata_test_atapi_packet_command: "
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "no device info for cport %d",
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_device.satadev_addr.cport);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
6ed1276fb5fe78fb1cce38682748a830ef8bd157pawelw
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx = kmem_zalloc(sizeof (sata_pkt_txlate_t), KM_SLEEP);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_sata_hba_inst = sata_hba_inst;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_scsi_pkt = NULL; /* No scsi pkt involved */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt = sata_pkt_alloc(spx, NULL);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (spkt == NULL) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown kmem_free(spx, sizeof (sata_pkt_txlate_t));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* address is needed now */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_device.satadev_addr = sata_device.satadev_addr;
6ed1276fb5fe78fb1cce38682748a830ef8bd157pawelw
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* 1024k buffer */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown bp = sata_alloc_local_buffer(spx, 1024);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (bp == NULL) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_pkt_free(spx);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown kmem_free(spx, sizeof (sata_pkt_txlate_t));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_log(sata_hba_inst, CE_WARN,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "sata_test_atapi_packet_command: "
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "cannot allocate data buffer");
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown bp_mapin(bp); /* make data buffer accessible */
6ed1276fb5fe78fb1cce38682748a830ef8bd157pawelw
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd = &spkt->satapkt_cmd;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ASSERT(scmd->satacmd_num_dma_cookies != 0);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ASSERT(scmd->satacmd_dma_cookie_list != NULL);
6ed1276fb5fe78fb1cce38682748a830ef8bd157pawelw
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Use synchronous mode */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_op_mode = SATA_OPMODE_SYNCH | SATA_OPMODE_INTERRUPTS;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Synchronous mode, no callback - may be changed by the caller */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_comp = NULL;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_time = sata_default_pkt_time;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Issue inquiry command - 6 bytes cdb, data transfer, read */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_flags.sata_data_direction = SATA_DIR_READ;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_flags.sata_ignore_dev_reset = B_TRUE;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_atapi_packet_cmd_setup(scmd, sdinfo);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Set-up acdb. */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_acdb_len = sdinfo->satadrv_atapi_cdb_len;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown bzero(scmd->satacmd_acdb, SATA_ATAPI_MAX_CDB_LEN);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_acdb[0] = 0x12; /* Inquiry */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_acdb[1] = 0x00;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_acdb[2] = 0x00;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_acdb[3] = 0x00;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_acdb[4] = sizeof (struct scsi_inquiry);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_acdb[5] = 0x00;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_fixed_sense_data_preset(
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (struct scsi_extended_sense *)scmd->satacmd_rqsense);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Transfer command to HBA */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_enter(&SATA_CPORT_INFO(sata_hba_inst, cport)->cport_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sata_hba_start(spx, &rval) != 0) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Pkt not accepted for execution */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_log(sata_hba_inst, CE_WARN,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "sata_test_atapi_packet_command: "
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "Packet not accepted for execution - ret: %02x", rval);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(
2038334ab26baaa43c9083f35def041511c3cc1fUnknown &SATA_CPORT_INFO(sata_hba_inst, cport)->cport_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown goto cleanup;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, cport)->cport_mutex);
6ed1276fb5fe78fb1cce38682748a830ef8bd157pawelw
b5fc475bca6525d8da80728128eefb7100aaf66bap if (spx->txlt_buf_dma_handle != NULL) {
b5fc475bca6525d8da80728128eefb7100aaf66bap /*
b5fc475bca6525d8da80728128eefb7100aaf66bap * Sync buffer. Handle is in usual place in translate struct.
b5fc475bca6525d8da80728128eefb7100aaf66bap */
b5fc475bca6525d8da80728128eefb7100aaf66bap rval = ddi_dma_sync(spx->txlt_buf_dma_handle, 0, 0,
b5fc475bca6525d8da80728128eefb7100aaf66bap DDI_DMA_SYNC_FORCPU);
b5fc475bca6525d8da80728128eefb7100aaf66bap ASSERT(rval == DDI_SUCCESS);
b5fc475bca6525d8da80728128eefb7100aaf66bap }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (spkt->satapkt_reason == SATA_PKT_COMPLETED) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_log(sata_hba_inst, CE_WARN,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "sata_test_atapi_packet_command: "
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw "Packet completed successfully");
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Normal completion - show inquiry data
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_show_inqry_data((uint8_t *)bp->b_un.b_addr);
6ed1276fb5fe78fb1cce38682748a830ef8bd157pawelw } else {
6ed1276fb5fe78fb1cce38682748a830ef8bd157pawelw /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Something went wrong - analyze return - check rqsense data
6ed1276fb5fe78fb1cce38682748a830ef8bd157pawelw */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (spkt->satapkt_reason == SATA_PKT_DEV_ERROR) {
6ed1276fb5fe78fb1cce38682748a830ef8bd157pawelw /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * ARQ data hopefull show something other than NO SENSE
6ed1276fb5fe78fb1cce38682748a830ef8bd157pawelw */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rqsp = scmd->satacmd_rqsense;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_log(spx->txlt_sata_hba_inst, CE_WARN,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "ATAPI packet completion reason: %02x\n"
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "RQSENSE: %02x %02x %02x %02x %02x %02x "
2038334ab26baaa43c9083f35def041511c3cc1fUnknown " %02x %02x %02x %02x %02x %02x "
2038334ab26baaa43c9083f35def041511c3cc1fUnknown " %02x %02x %02x %02x %02x %02x\n",
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_reason,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rqsp[0], rqsp[1], rqsp[2], rqsp[3],
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rqsp[4], rqsp[5], rqsp[6], rqsp[7],
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rqsp[8], rqsp[9], rqsp[10], rqsp[11],
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rqsp[12], rqsp[13], rqsp[14], rqsp[15],
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rqsp[16], rqsp[17]);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown } else {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown switch (spkt->satapkt_reason) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown case SATA_PKT_PORT_ERROR:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_log(sata_hba_inst, CE_WARN,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "sata_test_atapi_packet_command: "
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "packet reason: port error\n");
2038334ab26baaa43c9083f35def041511c3cc1fUnknown break;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown case SATA_PKT_TIMEOUT:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_log(sata_hba_inst, CE_WARN,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "sata_test_atapi_packet_command: "
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "packet reason: timeout\n");
2038334ab26baaa43c9083f35def041511c3cc1fUnknown break;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown case SATA_PKT_ABORTED:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_log(sata_hba_inst, CE_WARN,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "sata_test_atapi_packet_command: "
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "packet reason: aborted\n");
2038334ab26baaa43c9083f35def041511c3cc1fUnknown break;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown case SATA_PKT_RESET:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_log(sata_hba_inst, CE_WARN,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "sata_test_atapi_packet_command: "
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "packet reason: reset\n");
2038334ab26baaa43c9083f35def041511c3cc1fUnknown break;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown default:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_log(sata_hba_inst, CE_WARN,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "sata_test_atapi_packet_command: "
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "invalid packet reason: %02x\n",
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_reason);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown break;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
6ed1276fb5fe78fb1cce38682748a830ef8bd157pawelw }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
2038334ab26baaa43c9083f35def041511c3cc1fUnknowncleanup:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_free_local_buffer(spx);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_pkt_free(spx);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown kmem_free(spx, sizeof (sata_pkt_txlate_t));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown#endif /* SATA_DEBUG */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown#endif /* 1 */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown/* ************************** LOCAL HELPER FUNCTIONS *********************** */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Validate sata_tran info
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * SATA_FAILURE returns if structure is inconsistent or structure revision
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * does not match one used by the framework.
4360436b3c604bc28d37be269ad152b4c38157c3pawelw *
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Returns SATA_SUCCESS if sata_hba_tran has matching revision and contains
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * required function pointers.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Returns SATA_FAILURE otherwise.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic int
2038334ab26baaa43c9083f35def041511c3cc1fUnknownsata_validate_sata_hba_tran(dev_info_t *dip, sata_hba_tran_t *sata_tran)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * SATA_TRAN_HBA_REV is the current (highest) revision number
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * of the SATA interface.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sata_tran->sata_tran_hba_rev > SATA_TRAN_HBA_REV) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_log(NULL, CE_WARN,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "sata: invalid sata_hba_tran version %d for driver %s",
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_tran->sata_tran_hba_rev, ddi_driver_name(dip));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (SATA_FAILURE);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (dip != sata_tran->sata_tran_hba_dip) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_LOG_D((NULL, CE_WARN,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "sata: inconsistent sata_tran_hba_dip "
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "%p / %p", sata_tran->sata_tran_hba_dip, dip));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (SATA_FAILURE);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sata_tran->sata_tran_probe_port == NULL ||
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_tran->sata_tran_start == NULL ||
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_tran->sata_tran_abort == NULL ||
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_tran->sata_tran_reset_dport == NULL ||
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_tran->sata_tran_hotplug_ops == NULL ||
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_tran->sata_tran_hotplug_ops->sata_tran_port_activate == NULL ||
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_tran->sata_tran_hotplug_ops->sata_tran_port_deactivate ==
2038334ab26baaa43c9083f35def041511c3cc1fUnknown NULL) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_LOG_D((NULL, CE_WARN, "sata: sata_hba_tran missing "
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "required functions"));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (SATA_SUCCESS);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown/*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Remove HBA instance from sata_hba_list.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic void
2038334ab26baaa43c9083f35def041511c3cc1fUnknownsata_remove_hba_instance(dev_info_t *dip)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown{
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_hba_inst_t *sata_hba_inst;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_enter(&sata_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown for (sata_hba_inst = sata_hba_list;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_hba_inst != (struct sata_hba_inst *)NULL;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_hba_inst = sata_hba_inst->satahba_next) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sata_hba_inst->satahba_dip == dip)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sata_hba_inst == (struct sata_hba_inst *)NULL) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown#ifdef SATA_DEBUG
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cmn_err(CE_WARN, "sata_remove_hba_instance: "
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "unknown HBA instance\n");
2038334ab26baaa43c9083f35def041511c3cc1fUnknown#endif
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ASSERT(FALSE);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sata_hba_inst == sata_hba_list) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_hba_list = sata_hba_inst->satahba_next;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sata_hba_list) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_hba_list->satahba_prev =
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (struct sata_hba_inst *)NULL;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sata_hba_inst == sata_hba_list_tail) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_hba_list_tail = NULL;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown } else if (sata_hba_inst == sata_hba_list_tail) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_hba_list_tail = sata_hba_inst->satahba_prev;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sata_hba_list_tail) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_hba_list_tail->satahba_next =
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (struct sata_hba_inst *)NULL;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown } else {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_hba_inst->satahba_prev->satahba_next =
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_hba_inst->satahba_next;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_hba_inst->satahba_next->satahba_prev =
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_hba_inst->satahba_prev;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&sata_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Probe all SATA ports of the specified HBA instance.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * The assumption is that there are no target and attachment point minor nodes
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * created by the boot subsystems, so we do not need to prune device tree.
6ed1276fb5fe78fb1cce38682748a830ef8bd157pawelw *
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * This function is called only from sata_hba_attach(). It does not have to
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * be protected by controller mutex, because the hba_attached flag is not set
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * yet and no one would be touching this HBA instance other than this thread.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Determines if port is active and what type of the device is attached
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * (if any). Allocates necessary structures for each port.
6ed1276fb5fe78fb1cce38682748a830ef8bd157pawelw *
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * An AP (Attachement Point) node is created for each SATA device port even
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * when there is no device attached.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic void
2038334ab26baaa43c9083f35def041511c3cc1fUnknownsata_probe_ports(sata_hba_inst_t *sata_hba_inst)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
2038334ab26baaa43c9083f35def041511c3cc1fUnknown dev_info_t *dip = SATA_DIP(sata_hba_inst);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang int ncport;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_cport_info_t *cportinfo;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_drive_info_t *drive;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_device_t sata_device;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown int rval;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown dev_t minor_number;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown char name[16];
2038334ab26baaa43c9083f35def041511c3cc1fUnknown clock_t start_time, cur_time;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Probe controller ports first, to find port status and
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * any port multiplier attached.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown for (ncport = 0; ncport < SATA_NUM_CPORTS(sata_hba_inst); ncport++) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* allocate cport structure */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cportinfo = kmem_zalloc(sizeof (sata_cport_info_t), KM_SLEEP);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ASSERT(cportinfo != NULL);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_init(&cportinfo->cport_mutex, NULL, MUTEX_DRIVER, NULL);
6ed1276fb5fe78fb1cce38682748a830ef8bd157pawelw
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_enter(&cportinfo->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cportinfo->cport_addr.cport = ncport;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cportinfo->cport_addr.pmport = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cportinfo->cport_addr.qual = SATA_ADDR_CPORT;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cportinfo->cport_state &= ~SATA_PORT_STATE_CLEAR_MASK;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cportinfo->cport_state |= SATA_STATE_PROBING;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_CPORT_INFO(sata_hba_inst, ncport) = cportinfo;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Regardless if a port is usable or not, create
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * an attachment point
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&cportinfo->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang minor_number = SATA_MAKE_AP_MINOR(ddi_get_instance(dip),
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang ncport, 0, SATA_ADDR_CPORT);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (void) sprintf(name, "%d", ncport);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (ddi_create_minor_node(dip, name, S_IFCHR,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown minor_number, DDI_NT_SATA_ATTACHMENT_POINT, 0) !=
2038334ab26baaa43c9083f35def041511c3cc1fUnknown DDI_SUCCESS) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_log(sata_hba_inst, CE_WARN, "sata_hba_attach: "
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "cannot create SATA attachment point for port %d",
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ncport);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Probe port */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown start_time = ddi_get_lbolt();
2038334ab26baaa43c9083f35def041511c3cc1fUnknown reprobe_cport:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_device.satadev_addr.cport = ncport;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_device.satadev_addr.pmport = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_device.satadev_addr.qual = SATA_ADDR_CPORT;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_device.satadev_rev = SATA_DEVICE_REV;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rval = (*SATA_PROBE_PORT_FUNC(sata_hba_inst))
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (dip, &sata_device);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_enter(&cportinfo->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cportinfo->cport_scr = sata_device.satadev_scr;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (rval != SATA_SUCCESS) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Something went wrong? Fail the port */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cportinfo->cport_state = SATA_PSTATE_FAILED;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&cportinfo->cport_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown continue;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cportinfo->cport_state &= ~SATA_STATE_PROBING;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cportinfo->cport_state |= SATA_STATE_PROBED;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cportinfo->cport_dev_type = sata_device.satadev_type;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cportinfo->cport_state |= SATA_STATE_READY;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (cportinfo->cport_dev_type == SATA_DTYPE_NONE) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&cportinfo->cport_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown continue;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (cportinfo->cport_dev_type != SATA_DTYPE_PMULT) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * There is some device attached.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Allocate device info structure
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (SATA_CPORTINFO_DRV_INFO(cportinfo) == NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&cportinfo->cport_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_CPORTINFO_DRV_INFO(cportinfo) =
2038334ab26baaa43c9083f35def041511c3cc1fUnknown kmem_zalloc(sizeof (sata_drive_info_t),
2038334ab26baaa43c9083f35def041511c3cc1fUnknown KM_SLEEP);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_enter(&cportinfo->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown drive = SATA_CPORTINFO_DRV_INFO(cportinfo);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown drive->satadrv_addr = cportinfo->cport_addr;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown drive->satadrv_addr.qual = SATA_ADDR_DCPORT;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown drive->satadrv_type = cportinfo->cport_dev_type;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown drive->satadrv_state = SATA_STATE_UNKNOWN;
b73432889acd6e0776a9b3e58e911c13c7667a31pawelw
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&cportinfo->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (sata_add_device(dip, sata_hba_inst, &sata_device) !=
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_SUCCESS) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Plugged device was not correctly identified.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Retry, within a SATA_DEV_IDENTIFY_TIMEOUT
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cur_time = ddi_get_lbolt();
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if ((cur_time - start_time) <
2038334ab26baaa43c9083f35def041511c3cc1fUnknown drv_usectohz(SATA_DEV_IDENTIFY_TIMEOUT)) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* sleep for a while */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown delay(drv_usectohz(
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw SATA_DEV_RETRY_DLY));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown goto reprobe_cport;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang } else { /* SATA_DTYPE_PMULT */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&cportinfo->cport_mutex);
6ed1276fb5fe78fb1cce38682748a830ef8bd157pawelw
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Allocate sata_pmult_info and sata_pmport_info */
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang if (sata_alloc_pmult(sata_hba_inst, &sata_device) !=
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang SATA_SUCCESS)
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang continue;
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Log the information of the port multiplier */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_show_pmult_info(sata_hba_inst, &sata_device);
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Probe its pmports */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_probe_pmports(sata_hba_inst, ncport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang}
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang/*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Probe all device ports behind a port multiplier.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang *
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * PMult-related structure should be allocated before by sata_alloc_pmult().
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang *
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * NOTE1: Only called from sata_probe_ports()
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * NOTE2: No mutex should be hold.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhangstatic void
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhangsata_probe_pmports(sata_hba_inst_t *sata_hba_inst, uint8_t ncport)
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang{
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang dev_info_t *dip = SATA_DIP(sata_hba_inst);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_pmult_info_t *pmultinfo = NULL;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_pmport_info_t *pmportinfo = NULL;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_drive_info_t *drive = NULL;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device_t sata_device;
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang clock_t start_time, cur_time;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang int npmport;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang int rval;
b73432889acd6e0776a9b3e58e911c13c7667a31pawelw
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmultinfo = SATA_PMULT_INFO(sata_hba_inst, ncport);
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Probe Port Multiplier ports */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang for (npmport = 0; npmport < pmultinfo->pmult_num_dev_ports; npmport++) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo = pmultinfo->pmult_dev_port[npmport];
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang start_time = ddi_get_lbolt();
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhangreprobe_pmport:
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device.satadev_addr.cport = ncport;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device.satadev_addr.pmport = npmport;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device.satadev_addr.qual = SATA_ADDR_PMPORT;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device.satadev_rev = SATA_DEVICE_REV;
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Let HBA driver probe it. */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang rval = (*SATA_PROBE_PORT_FUNC(sata_hba_inst))
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (dip, &sata_device);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&pmportinfo->pmport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo->pmport_scr = sata_device.satadev_scr;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (rval != SATA_SUCCESS) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown pmportinfo->pmport_state =
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_PSTATE_FAILED;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang continue;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo->pmport_state &= ~SATA_STATE_PROBING;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo->pmport_state |= SATA_STATE_PROBED;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo->pmport_dev_type = sata_device.satadev_type;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo->pmport_state |= SATA_STATE_READY;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (pmportinfo->pmport_dev_type ==
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_DTYPE_NONE) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATADBG2(SATA_DBG_PMULT, sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "no device found at port %d:%d", ncport, npmport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang continue;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Port multipliers cannot be chained */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang ASSERT(pmportinfo->pmport_dev_type != SATA_DTYPE_PMULT);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * There is something attached to Port
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Multiplier device port
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Allocate device info structure
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (pmportinfo->pmport_sata_drive == NULL) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo->pmport_sata_drive =
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang kmem_zalloc(sizeof (sata_drive_info_t), KM_SLEEP);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang drive = pmportinfo->pmport_sata_drive;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang drive->satadrv_addr.cport = pmportinfo->pmport_addr.cport;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang drive->satadrv_addr.pmport = npmport;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang drive->satadrv_addr.qual = SATA_ADDR_DPMPORT;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang drive->satadrv_type = pmportinfo-> pmport_dev_type;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang drive->satadrv_state = SATA_STATE_UNKNOWN;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang rval = sata_add_device(dip, sata_hba_inst, &sata_device);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (rval != SATA_SUCCESS) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Plugged device was not correctly identified.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Retry, within the SATA_DEV_IDENTIFY_TIMEOUT
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cur_time = ddi_get_lbolt();
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if ((cur_time - start_time) < drv_usectohz(
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_DEV_IDENTIFY_TIMEOUT)) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* sleep for a while */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang delay(drv_usectohz(SATA_DEV_RETRY_DLY));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang goto reprobe_pmport;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Add SATA device for specified HBA instance & port (SCSI target
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * device nodes).
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * This function is called (indirectly) only from sata_hba_attach().
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * A target node is created when there is a supported type device attached,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * but may be removed if it cannot be put online.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown *
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * This function cannot be called from an interrupt context.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown *
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Create target nodes for disk, CD/DVD, Tape and ATAPI disk devices
2038334ab26baaa43c9083f35def041511c3cc1fUnknown *
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Returns SATA_SUCCESS when port/device was fully processed, SATA_FAILURE when
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * device identification failed - adding a device could be retried.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic int
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhangsata_add_device(dev_info_t *pdip, sata_hba_inst_t *sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device_t *sata_device)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_cport_info_t *cportinfo;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_pmult_info_t *pminfo;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_pmport_info_t *pmportinfo;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown dev_info_t *cdip; /* child dip */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_address_t *saddr = &sata_device->satadev_addr;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang uint8_t cport, pmport;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown int rval;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cport = saddr->cport;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmport = saddr->pmport;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cportinfo = SATA_CPORT_INFO(sata_hba_inst, cport);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ASSERT(cportinfo->cport_dev_type != SATA_DTYPE_NONE);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Some device is attached to a controller port.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * We rely on controllers distinquishing between no-device,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * attached port multiplier and other kind of attached device.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * We need to get Identify Device data and determine
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * positively the dev type before trying to attach
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * the target driver.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device->satadev_rev = SATA_DEVICE_REV;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang switch (saddr->qual) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang case SATA_ADDR_CPORT:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Add a non-port-multiplier device at controller port.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang saddr->qual = SATA_ADDR_DCPORT;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang rval = sata_probe_device(sata_hba_inst, sata_device);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (rval != SATA_SUCCESS ||
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device->satadev_type == SATA_DTYPE_UNKNOWN)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (SATA_FAILURE);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_enter(&cportinfo->cport_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_show_drive_info(sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_CPORTINFO_DRV_INFO(cportinfo));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if ((sata_device->satadev_type & SATA_VALID_DEV_TYPE) == 0) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Could not determine device type or
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * a device is not supported.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Degrade this device to unknown.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cportinfo->cport_dev_type = SATA_DTYPE_UNKNOWN;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&cportinfo->cport_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (SATA_SUCCESS);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cportinfo->cport_dev_type = sata_device->satadev_type;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cportinfo->cport_tgtnode_clean = B_TRUE;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&cportinfo->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Initialize device to the desired state. Even if it
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * fails, the device will still attach but syslog
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * will show the warning.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sata_initialize_device(sata_hba_inst,
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik SATA_CPORTINFO_DRV_INFO(cportinfo)) != SATA_SUCCESS) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Retry */
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik rval = sata_initialize_device(sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_CPORTINFO_DRV_INFO(cportinfo));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik if (rval == SATA_RETRY)
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik sata_log(sata_hba_inst, CE_WARN,
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik "SATA device at port %d - "
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik "default device features could not be set."
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik " Device may not operate as expected.",
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cport);
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik }
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cdip = sata_create_target_node(pdip, sata_hba_inst, saddr);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (cdip == NULL) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Attaching target node failed.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * We retain sata_drive_info structure...
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (SATA_SUCCESS);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&cportinfo->cport_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (SATA_CPORTINFO_DRV_INFO(cportinfo))->
2038334ab26baaa43c9083f35def041511c3cc1fUnknown satadrv_state = SATA_STATE_READY;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&cportinfo->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang break;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang case SATA_ADDR_PMPORT:
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang saddr->qual = SATA_ADDR_DPMPORT;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&cportinfo->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* It must be a Port Multiplier at the controller port */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang ASSERT(cportinfo->cport_dev_type == SATA_DTYPE_PMULT);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
2038334ab26baaa43c9083f35def041511c3cc1fUnknown pminfo = SATA_CPORTINFO_PMULT_INFO(cportinfo);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo = pminfo->pmult_dev_port[saddr->pmport];
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&cportinfo->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang rval = sata_probe_device(sata_hba_inst, sata_device);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (rval != SATA_SUCCESS ||
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device->satadev_type == SATA_DTYPE_UNKNOWN) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (SATA_FAILURE);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&pmportinfo->pmport_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_show_drive_info(sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_PMPORTINFO_DRV_INFO(pmportinfo));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if ((sata_device->satadev_type & SATA_VALID_DEV_TYPE) == 0) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Could not determine device type.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Degrade this device to unknown.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown pmportinfo->pmport_dev_type = SATA_DTYPE_UNKNOWN;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&pmportinfo->pmport_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (SATA_SUCCESS);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo->pmport_dev_type = sata_device->satadev_type;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown pmportinfo->pmport_tgtnode_clean = B_TRUE;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&pmportinfo->pmport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Initialize device to the desired state.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Even if it fails, the device will still
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * attach but syslog will show the warning.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sata_initialize_device(sata_hba_inst,
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik pmportinfo->pmport_sata_drive) != SATA_SUCCESS) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Retry */
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik rval = sata_initialize_device(sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown pmportinfo->pmport_sata_drive);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik if (rval == SATA_RETRY)
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik sata_log(sata_hba_inst, CE_WARN,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "SATA device at port %d:%d - "
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik "default device features could not be set."
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik " Device may not operate as expected.",
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cport, pmport);
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cdip = sata_create_target_node(pdip, sata_hba_inst, saddr);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (cdip == NULL) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Attaching target node failed.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * We retain sata_drive_info structure...
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (SATA_SUCCESS);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&pmportinfo->pmport_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown pmportinfo->pmport_sata_drive->satadrv_state |=
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_STATE_READY;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang break;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang default:
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang return (SATA_FAILURE);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (SATA_SUCCESS);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang/*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Clean up target node at specific address.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang *
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * NOTE: No Mutex should be hold.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhangstatic int
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhangsata_offline_device(sata_hba_inst_t *sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device_t *sata_device, sata_drive_info_t *sdinfo)
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang{
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang uint8_t cport, pmport, qual;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang dev_info_t *tdip;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cport = sata_device->satadev_addr.cport;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmport = sata_device->satadev_addr.pmport;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang qual = sata_device->satadev_addr.qual;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (qual == SATA_ADDR_DCPORT) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_LOG_D((sata_hba_inst, CE_WARN,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "sata_hba_ioctl: disconnect device at port %d", cport));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang } else {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_LOG_D((sata_hba_inst, CE_WARN,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "sata_hba_ioctl: disconnect device at port %d:%d",
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cport, pmport));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* We are addressing attached device, not a port */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device->satadev_addr.qual =
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sdinfo->satadrv_addr.qual;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang tdip = sata_get_scsi_target_dip(SATA_DIP(sata_hba_inst),
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang &sata_device->satadev_addr);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (tdip != NULL && ndi_devi_offline(tdip,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang NDI_DEVI_REMOVE) != NDI_SUCCESS) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Problem :
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * The target node remained attached.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * This happens when the device file was open
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * or a node was waiting for resources.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Cannot do anything about it.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (qual == SATA_ADDR_DCPORT) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_LOG_D((sata_hba_inst, CE_WARN,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "sata_hba_ioctl: disconnect: could "
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "not unconfigure device before "
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "disconnecting the SATA port %d",
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cport));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang } else {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_LOG_D((sata_hba_inst, CE_WARN,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "sata_hba_ioctl: disconnect: could "
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "not unconfigure device before "
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "disconnecting the SATA port %d:%d",
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cport, pmport));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Set DEVICE REMOVED state in the target
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * node. It will prevent access to the device
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * even when a new device is attached, until
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * the old target node is released, removed and
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * recreated for a new device.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_set_device_removed(tdip);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Instruct event daemon to try the target
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * node cleanup later.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_set_target_node_cleanup(
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_hba_inst, &sata_device->satadev_addr);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang return (SATA_SUCCESS);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Create scsi target node for attached device, create node properties and
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * attach the node.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * The node could be removed if the device onlining fails.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * A dev_info_t pointer is returned if operation is successful, NULL is
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * returned otherwise.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic dev_info_t *
2038334ab26baaa43c9083f35def041511c3cc1fUnknownsata_create_target_node(dev_info_t *dip, sata_hba_inst_t *sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_address_t *sata_addr)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
2038334ab26baaa43c9083f35def041511c3cc1fUnknown dev_info_t *cdip = NULL;
6ed1276fb5fe78fb1cce38682748a830ef8bd157pawelw int rval;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown char *nname = NULL;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown char **compatible = NULL;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown int ncompatible;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown struct scsi_inquiry inq;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_device_t sata_device;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_drive_info_t *sdinfo;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown int target;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown int i;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_device.satadev_rev = SATA_DEVICE_REV;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_device.satadev_addr = *sata_addr;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_enter(&(SATA_CPORT_MUTEX(sata_hba_inst, sata_addr->cport)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo = sata_get_device_info(sata_hba_inst, &sata_device);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown target = SATA_TO_SCSI_TARGET(sata_addr->cport,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_addr->pmport, sata_addr->qual);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sdinfo == NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_addr->cport)));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_LOG_D((sata_hba_inst, CE_WARN,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "sata_create_target_node: no sdinfo for target %x",
2038334ab26baaa43c9083f35def041511c3cc1fUnknown target));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * create or get scsi inquiry data, expected by
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * scsi_hba_nodename_compatible_get()
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * SATA hard disks get Identify Data translated into Inguiry Data.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * ATAPI devices respond directly to Inquiry request.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sdinfo->satadrv_type == SATA_DTYPE_ATADISK) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_identdev_to_inquiry(sata_hba_inst, sdinfo,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (uint8_t *)&inq);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_addr->cport)));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown } else { /* Assume supported ATAPI device */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_addr->cport)));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sata_get_atapi_inquiry_data(sata_hba_inst, sata_addr,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown &inq) == SATA_FAILURE)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (NULL);
6ed1276fb5fe78fb1cce38682748a830ef8bd157pawelw /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Save supported ATAPI transport version
6ed1276fb5fe78fb1cce38682748a830ef8bd157pawelw */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_atapi_trans_ver =
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_ATAPI_TRANS_VERSION(&inq);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
6ed1276fb5fe78fb1cce38682748a830ef8bd157pawelw
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* determine the node name and compatible */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scsi_hba_nodename_compatible_get(&inq, NULL,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown inq.inq_dtype, NULL, &nname, &compatible, &ncompatible);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown#ifdef SATA_DEBUG
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sata_debug_flags & SATA_DBG_NODES) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (nname == NULL) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cmn_err(CE_NOTE, "sata_create_target_node: "
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "cannot determine nodename for target %d\n",
2038334ab26baaa43c9083f35def041511c3cc1fUnknown target);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown } else {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cmn_err(CE_WARN, "sata_create_target_node: "
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "target %d nodename: %s\n", target, nname);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (compatible == NULL) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cmn_err(CE_WARN,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "sata_create_target_node: no compatible name\n");
2038334ab26baaa43c9083f35def041511c3cc1fUnknown } else {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown for (i = 0; i < ncompatible; i++) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cmn_err(CE_WARN, "sata_create_target_node: "
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "compatible name: %s\n", compatible[i]);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown#endif
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* if nodename can't be determined, log error and exit */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (nname == NULL) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_LOG_D((sata_hba_inst, CE_WARN,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "sata_create_target_node: cannot determine nodename "
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "for target %d\n", target));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scsi_hba_nodename_compatible_free(nname, compatible);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (NULL);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Create scsi target node
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ndi_devi_alloc_sleep(dip, nname, (pnode_t)DEVI_SID_NODEID, &cdip);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rval = ndi_prop_update_string(DDI_DEV_T_NONE, cdip,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "device-type", "scsi");
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (rval != DDI_PROP_SUCCESS) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_LOG_D((sata_hba_inst, CE_WARN, "sata_create_target_node: "
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "updating device_type prop failed %d", rval));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown goto fail;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Create target node properties: target & lun
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rval = ndi_prop_update_int(DDI_DEV_T_NONE, cdip, "target", target);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (rval != DDI_PROP_SUCCESS) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_LOG_D((sata_hba_inst, CE_WARN, "sata_create_target_node: "
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "updating target prop failed %d", rval));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown goto fail;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rval = ndi_prop_update_int(DDI_DEV_T_NONE, cdip, "lun", 0);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (rval != DDI_PROP_SUCCESS) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_LOG_D((sata_hba_inst, CE_WARN, "sata_create_target_node: "
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "updating target prop failed %d", rval));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown goto fail;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
f8a673ad9145b262edb65a98fb3fb92027d23a05ying tian - Beijing China if (sdinfo->satadrv_type & SATA_DTYPE_ATAPI) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Add "variant" property
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rval = ndi_prop_update_string(DDI_DEV_T_NONE, cdip,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "variant", "atapi");
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (rval != DDI_PROP_SUCCESS) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_LOG_D((sata_hba_inst, CE_WARN,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "sata_create_target_node: variant atapi "
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "property could not be created: %d", rval));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown goto fail;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* decorate the node with compatible */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (ndi_prop_update_string_array(DDI_DEV_T_NONE, cdip, "compatible",
2038334ab26baaa43c9083f35def041511c3cc1fUnknown compatible, ncompatible) != DDI_PROP_SUCCESS) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_LOG_D((sata_hba_inst, CE_WARN,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "sata_create_target_node: FAIL compatible props cdip 0x%p",
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (void *)cdip));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown goto fail;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Now, try to attach the driver. If probing of the device fails,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * the target node may be removed
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rval = ndi_devi_online(cdip, NDI_ONLINE_ATTACH);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scsi_hba_nodename_compatible_free(nname, compatible);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (rval == NDI_SUCCESS)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (cdip);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* target node was removed - are we sure? */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknownfail:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scsi_hba_nodename_compatible_free(nname, compatible);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ddi_prop_remove_all(cdip);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rval = ndi_devi_free(cdip);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (rval != NDI_SUCCESS) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_LOG_D((sata_hba_inst, CE_WARN, "sata_create_target_node: "
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "node removal failed %d", rval));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_log(sata_hba_inst, CE_WARN, "sata_create_target_node: "
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "cannot create target node for SATA device at port %d",
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_addr->cport);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang/*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Remove a target node.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhangstatic void
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhangsata_remove_target_node(sata_hba_inst_t *sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_address_t *sata_addr)
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang{
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang dev_info_t *tdip;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang uint8_t cport = sata_addr->cport;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang uint8_t pmport = sata_addr->pmport;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang uint8_t qual = sata_addr->qual;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Note the sata daemon uses the address of the port/pmport */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang ASSERT(qual == SATA_ADDR_CPORT || qual == SATA_ADDR_PMPORT);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Remove target node */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang tdip = sata_get_target_dip(SATA_DIP(sata_hba_inst), cport, pmport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (tdip != NULL) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Target node exists. Unconfigure device
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * then remove the target node (one ndi
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * operation).
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (ndi_devi_offline(tdip, NDI_DEVI_REMOVE) != NDI_SUCCESS) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * PROBLEM - no device, but target node remained. This
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * happens when the file was open or node was waiting
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * for resources.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_LOG_D((sata_hba_inst, CE_WARN,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "sata_remove_target_node: "
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "Failed to remove target node for "
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "detached SATA device."));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Set target node state to DEVI_DEVICE_REMOVED. But
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * re-check first that the node still exists.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang tdip = sata_get_target_dip(SATA_DIP(sata_hba_inst),
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cport, pmport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (tdip != NULL) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_set_device_removed(tdip);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Instruct event daemon to retry the cleanup
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * later.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_set_target_node_cleanup(sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_addr);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (qual == SATA_ADDR_CPORT)
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_log(sata_hba_inst, CE_WARN,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "SATA device detached at port %d", cport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang else
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_log(sata_hba_inst, CE_WARN,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "SATA device detached at port %d:%d",
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cport, pmport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang#ifdef SATA_DEBUG
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang else {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (qual == SATA_ADDR_CPORT)
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_log(sata_hba_inst, CE_WARN,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "target node not found at port %d", cport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang else
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_log(sata_hba_inst, CE_WARN,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "target node not found at port %d:%d",
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cport, pmport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang#endif
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Re-probe sata port, check for a device and attach info
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * structures when necessary. Identify Device data is fetched, if possible.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Assumption: sata address is already validated.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * SATA_SUCCESS is returned if port is re-probed sucessfully, regardless of
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * the presence of a device and its type.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * flag arg specifies that the function should try multiple times to identify
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * device type and to initialize it, or it should return immediately on failure.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * SATA_DEV_IDENTIFY_RETRY - retry
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * SATA_DEV_IDENTIFY_NORETRY - no retry
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * SATA_FAILURE is returned if one of the operations failed.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown *
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * This function cannot be called in interrupt context - it may sleep.
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw *
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Note: Port multiplier is supported.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int
2038334ab26baaa43c9083f35def041511c3cc1fUnknownsata_reprobe_port(sata_hba_inst_t *sata_hba_inst, sata_device_t *sata_device,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown int flag)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_cport_info_t *cportinfo;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_pmult_info_t *pmultinfo;
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw sata_drive_info_t *sdinfo, *osdinfo;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown boolean_t init_device = B_FALSE;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown int prev_device_type = SATA_DTYPE_NONE;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown int prev_device_settings = 0;
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw int prev_device_state = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown clock_t start_time;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown int retry = B_FALSE;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang uint8_t cport = sata_device->satadev_addr.cport;
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik int rval_probe, rval_init;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * If target is pmport, sata_reprobe_pmport() will handle it.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (sata_device->satadev_addr.qual == SATA_ADDR_PMPORT ||
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device->satadev_addr.qual == SATA_ADDR_DPMPORT)
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang return (sata_reprobe_pmport(sata_hba_inst, sata_device, flag));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* We only care about host sata cport for now */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cportinfo = SATA_CPORT_INFO(sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_device->satadev_addr.cport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * If a port multiplier was previously attached (we have no idea it
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * still there or not), sata_reprobe_pmult() will handle it.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (cportinfo->cport_dev_type == SATA_DTYPE_PMULT)
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang return (sata_reprobe_pmult(sata_hba_inst, sata_device, flag));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Store sata_drive_info when a non-pmult device was attached. */
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw osdinfo = SATA_CPORTINFO_DRV_INFO(cportinfo);
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw if (osdinfo != NULL) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * We are re-probing port with a previously attached device.
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw * Save previous device type and settings.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown prev_device_type = cportinfo->cport_dev_type;
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw prev_device_settings = osdinfo->satadrv_settings;
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw prev_device_state = osdinfo->satadrv_state;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (flag == SATA_DEV_IDENTIFY_RETRY) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown start_time = ddi_get_lbolt();
2038334ab26baaa43c9083f35def041511c3cc1fUnknown retry = B_TRUE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
2038334ab26baaa43c9083f35def041511c3cc1fUnknownretry_probe:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* probe port */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_enter(&cportinfo->cport_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cportinfo->cport_state &= ~SATA_PORT_STATE_CLEAR_MASK;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cportinfo->cport_state |= SATA_STATE_PROBING;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&cportinfo->cport_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik rval_probe = (*SATA_PROBE_PORT_FUNC(sata_hba_inst))
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (SATA_DIP(sata_hba_inst), sata_device);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_enter(&cportinfo->cport_mutex);
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik if (rval_probe != SATA_SUCCESS) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cportinfo->cport_state = SATA_PSTATE_FAILED;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&cportinfo->cport_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_LOG_D((sata_hba_inst, CE_WARN, "sata_reprobe_port: "
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "SATA port %d probing failed",
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cportinfo->cport_addr.cport));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (SATA_FAILURE);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * update sata port state and set device type
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_update_port_info(sata_hba_inst, sata_device);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cportinfo->cport_state &= ~SATA_STATE_PROBING;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Sanity check - Port is active? Is the link active?
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Is there any device attached?
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if ((cportinfo->cport_state &
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (SATA_PSTATE_SHUTDOWN | SATA_PSTATE_FAILED)) ||
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (cportinfo->cport_scr.sstatus & SATA_PORT_DEVLINK_UP_MASK) !=
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_PORT_DEVLINK_UP) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Port in non-usable state or no link active/no device.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Free info structure if necessary (direct attached drive
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * only, for now!
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo = SATA_CPORTINFO_DRV_INFO(cportinfo);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_CPORTINFO_DRV_INFO(cportinfo) = NULL;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Add here differentiation for device attached or not */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cportinfo->cport_dev_type = SATA_DTYPE_NONE;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&cportinfo->cport_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sdinfo != NULL)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown kmem_free(sdinfo, sizeof (sata_drive_info_t));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (SATA_SUCCESS);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cportinfo->cport_state |= SATA_STATE_READY;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cportinfo->cport_state |= SATA_STATE_PROBED;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cportinfo->cport_dev_type = sata_device->satadev_type;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo = SATA_CPORTINFO_DRV_INFO(cportinfo);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * If we are re-probing the port, there may be
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * sata_drive_info structure attached
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sata_device->satadev_type == SATA_DTYPE_NONE) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * There is no device, so remove device info structure,
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw * if necessary.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Device change: Drive -> None */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_CPORTINFO_DRV_INFO(cportinfo) = NULL;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cportinfo->cport_dev_type = SATA_DTYPE_NONE;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sdinfo != NULL) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown kmem_free(sdinfo, sizeof (sata_drive_info_t));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_log(sata_hba_inst, CE_WARN,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "SATA device detached "
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "from port %d", cportinfo->cport_addr.cport);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&cportinfo->cport_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (SATA_SUCCESS);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sata_device->satadev_type != SATA_DTYPE_PMULT) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Device (may) change: Drive -> Drive */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sdinfo == NULL) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * There is some device attached, but there is
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * no sata_drive_info structure - allocate one
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&cportinfo->cport_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo = kmem_zalloc(
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sizeof (sata_drive_info_t), KM_SLEEP);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_enter(&cportinfo->cport_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Recheck, that the port state did not change when we
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * released mutex.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (cportinfo->cport_state & SATA_STATE_READY) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_CPORTINFO_DRV_INFO(cportinfo) = sdinfo;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_addr = cportinfo->cport_addr;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_addr.qual = SATA_ADDR_DCPORT;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_type = SATA_DTYPE_UNKNOWN;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_state = SATA_STATE_UNKNOWN;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown } else {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Port is not in ready state, we
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * cannot attach a device.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&cportinfo->cport_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown kmem_free(sdinfo, sizeof (sata_drive_info_t));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (SATA_SUCCESS);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Since we are adding device, presumably new one,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * indicate that it should be initalized,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * as well as some internal framework states).
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown init_device = B_TRUE;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cportinfo->cport_dev_type = SATA_DTYPE_UNKNOWN;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_device->satadev_addr.qual = sdinfo->satadrv_addr.qual;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Device change: Drive -> PMult */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_CPORTINFO_DRV_INFO(cportinfo) = NULL;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (sdinfo != NULL) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang kmem_free(sdinfo, sizeof (sata_drive_info_t));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_log(sata_hba_inst, CE_WARN,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "SATA device detached "
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "from port %d", cportinfo->cport_addr.cport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_log(sata_hba_inst, CE_WARN,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "SATA port multiplier detected at port %d",
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cportinfo->cport_addr.cport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&cportinfo->cport_mutex);
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang if (sata_alloc_pmult(sata_hba_inst, sata_device) !=
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang SATA_SUCCESS)
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang return (SATA_FAILURE);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_show_pmult_info(sata_hba_inst, sata_device);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&cportinfo->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Mark all the port multiplier port behind the port
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * multiplier behind with link events, so that the sata daemon
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * will update their status.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmultinfo = SATA_PMULT_INFO(sata_hba_inst, cport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmultinfo->pmult_event_flags |= SATA_EVNT_DEVICE_RESET;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&cportinfo->cport_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (SATA_SUCCESS);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&cportinfo->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Figure out what kind of device we are really
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik * dealing with. Failure of identifying device does not fail this
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik * function.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik rval_probe = sata_probe_device(sata_hba_inst, sata_device);
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik rval_init = SATA_FAILURE;
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw mutex_enter(&cportinfo->cport_mutex);
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik if (rval_probe == SATA_SUCCESS) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * If we are dealing with the same type of a device as before,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * restore its settings flags.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw if (osdinfo != NULL &&
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw sata_device->satadev_type == prev_device_type)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_settings = prev_device_settings;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw mutex_exit(&cportinfo->cport_mutex);
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik rval_init = SATA_SUCCESS;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Set initial device features, if necessary */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (init_device == B_TRUE) {
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik rval_init = sata_initialize_device(sata_hba_inst,
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik sdinfo);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik if (rval_init == SATA_SUCCESS)
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik return (rval_init);
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik /* else we will retry if retry was asked for */
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw } else {
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw /*
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw * If there was some device info before we probe the device,
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw * restore previous device setting, so we can retry from scratch
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw * later. Providing, of course, that device has not disapear
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw * during probing process.
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw */
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw if (sata_device->satadev_type != SATA_DTYPE_NONE) {
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw if (osdinfo != NULL) {
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw cportinfo->cport_dev_type = prev_device_type;
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw sdinfo->satadrv_type = prev_device_type;
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw sdinfo->satadrv_state = prev_device_state;
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw }
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw } else {
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw /* device is gone */
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw kmem_free(sdinfo, sizeof (sata_drive_info_t));
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw cportinfo->cport_dev_type = SATA_DTYPE_NONE;
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw SATA_CPORTINFO_DRV_INFO(cportinfo) = NULL;
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw mutex_exit(&cportinfo->cport_mutex);
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw return (SATA_SUCCESS);
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw }
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw mutex_exit(&cportinfo->cport_mutex);
497c5ad58d5c382fa66ec5355d7a84ca3fb4573als }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (retry) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown clock_t cur_time = ddi_get_lbolt();
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * A device was not successfully identified or initialized.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Track retry time for device identification.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if ((cur_time - start_time) <
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw drv_usectohz(SATA_DEV_REPROBE_TIMEOUT)) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* sleep for a while */
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw delay(drv_usectohz(SATA_DEV_RETRY_DLY));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown goto retry_probe;
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik }
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik /* else no more retries */
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik mutex_enter(&cportinfo->cport_mutex);
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik if (SATA_CPORTINFO_DRV_INFO(cportinfo) != NULL) {
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik if (rval_init == SATA_RETRY) {
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik /*
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik * Setting drive features have failed, but
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik * because the drive is still accessible,
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik * keep it and emit a warning message.
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik */
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik sata_log(sata_hba_inst, CE_WARN,
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik "SATA device at port %d - desired "
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik "drive features could not be set. "
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik "Device may not operate as expected.",
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik cportinfo->cport_addr.cport);
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik } else {
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw SATA_CPORTINFO_DRV_INFO(cportinfo)->
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw satadrv_state = SATA_DSTATE_FAILED;
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik mutex_exit(&cportinfo->cport_mutex);
37a077ef1920ee044b2887247b2a802e726d3368ls }
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw return (SATA_SUCCESS);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Reprobe a controller port that connected to a port multiplier.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * NOTE: No Mutex should be hold.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic int
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhangsata_reprobe_pmult(sata_hba_inst_t *sata_hba_inst, sata_device_t *sata_device,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang int flag)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang _NOTE(ARGUNUSED(flag))
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_cport_info_t *cportinfo;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_pmult_info_t *pmultinfo;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang uint8_t cport = sata_device->satadev_addr.cport;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang int rval_probe;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cportinfo = SATA_CPORT_INFO(sata_hba_inst, cport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmultinfo = SATA_PMULT_INFO(sata_hba_inst, cport);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* probe port */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&cportinfo->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cportinfo->cport_state &= ~SATA_PORT_STATE_CLEAR_MASK;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cportinfo->cport_state |= SATA_STATE_PROBING;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&cportinfo->cport_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang rval_probe = (*SATA_PROBE_PORT_FUNC(sata_hba_inst))
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (SATA_DIP(sata_hba_inst), sata_device);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&cportinfo->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (rval_probe != SATA_SUCCESS) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cportinfo->cport_state = SATA_PSTATE_FAILED;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_LOG_D((sata_hba_inst, CE_WARN, "sata_reprobe_pmult: "
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "SATA port %d probing failed", cport));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_log(sata_hba_inst, CE_WARN,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "SATA port multiplier detached at port %d", cport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&cportinfo->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_free_pmult(sata_hba_inst, sata_device);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang return (SATA_FAILURE);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * update sata port state and set device type
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_update_port_info(sata_hba_inst, sata_device);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cportinfo->cport_state &= ~SATA_STATE_PROBING;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cportinfo->cport_state |= SATA_STATE_PROBED;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Sanity check - Port is active? Is the link active?
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Is there any device attached?
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if ((cportinfo->cport_state &
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (SATA_PSTATE_SHUTDOWN | SATA_PSTATE_FAILED)) ||
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (cportinfo->cport_scr.sstatus & SATA_PORT_DEVLINK_UP_MASK) !=
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_PORT_DEVLINK_UP ||
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (sata_device->satadev_type == SATA_DTYPE_NONE)) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cportinfo->cport_dev_type = SATA_DTYPE_NONE;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&cportinfo->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_free_pmult(sata_hba_inst, sata_device);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_log(sata_hba_inst, CE_WARN,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "SATA port multiplier detached at port %d", cport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang return (SATA_SUCCESS);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
2ee4dfc799525d35706ee64a901cd970a7080bb6Jane Chu
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Device changed: PMult -> Non-PMult
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang *
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * This situation is uncommon, most possibly being caused by errors
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * after which the port multiplier is not correct initialized and
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * recognized. In that case the new device will be marked as unknown
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * and will not be automatically probed in this routine. Instead
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * system administrator could manually restart it via cfgadm(1M).
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (sata_device->satadev_type != SATA_DTYPE_PMULT) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cportinfo->cport_dev_type = SATA_DTYPE_UNKNOWN;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&cportinfo->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_free_pmult(sata_hba_inst, sata_device);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_log(sata_hba_inst, CE_WARN,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "SATA port multiplier detached at port %d", cport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang return (SATA_FAILURE);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Now we know it is a port multiplier. However, if this is not the
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * previously attached port multiplier - they may have different
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * pmport numbers - we need to re-allocate data structures for every
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * pmport and drive.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang *
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Port multipliers of the same model have identical values in these
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * registers, so it is still necessary to update the information of
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * all drives attached to the previous port multiplier afterwards.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang /* Device changed: PMult -> another PMult */
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang mutex_exit(&cportinfo->cport_mutex);
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang sata_free_pmult(sata_hba_inst, sata_device);
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang if (sata_alloc_pmult(sata_hba_inst, sata_device) != SATA_SUCCESS)
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang return (SATA_FAILURE);
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang mutex_enter(&cportinfo->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang SATADBG1(SATA_DBG_PMULT, sata_hba_inst,
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang "SATA port multiplier [changed] at port %d", cport);
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang sata_log(sata_hba_inst, CE_WARN,
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang "SATA port multiplier detected at port %d", cport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Mark all the port multiplier port behind the port
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * multiplier behind with link events, so that the sata daemon
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * will update their status.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmultinfo->pmult_event_flags |= SATA_EVNT_DEVICE_RESET;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&cportinfo->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang return (SATA_SUCCESS);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Re-probe a port multiplier port, check for a device and attach info
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * structures when necessary. Identify Device data is fetched, if possible.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Assumption: sata address is already validated as port multiplier port.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * SATA_SUCCESS is returned if port is re-probed sucessfully, regardless of
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * the presence of a device and its type.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * flag arg specifies that the function should try multiple times to identify
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * device type and to initialize it, or it should return immediately on failure.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * SATA_DEV_IDENTIFY_RETRY - retry
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * SATA_DEV_IDENTIFY_NORETRY - no retry
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * SATA_FAILURE is returned if one of the operations failed.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown *
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * This function cannot be called in interrupt context - it may sleep.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang *
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * NOTE: Should be only called by sata_probe_port() in case target port is a
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * port multiplier port.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * NOTE: No Mutex should be hold.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhangstatic int
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhangsata_reprobe_pmport(sata_hba_inst_t *sata_hba_inst, sata_device_t *sata_device,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang int flag)
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang{
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_cport_info_t *cportinfo = NULL;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_pmport_info_t *pmportinfo = NULL;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_drive_info_t *sdinfo, *osdinfo;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device_t sdevice;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang boolean_t init_device = B_FALSE;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang int prev_device_type = SATA_DTYPE_NONE;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang int prev_device_settings = 0;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang int prev_device_state = 0;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang clock_t start_time;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang uint8_t cport = sata_device->satadev_addr.cport;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang uint8_t pmport = sata_device->satadev_addr.pmport;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang int rval;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cportinfo = SATA_CPORT_INFO(sata_hba_inst, cport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo = SATA_PMPORT_INFO(sata_hba_inst, cport, pmport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang osdinfo = SATA_PMPORTINFO_DRV_INFO(pmportinfo);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (osdinfo != NULL) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * We are re-probing port with a previously attached device.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Save previous device type and settings.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang prev_device_type = pmportinfo->pmport_dev_type;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang prev_device_settings = osdinfo->satadrv_settings;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang prev_device_state = osdinfo->satadrv_state;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang start_time = ddi_get_lbolt();
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* check parent status */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&cportinfo->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if ((cportinfo->cport_state &
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (SATA_PSTATE_SHUTDOWN | SATA_PSTATE_FAILED)) ||
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (cportinfo->cport_scr.sstatus & SATA_PORT_DEVLINK_UP_MASK) !=
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_PORT_DEVLINK_UP) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&cportinfo->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang return (SATA_FAILURE);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&cportinfo->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhangretry_probe_pmport:
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* probe port */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo->pmport_state &= ~SATA_PORT_STATE_CLEAR_MASK;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo->pmport_state |= SATA_STATE_PROBING;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang rval = (*SATA_PROBE_PORT_FUNC(sata_hba_inst))
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (SATA_DIP(sata_hba_inst), sata_device);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* might need retry because we cannot touch registers. */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (rval == SATA_FAILURE) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo->pmport_state = SATA_PSTATE_FAILED;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_LOG_D((sata_hba_inst, CE_WARN, "sata_reprobe_pmport: "
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "SATA port %d:%d probing failed",
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cport, pmport));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang return (SATA_FAILURE);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang } else if (rval == SATA_RETRY) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_LOG_D((sata_hba_inst, CE_WARN, "sata_reprobe_pmport: "
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "SATA port %d:%d probing failed, retrying...",
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cport, pmport));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang clock_t cur_time = ddi_get_lbolt();
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * A device was not successfully identified or initialized.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Track retry time for device identification.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if ((cur_time - start_time) <
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang drv_usectohz(SATA_DEV_REPROBE_TIMEOUT)) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* sleep for a while */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang delay(drv_usectohz(SATA_DEV_RETRY_DLY));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang goto retry_probe_pmport;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang } else {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (SATA_PMPORTINFO_DRV_INFO(pmportinfo) != NULL)
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_PMPORTINFO_DRV_INFO(pmportinfo)->
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang satadrv_state = SATA_DSTATE_FAILED;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang return (SATA_SUCCESS);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Sanity check - Controller port is active? Is the link active?
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Is it still a port multiplier?
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if ((cportinfo->cport_state &
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (SATA_PSTATE_SHUTDOWN | SATA_PSTATE_FAILED)) ||
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (cportinfo->cport_scr.sstatus & SATA_PORT_DEVLINK_UP_MASK) !=
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_PORT_DEVLINK_UP ||
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (cportinfo->cport_dev_type != SATA_DTYPE_PMULT)) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Port in non-usable state or no link active/no
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * device. Free info structure.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cportinfo->cport_dev_type = SATA_DTYPE_UNKNOWN;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sdevice.satadev_addr.cport = cport;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sdevice.satadev_addr.pmport = pmport;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sdevice.satadev_addr.qual = SATA_ADDR_PMULT;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&cportinfo->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_free_pmult(sata_hba_inst, &sdevice);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang return (SATA_FAILURE);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* SATA_SUCCESS NOW */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * update sata port state and set device type
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_update_pmport_info(sata_hba_inst, sata_device);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo->pmport_state &= ~SATA_STATE_PROBING;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Sanity check - Port is active? Is the link active?
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Is there any device attached?
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if ((pmportinfo->pmport_state &
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (SATA_PSTATE_SHUTDOWN | SATA_PSTATE_FAILED)) ||
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (pmportinfo->pmport_scr.sstatus & SATA_PORT_DEVLINK_UP_MASK) !=
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_PORT_DEVLINK_UP) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Port in non-usable state or no link active/no device.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Free info structure if necessary (direct attached drive
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * only, for now!
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sdinfo = SATA_PMPORTINFO_DRV_INFO(pmportinfo);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_PMPORTINFO_DRV_INFO(pmportinfo) = NULL;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Add here differentiation for device attached or not */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo->pmport_dev_type = SATA_DTYPE_NONE;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (sdinfo != NULL)
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang kmem_free(sdinfo, sizeof (sata_drive_info_t));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang return (SATA_SUCCESS);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo->pmport_state |= SATA_STATE_READY;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo->pmport_dev_type = sata_device->satadev_type;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sdinfo = SATA_PMPORTINFO_DRV_INFO(pmportinfo);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * If we are re-probing the port, there may be
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * sata_drive_info structure attached
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * (or sata_pm_info, if PMult is supported).
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (sata_device->satadev_type == SATA_DTYPE_NONE) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * There is no device, so remove device info structure,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * if necessary.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_PMPORTINFO_DRV_INFO(pmportinfo) = NULL;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo->pmport_dev_type = SATA_DTYPE_NONE;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (sdinfo != NULL) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang kmem_free(sdinfo, sizeof (sata_drive_info_t));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_log(sata_hba_inst, CE_WARN,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "SATA device detached from port %d:%d",
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cport, pmport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang return (SATA_SUCCESS);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* this should not be a pmult */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang ASSERT(sata_device->satadev_type != SATA_DTYPE_PMULT);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (sdinfo == NULL) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * There is some device attached, but there is
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * no sata_drive_info structure - allocate one
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sdinfo = kmem_zalloc(sizeof (sata_drive_info_t),
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang KM_SLEEP);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Recheck, that the port state did not change when we
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * released mutex.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (pmportinfo->pmport_state & SATA_STATE_READY) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_PMPORTINFO_DRV_INFO(pmportinfo) = sdinfo;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sdinfo->satadrv_addr = pmportinfo->pmport_addr;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sdinfo->satadrv_addr.qual = SATA_ADDR_DPMPORT;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sdinfo->satadrv_type = SATA_DTYPE_UNKNOWN;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sdinfo->satadrv_state = SATA_STATE_UNKNOWN;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang } else {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Port is not in ready state, we
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * cannot attach a device.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang kmem_free(sdinfo, sizeof (sata_drive_info_t));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang return (SATA_SUCCESS);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Since we are adding device, presumably new one,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * indicate that it should be initalized,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * as well as some internal framework states).
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang init_device = B_TRUE;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo->pmport_dev_type = SATA_DTYPE_UNKNOWN;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device->satadev_addr.qual = sdinfo->satadrv_addr.qual;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Figure out what kind of device we are really
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * dealing with.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang rval = sata_probe_device(sata_hba_inst, sata_device);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (rval == SATA_SUCCESS) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * If we are dealing with the same type of a device as before,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * restore its settings flags.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (osdinfo != NULL &&
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device->satadev_type == prev_device_type)
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sdinfo->satadrv_settings = prev_device_settings;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Set initial device features, if necessary */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (init_device == B_TRUE) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang rval = sata_initialize_device(sata_hba_inst, sdinfo);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (rval == SATA_SUCCESS)
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang return (rval);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang } else {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * If there was some device info before we probe the device,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * restore previous device setting, so we can retry from scratch
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * later. Providing, of course, that device has not disappeared
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * during probing process.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (sata_device->satadev_type != SATA_DTYPE_NONE) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (osdinfo != NULL) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo->pmport_dev_type = prev_device_type;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sdinfo->satadrv_type = prev_device_type;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sdinfo->satadrv_state = prev_device_state;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang } else {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* device is gone */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang kmem_free(sdinfo, sizeof (sata_drive_info_t));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo->pmport_dev_type = SATA_DTYPE_NONE;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_PMPORTINFO_DRV_INFO(pmportinfo) = NULL;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang return (SATA_SUCCESS);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (flag == SATA_DEV_IDENTIFY_RETRY) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang clock_t cur_time = ddi_get_lbolt();
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * A device was not successfully identified or initialized.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Track retry time for device identification.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if ((cur_time - start_time) <
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang drv_usectohz(SATA_DEV_REPROBE_TIMEOUT)) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* sleep for a while */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang delay(drv_usectohz(SATA_DEV_RETRY_DLY));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang goto retry_probe_pmport;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang } else {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (SATA_PMPORTINFO_DRV_INFO(pmportinfo) != NULL)
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_PMPORTINFO_DRV_INFO(pmportinfo)->
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang satadrv_state = SATA_DSTATE_FAILED;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang return (SATA_SUCCESS);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang}
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang/*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Allocated related structure for a port multiplier and its device ports
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang *
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Port multiplier should be ready and probed, and related information like
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * the number of the device ports should be store in sata_device_t.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang *
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * NOTE: No Mutex should be hold.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhangstatic int
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhangsata_alloc_pmult(sata_hba_inst_t *sata_hba_inst, sata_device_t *sata_device)
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang{
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang dev_info_t *dip = SATA_DIP(sata_hba_inst);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_cport_info_t *cportinfo = NULL;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_pmult_info_t *pmultinfo = NULL;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_pmport_info_t *pmportinfo = NULL;
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang sata_device_t sd;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang dev_t minor_number;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang char name[16];
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang uint8_t cport = sata_device->satadev_addr.cport;
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang int rval;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang int npmport;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cportinfo = SATA_CPORT_INFO(sata_hba_inst, cport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* This function might be called while a port-mult is hot-plugged. */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&cportinfo->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* dev_type's not updated when get called from sata_reprobe_port() */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cportinfo->cport_dev_type = SATA_DTYPE_PMULT;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (SATA_CPORTINFO_PMULT_INFO(cportinfo) == NULL) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Create a pmult_info structure */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_CPORTINFO_PMULT_INFO(cportinfo) =
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang kmem_zalloc(sizeof (sata_pmult_info_t), KM_SLEEP);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmultinfo = SATA_CPORTINFO_PMULT_INFO(cportinfo);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmultinfo->pmult_addr = sata_device->satadev_addr;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmultinfo->pmult_addr.qual = SATA_ADDR_PMULT;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmultinfo->pmult_state = SATA_STATE_PROBING;
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang /*
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang * Probe the port multiplier with qualifier SATA_ADDR_PMULT_SPEC,
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang * The HBA driver should initialize and register the port multiplier,
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang * sata_register_pmult() will fill following fields,
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang * + sata_pmult_info.pmult_gscr
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang * + sata_pmult_info.pmult_num_dev_ports
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang */
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang sd.satadev_addr = sata_device->satadev_addr;
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang sd.satadev_addr.qual = SATA_ADDR_PMULT_SPEC;
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang mutex_exit(&cportinfo->cport_mutex);
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang rval = (*SATA_PROBE_PORT_FUNC(sata_hba_inst))
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang (SATA_DIP(sata_hba_inst), &sd);
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang mutex_enter(&cportinfo->cport_mutex);
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang if (rval != SATA_SUCCESS ||
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang (sd.satadev_type != SATA_DTYPE_PMULT) ||
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang !(sd.satadev_state & SATA_DSTATE_PMULT_INIT)) {
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang SATA_CPORTINFO_PMULT_INFO(cportinfo) = NULL;
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang kmem_free(pmultinfo, sizeof (sata_pmult_info_t));
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang cportinfo->cport_state = SATA_PSTATE_FAILED;
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang cportinfo->cport_dev_type = SATA_DTYPE_UNKNOWN;
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang mutex_exit(&cportinfo->cport_mutex);
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang SATADBG1(SATA_DBG_PMULT, sata_hba_inst,
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang "sata_alloc_pmult: failed to initialize pmult "
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang "at port %d.", cport)
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang return (SATA_FAILURE);
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Initialize pmport_info structure */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang for (npmport = 0; npmport < pmultinfo->pmult_num_dev_ports;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang npmport++) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* if everything is allocated, skip */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (SATA_PMPORT_INFO(sata_hba_inst, cport, npmport) != NULL)
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang continue;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo = kmem_zalloc(sizeof (sata_pmport_info_t), KM_SLEEP);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_init(&pmportinfo->pmport_mutex, NULL, MUTEX_DRIVER, NULL);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&cportinfo->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo->pmport_addr.cport = cport;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo->pmport_addr.pmport = (uint8_t)npmport;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo->pmport_addr.qual = SATA_ADDR_PMPORT;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo->pmport_state &= ~SATA_PORT_STATE_CLEAR_MASK;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&cportinfo->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_PMPORT_INFO(sata_hba_inst, cport, npmport) = pmportinfo;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Create an attachment point */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang minor_number = SATA_MAKE_AP_MINOR(ddi_get_instance(dip),
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cport, (uint8_t)npmport, SATA_ADDR_PMPORT);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (void) sprintf(name, "%d.%d", cport, npmport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (ddi_create_minor_node(dip, name, S_IFCHR, minor_number,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang DDI_NT_SATA_ATTACHMENT_POINT, 0) != DDI_SUCCESS) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_log(sata_hba_inst, CE_WARN, "sata_hba_attach: "
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "cannot create SATA attachment point for "
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "port %d:%d", cport, npmport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmultinfo->pmult_state &= ~SATA_STATE_PROBING;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmultinfo->pmult_state |= (SATA_STATE_PROBED|SATA_STATE_READY);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&cportinfo->cport_mutex);
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang return (SATA_SUCCESS);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang}
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang/*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Free data structures when a port multiplier is removed.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang *
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * NOTE: No Mutex should be hold.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhangstatic void
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhangsata_free_pmult(sata_hba_inst_t *sata_hba_inst, sata_device_t *sata_device)
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang{
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_cport_info_t *cportinfo;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_pmult_info_t *pmultinfo;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_pmport_info_t *pmportinfo;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device_t pmport_device;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_drive_info_t *sdinfo;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang dev_info_t *tdip;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang char name[16];
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang uint8_t cport = sata_device->satadev_addr.cport;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang int npmport;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cportinfo = SATA_CPORT_INFO(sata_hba_inst, cport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* This function might be called while port-mult is hot plugged. */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&cportinfo->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmultinfo = SATA_CPORTINFO_PMULT_INFO(cportinfo);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang ASSERT(pmultinfo != NULL);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Free pmport_info structure */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang for (npmport = 0; npmport < pmultinfo->pmult_num_dev_ports;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang npmport++) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo = SATA_PMPORT_INFO(sata_hba_inst, cport, npmport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (pmportinfo == NULL)
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang continue;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&cportinfo->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sdinfo = pmportinfo->pmport_sata_drive;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_PMPORTINFO_DRV_INFO(pmportinfo) = NULL;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Remove attachment point. */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang name[0] = '\0';
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (void) sprintf(name, "%d.%d", cport, npmport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang ddi_remove_minor_node(SATA_DIP(sata_hba_inst), name);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_log(sata_hba_inst, CE_NOTE,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "Remove attachment point of port %d:%d",
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cport, npmport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Rumove target node
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang bzero(&pmport_device, sizeof (sata_device_t));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmport_device.satadev_rev = SATA_DEVICE_REV;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmport_device.satadev_addr.cport = cport;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmport_device.satadev_addr.pmport = (uint8_t)npmport;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmport_device.satadev_addr.qual = SATA_ADDR_DPMPORT;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang tdip = sata_get_scsi_target_dip(SATA_DIP(sata_hba_inst),
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang &(pmport_device.satadev_addr));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (tdip != NULL && ndi_devi_offline(tdip,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang NDI_DEVI_REMOVE) != NDI_SUCCESS) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Problem :
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * The target node remained attached.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * This happens when the device file was open
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * or a node was waiting for resources.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Cannot do anything about it.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_LOG_D((sata_hba_inst, CE_WARN,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "sata_free_pmult: could not unconfigure device "
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "before disconnecting the SATA port %d:%d",
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cport, npmport));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Set DEVICE REMOVED state in the target
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * node. It will prevent access to the device
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * even when a new device is attached, until
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * the old target node is released, removed and
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * recreated for a new device.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_set_device_removed(tdip);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Instruct event daemon to try the target
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * node cleanup later.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_set_target_node_cleanup(
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_hba_inst, &(pmport_device.satadev_addr));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&cportinfo->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Add here differentiation for device attached or not
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (sdinfo != NULL) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_log(sata_hba_inst, CE_WARN,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "SATA device detached from port %d:%d",
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cport, npmport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang kmem_free(sdinfo, sizeof (sata_drive_info_t));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_destroy(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang kmem_free(pmportinfo, sizeof (sata_pmport_info_t));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang kmem_free(pmultinfo, sizeof (sata_pmult_info_t));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cportinfo->cport_devp.cport_sata_pmult = NULL;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cportinfo->cport_dev_type = SATA_DTYPE_NONE;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_log(sata_hba_inst, CE_WARN,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "SATA port multiplier detached at port %d", cport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&cportinfo->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang}
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang/*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Initialize device
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Specified device is initialized to a default state.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang *
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Returns SATA_SUCCESS if all device features are set successfully,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * SATA_RETRY if device is accessible but device features were not set
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * successfully, and SATA_FAILURE otherwise.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhangstatic int
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhangsata_initialize_device(sata_hba_inst_t *sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_drive_info_t *sdinfo)
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang{
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang int rval;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_save_drive_settings(sdinfo);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sdinfo->satadrv_settings |= SATA_DEV_READ_AHEAD;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_init_write_cache_mode(sdinfo);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang rval = sata_set_drive_features(sata_hba_inst, sdinfo, 0);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Determine current data transfer mode */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if ((sdinfo->satadrv_id.ai_cap & SATA_DMA_SUPPORT) == 0) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sdinfo->satadrv_settings &= ~SATA_DEV_DMA;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang } else if ((sdinfo->satadrv_id.ai_validinfo &
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_VALIDINFO_88) != 0 &&
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (sdinfo->satadrv_id.ai_ultradma & SATA_UDMA_SEL_MASK) != 0) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sdinfo->satadrv_settings |= SATA_DEV_DMA;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang } else if ((sdinfo->satadrv_id.ai_dworddma &
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_MDMA_SEL_MASK) != 0) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sdinfo->satadrv_settings |= SATA_DEV_DMA;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang } else
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* DMA supported, not no DMA transfer mode is selected !? */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sdinfo->satadrv_settings &= ~SATA_DEV_DMA;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if ((sdinfo->satadrv_id.ai_cmdset83 & 0x20) &&
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (sdinfo->satadrv_id.ai_features86 & 0x20))
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sdinfo->satadrv_power_level = SATA_POWER_STANDBY;
776955ed2c90dad066581c20700f1969e3c15f77Ada else
776955ed2c90dad066581c20700f1969e3c15f77Ada sdinfo->satadrv_power_level = SATA_POWER_ACTIVE;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang return (rval);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang}
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang/*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Initialize write cache mode.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang *
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * The default write cache setting for SATA HDD is provided by sata_write_cache
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * static variable. ATAPI CD/DVDs devices have write cache default is
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * determined by sata_atapicdvd_write_cache static variable.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * ATAPI tape devices have write cache default is determined by
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * sata_atapitape_write_cache static variable.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * ATAPI disk devices have write cache default is determined by
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * sata_atapidisk_write_cache static variable.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * 1 - enable
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * 0 - disable
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * any other value - current drive setting
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang *
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Although there is not reason to disable write cache on CD/DVD devices,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * tape devices and ATAPI disk devices, the default setting control is provided
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * for the maximun flexibility.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang *
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * In the future, it may be overridden by the
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * disk-write-cache-enable property setting, if it is defined.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Returns SATA_SUCCESS if all device features are set successfully,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * SATA_FAILURE otherwise.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic void
2038334ab26baaa43c9083f35def041511c3cc1fUnknownsata_init_write_cache_mode(sata_drive_info_t *sdinfo)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China switch (sdinfo->satadrv_type) {
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China case SATA_DTYPE_ATADISK:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sata_write_cache == 1)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_settings |= SATA_DEV_WRITE_CACHE;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown else if (sata_write_cache == 0)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_settings &= ~SATA_DEV_WRITE_CACHE;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * When sata_write_cache value is not 0 or 1,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * a current setting of the drive's write cache is used.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China break;
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China case SATA_DTYPE_ATAPICD:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sata_atapicdvd_write_cache == 1)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_settings |= SATA_DEV_WRITE_CACHE;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown else if (sata_atapicdvd_write_cache == 0)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_settings &= ~SATA_DEV_WRITE_CACHE;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
f8a673ad9145b262edb65a98fb3fb92027d23a05ying tian - Beijing China * When sata_atapicdvd_write_cache value is not 0 or 1,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * a current setting of the drive's write cache is used.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China break;
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China case SATA_DTYPE_ATAPITAPE:
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China if (sata_atapitape_write_cache == 1)
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China sdinfo->satadrv_settings |= SATA_DEV_WRITE_CACHE;
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China else if (sata_atapitape_write_cache == 0)
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China sdinfo->satadrv_settings &= ~SATA_DEV_WRITE_CACHE;
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China /*
f8a673ad9145b262edb65a98fb3fb92027d23a05ying tian - Beijing China * When sata_atapitape_write_cache value is not 0 or 1,
f8a673ad9145b262edb65a98fb3fb92027d23a05ying tian - Beijing China * a current setting of the drive's write cache is used.
f8a673ad9145b262edb65a98fb3fb92027d23a05ying tian - Beijing China */
f8a673ad9145b262edb65a98fb3fb92027d23a05ying tian - Beijing China break;
f8a673ad9145b262edb65a98fb3fb92027d23a05ying tian - Beijing China case SATA_DTYPE_ATAPIDISK:
f8a673ad9145b262edb65a98fb3fb92027d23a05ying tian - Beijing China if (sata_atapidisk_write_cache == 1)
f8a673ad9145b262edb65a98fb3fb92027d23a05ying tian - Beijing China sdinfo->satadrv_settings |= SATA_DEV_WRITE_CACHE;
f8a673ad9145b262edb65a98fb3fb92027d23a05ying tian - Beijing China else if (sata_atapidisk_write_cache == 0)
f8a673ad9145b262edb65a98fb3fb92027d23a05ying tian - Beijing China sdinfo->satadrv_settings &= ~SATA_DEV_WRITE_CACHE;
f8a673ad9145b262edb65a98fb3fb92027d23a05ying tian - Beijing China /*
f8a673ad9145b262edb65a98fb3fb92027d23a05ying tian - Beijing China * When sata_atapidisk_write_cache value is not 0 or 1,
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China * a current setting of the drive's write cache is used.
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China */
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Validate sata address.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Specified cport, pmport and qualifier has to match
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * passed sata_scsi configuration info.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * The presence of an attached device is not verified.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Returns 0 when address is valid, -1 otherwise.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic int
2038334ab26baaa43c9083f35def041511c3cc1fUnknownsata_validate_sata_address(sata_hba_inst_t *sata_hba_inst, int cport,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown int pmport, int qual)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (qual == SATA_ADDR_DCPORT && pmport != 0)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown goto invalid_address;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (cport >= SATA_NUM_CPORTS(sata_hba_inst))
2038334ab26baaa43c9083f35def041511c3cc1fUnknown goto invalid_address;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if ((qual == SATA_ADDR_DPMPORT || qual == SATA_ADDR_PMPORT) &&
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ((SATA_CPORT_DEV_TYPE(sata_hba_inst, cport) != SATA_DTYPE_PMULT) ||
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (SATA_PMULT_INFO(sata_hba_inst, cport) == NULL) ||
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (pmport >= SATA_NUM_PMPORTS(sata_hba_inst, cport))))
2038334ab26baaa43c9083f35def041511c3cc1fUnknown goto invalid_address;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (0);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknowninvalid_address:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (-1);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Validate scsi address
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * SCSI target address is translated into SATA cport/pmport and compared
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * with a controller port/device configuration. LUN has to be 0.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Returns 0 if a scsi target refers to an attached device,
a9d5ae2e08c504913c088349c3d4c144f3c92be8Pawel Wojcik * returns 1 if address is valid but no valid device is attached,
a9d5ae2e08c504913c088349c3d4c144f3c92be8Pawel Wojcik * returns 2 if address is valid but device type is unknown (not valid device),
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * returns -1 if bad address or device is of an unsupported type.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Upon return sata_device argument is set.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang *
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Port multiplier is supported now.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic int
2038334ab26baaa43c9083f35def041511c3cc1fUnknownsata_validate_scsi_address(sata_hba_inst_t *sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown struct scsi_address *ap, sata_device_t *sata_device)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
2038334ab26baaa43c9083f35def041511c3cc1fUnknown int cport, pmport, qual, rval;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rval = -1; /* Invalid address */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (ap->a_lun != 0)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown goto out;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown qual = SCSI_TO_SATA_ADDR_QUAL(ap->a_target);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cport = SCSI_TO_SATA_CPORT(ap->a_target);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown pmport = SCSI_TO_SATA_PMPORT(ap->a_target);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (qual != SATA_ADDR_DCPORT && qual != SATA_ADDR_DPMPORT)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown goto out;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sata_validate_sata_address(sata_hba_inst, cport, pmport, qual) ==
2038334ab26baaa43c9083f35def041511c3cc1fUnknown 0) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_cport_info_t *cportinfo;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_pmult_info_t *pmultinfo;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_drive_info_t *sdinfo = NULL;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
a9d5ae2e08c504913c088349c3d4c144f3c92be8Pawel Wojcik sata_device->satadev_addr.qual = qual;
a9d5ae2e08c504913c088349c3d4c144f3c92be8Pawel Wojcik sata_device->satadev_addr.cport = cport;
a9d5ae2e08c504913c088349c3d4c144f3c92be8Pawel Wojcik sata_device->satadev_addr.pmport = pmport;
a9d5ae2e08c504913c088349c3d4c144f3c92be8Pawel Wojcik sata_device->satadev_rev = SATA_DEVICE_REV_1;
a9d5ae2e08c504913c088349c3d4c144f3c92be8Pawel Wojcik
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rval = 1; /* Valid sata address */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cportinfo = SATA_CPORT_INFO(sata_hba_inst, cport);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (qual == SATA_ADDR_DCPORT) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (cportinfo == NULL ||
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cportinfo->cport_dev_type == SATA_DTYPE_NONE)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown goto out;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
a9d5ae2e08c504913c088349c3d4c144f3c92be8Pawel Wojcik sdinfo = SATA_CPORTINFO_DRV_INFO(cportinfo);
a9d5ae2e08c504913c088349c3d4c144f3c92be8Pawel Wojcik if (cportinfo->cport_dev_type == SATA_DTYPE_UNKNOWN &&
a9d5ae2e08c504913c088349c3d4c144f3c92be8Pawel Wojcik sdinfo != NULL) {
a9d5ae2e08c504913c088349c3d4c144f3c92be8Pawel Wojcik rval = 2;
a9d5ae2e08c504913c088349c3d4c144f3c92be8Pawel Wojcik goto out;
a9d5ae2e08c504913c088349c3d4c144f3c92be8Pawel Wojcik }
a9d5ae2e08c504913c088349c3d4c144f3c92be8Pawel Wojcik
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if ((cportinfo->cport_dev_type &
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_VALID_DEV_TYPE) == 0) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rval = -1;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown goto out;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown } else if (qual == SATA_ADDR_DPMPORT) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown pmultinfo = SATA_CPORTINFO_PMULT_INFO(cportinfo);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (pmultinfo == NULL) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rval = -1;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown goto out;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (SATA_PMPORT_INFO(sata_hba_inst, cport, pmport) ==
2038334ab26baaa43c9083f35def041511c3cc1fUnknown NULL ||
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_PMPORT_DEV_TYPE(sata_hba_inst, cport,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown pmport) == SATA_DTYPE_NONE)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown goto out;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo = SATA_PMPORT_DRV_INFO(sata_hba_inst, cport,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown pmport);
a9d5ae2e08c504913c088349c3d4c144f3c92be8Pawel Wojcik if (SATA_PMPORT_DEV_TYPE(sata_hba_inst, cport,
a9d5ae2e08c504913c088349c3d4c144f3c92be8Pawel Wojcik pmport) == SATA_DTYPE_UNKNOWN && sdinfo != NULL) {
a9d5ae2e08c504913c088349c3d4c144f3c92be8Pawel Wojcik rval = 2;
a9d5ae2e08c504913c088349c3d4c144f3c92be8Pawel Wojcik goto out;
a9d5ae2e08c504913c088349c3d4c144f3c92be8Pawel Wojcik }
a9d5ae2e08c504913c088349c3d4c144f3c92be8Pawel Wojcik
a9d5ae2e08c504913c088349c3d4c144f3c92be8Pawel Wojcik if ((SATA_PMPORT_DEV_TYPE(sata_hba_inst, cport,
a9d5ae2e08c504913c088349c3d4c144f3c92be8Pawel Wojcik pmport) && SATA_VALID_DEV_TYPE) == 0) {
a9d5ae2e08c504913c088349c3d4c144f3c92be8Pawel Wojcik rval = -1;
a9d5ae2e08c504913c088349c3d4c144f3c92be8Pawel Wojcik goto out;
a9d5ae2e08c504913c088349c3d4c144f3c92be8Pawel Wojcik }
a9d5ae2e08c504913c088349c3d4c144f3c92be8Pawel Wojcik
2038334ab26baaa43c9083f35def041511c3cc1fUnknown } else {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rval = -1;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown goto out;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if ((sdinfo == NULL) ||
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (sdinfo->satadrv_type & SATA_VALID_DEV_TYPE) == 0)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown goto out;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_device->satadev_type = sdinfo->satadrv_type;
a9d5ae2e08c504913c088349c3d4c144f3c92be8Pawel Wojcik
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (0);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknownout:
a9d5ae2e08c504913c088349c3d4c144f3c92be8Pawel Wojcik if (rval > 0) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATADBG2(SATA_DBG_SCSI_IF, sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "sata_validate_scsi_address: no valid target %x lun %x",
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ap->a_target, ap->a_lun);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (rval);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Find dip corresponding to passed device number
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Returns NULL if invalid device number is passed or device cannot be found,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Returns dip is device is found.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic dev_info_t *
2038334ab26baaa43c9083f35def041511c3cc1fUnknownsata_devt_to_devinfo(dev_t dev)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
2038334ab26baaa43c9083f35def041511c3cc1fUnknown dev_info_t *dip;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown#ifndef __lock_lint
2038334ab26baaa43c9083f35def041511c3cc1fUnknown struct devnames *dnp;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown major_t major = getmajor(dev);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown int instance = SATA_MINOR2INSTANCE(getminor(dev));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (major >= devcnt)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (NULL);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown dnp = &devnamesp[major];
2038334ab26baaa43c9083f35def041511c3cc1fUnknown LOCK_DEV_OPS(&(dnp->dn_lock));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown dip = dnp->dn_head;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown while (dip && (ddi_get_instance(dip) != instance)) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown dip = ddi_get_next(dip);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown UNLOCK_DEV_OPS(&(dnp->dn_lock));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown#endif
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (dip);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Probe device.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * This function issues Identify Device command and initializes local
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * sata_drive_info structure if the device can be identified.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * The device type is determined by examining Identify Device
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * command response.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * If the sata_hba_inst has linked drive info structure for this
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * device address, the Identify Device data is stored into sata_drive_info
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * structure linked to the port info structure.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown *
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * sata_device has to refer to the valid sata port(s) for HBA described
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * by sata_hba_inst structure.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown *
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Returns:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * SATA_SUCCESS if device type was successfully probed and port-linked
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * drive info structure was updated;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * SATA_FAILURE if there is no device, or device was not probed
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * successully;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * SATA_RETRY if device probe can be retried later.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * If a device cannot be identified, sata_device's dev_state and dev_type
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * fields are set to unknown.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * There are no retries in this function. Any retries should be managed by
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * the caller.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic int
2038334ab26baaa43c9083f35def041511c3cc1fUnknownsata_probe_device(sata_hba_inst_t *sata_hba_inst, sata_device_t *sata_device)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_pmport_info_t *pmportinfo;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_drive_info_t *sdinfo;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_drive_info_t new_sdinfo; /* local drive info struct */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown int rval;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ASSERT((SATA_CPORT_STATE(sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_device->satadev_addr.cport) &
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (SATA_STATE_PROBED | SATA_STATE_READY)) != 0);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_device->satadev_type = SATA_DTYPE_NONE;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_enter(&(SATA_CPORT_MUTEX(sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_device->satadev_addr.cport)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (sata_device->satadev_addr.qual == SATA_ADDR_DPMPORT) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo = SATA_PMPORT_INFO(sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device->satadev_addr.cport,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device->satadev_addr.pmport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang ASSERT(pmportinfo != NULL);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Get pointer to port-linked sata device info structure */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo = sata_get_device_info(sata_hba_inst, sata_device);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sdinfo != NULL) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_state &=
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ~(SATA_STATE_PROBED | SATA_STATE_READY);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_state |= SATA_STATE_PROBING;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown } else {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* No device to probe */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_device->satadev_addr.cport)));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_device->satadev_type = SATA_DTYPE_NONE;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_device->satadev_state = SATA_STATE_UNKNOWN;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (SATA_FAILURE);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Need to issue both types of identify device command and
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * determine device type by examining retreived data/status.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * First, ATA Identify Device.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown bzero(&new_sdinfo, sizeof (sata_drive_info_t));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown new_sdinfo.satadrv_addr = sata_device->satadev_addr;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_device->satadev_addr.cport)));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown new_sdinfo.satadrv_type = SATA_DTYPE_ATADISK;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rval = sata_identify_device(sata_hba_inst, &new_sdinfo);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (rval == SATA_RETRY) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* We may try to check for ATAPI device */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (SATA_FEATURES(sata_hba_inst) & SATA_CTLF_ATAPI) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * HBA supports ATAPI - try to issue Identify Packet
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Device command.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China new_sdinfo.satadrv_type = SATA_DTYPE_ATAPI;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rval = sata_identify_device(sata_hba_inst, &new_sdinfo);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (rval == SATA_SUCCESS) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Got something responding positively to ATA Identify Device
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * or to Identify Packet Device cmd.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Save last used device type.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_device->satadev_type = new_sdinfo.satadrv_type;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* save device info, if possible */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_enter(&(SATA_CPORT_MUTEX(sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_device->satadev_addr.cport)));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo = sata_get_device_info(sata_hba_inst, sata_device);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sdinfo == NULL) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_device->satadev_addr.cport)));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (SATA_FAILURE);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Copy drive info into the port-linked drive info structure.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown *sdinfo = new_sdinfo;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_state &= ~SATA_STATE_PROBING;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_state |= SATA_STATE_PROBED;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sata_device->satadev_addr.qual == SATA_ADDR_DCPORT)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_CPORT_DEV_TYPE(sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_device->satadev_addr.cport) =
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_type;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang else { /* SATA_ADDR_DPMPORT */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&pmportinfo->pmport_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_PMPORT_DEV_TYPE(sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_device->satadev_addr.cport,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_device->satadev_addr.pmport) =
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_type;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_device->satadev_addr.cport)));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (SATA_SUCCESS);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * It may be SATA_RETRY or SATA_FAILURE return.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Looks like we cannot determine the device type at this time.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_enter(&(SATA_CPORT_MUTEX(sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_device->satadev_addr.cport)));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo = sata_get_device_info(sata_hba_inst, sata_device);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sdinfo != NULL) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_device->satadev_type = SATA_DTYPE_UNKNOWN;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_type = SATA_DTYPE_UNKNOWN;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_state &= ~SATA_STATE_PROBING;
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw sdinfo->satadrv_state |= SATA_STATE_PROBED;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sata_device->satadev_addr.qual == SATA_ADDR_DCPORT)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_CPORT_DEV_TYPE(sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_device->satadev_addr.cport) =
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_DTYPE_UNKNOWN;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown else {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* SATA_ADDR_DPMPORT */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&pmportinfo->pmport_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if ((SATA_PMULT_INFO(sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_device->satadev_addr.cport) != NULL) &&
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (SATA_PMPORT_INFO(sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_device->satadev_addr.cport,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_device->satadev_addr.pmport) != NULL))
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_PMPORT_DEV_TYPE(sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_device->satadev_addr.cport,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_device->satadev_addr.pmport) =
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_DTYPE_UNKNOWN;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&pmportinfo->pmport_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_device->satadev_addr.cport)));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (rval);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
a9d5ae2e08c504913c088349c3d4c144f3c92be8Pawel Wojcik
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Get pointer to sata_drive_info structure.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * The sata_device has to contain address (cport, pmport and qualifier) for
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * specified sata_scsi structure.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown *
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Returns NULL if device address is not valid for this HBA configuration.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Otherwise, returns a pointer to sata_drive_info structure.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown *
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * This function should be called with a port mutex held.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic sata_drive_info_t *
2038334ab26baaa43c9083f35def041511c3cc1fUnknownsata_get_device_info(sata_hba_inst_t *sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_device_t *sata_device)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
2038334ab26baaa43c9083f35def041511c3cc1fUnknown uint8_t cport = sata_device->satadev_addr.cport;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown uint8_t pmport = sata_device->satadev_addr.pmport;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown uint8_t qual = sata_device->satadev_addr.qual;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (cport >= SATA_NUM_CPORTS(sata_hba_inst))
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (NULL);
37a077ef1920ee044b2887247b2a802e726d3368ls
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (!(SATA_CPORT_STATE(sata_hba_inst, cport) &
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (SATA_STATE_PROBED | SATA_STATE_READY)))
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Port not probed yet */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (SATA_CPORT_DEV_TYPE(sata_hba_inst, cport) == SATA_DTYPE_NONE)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (qual == SATA_ADDR_DCPORT) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Request for a device on a controller port */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (SATA_CPORT_DEV_TYPE(sata_hba_inst, cport) ==
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_DTYPE_PMULT)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Port multiplier attached */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (NULL);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (SATA_CPORT_DRV_INFO(sata_hba_inst, cport));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (qual == SATA_ADDR_DPMPORT) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (SATA_CPORT_DEV_TYPE(sata_hba_inst, cport) !=
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_DTYPE_PMULT)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (pmport > SATA_NUM_PMPORTS(sata_hba_inst, cport))
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (!(SATA_PMPORT_STATE(sata_hba_inst, cport, pmport) &
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (SATA_STATE_PROBED | SATA_STATE_READY)))
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Port multiplier port not probed yet */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang return (NULL);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (SATA_PMPORT_DRV_INFO(sata_hba_inst, cport, pmport));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* we should not get here */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (NULL);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown}
7a70ede882eacbae00c8d5209afb443e7755684cpawelw
7a70ede882eacbae00c8d5209afb443e7755684cpawelw
2038334ab26baaa43c9083f35def041511c3cc1fUnknown/*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * sata_identify_device.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Send Identify Device command to SATA HBA driver.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * If command executes successfully, update sata_drive_info structure pointed
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * to by sdinfo argument, including Identify Device data.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * If command fails, invalidate data in sata_drive_info.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown *
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Cannot be called from interrupt level.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown *
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Returns:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * SATA_SUCCESS if the device was identified as a supported device,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * SATA_RETRY if the device was not identified but could be retried,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * SATA_FAILURE if the device was not identified and identify attempt
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * should not be retried.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic int
2038334ab26baaa43c9083f35def041511c3cc1fUnknownsata_identify_device(sata_hba_inst_t *sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_drive_info_t *sdinfo)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown{
2038334ab26baaa43c9083f35def041511c3cc1fUnknown uint16_t cfg_word;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown int rval;
7a70ede882eacbae00c8d5209afb443e7755684cpawelw
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* fetch device identify data */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if ((rval = sata_fetch_device_identify_data(sata_hba_inst,
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China sdinfo)) != SATA_SUCCESS)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown goto fail_unknown;
7a70ede882eacbae00c8d5209afb443e7755684cpawelw
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cfg_word = sdinfo->satadrv_id.ai_config;
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China /* Set the correct device type */
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China if ((cfg_word & SATA_ATA_TYPE_MASK) == SATA_ATA_TYPE) {
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China sdinfo->satadrv_type = SATA_DTYPE_ATADISK;
2ce278eb5cbdc9cfe3f361f2144877964b5a35cbying tian - Beijing China } else if (cfg_word == SATA_CFA_TYPE) {
2ce278eb5cbdc9cfe3f361f2144877964b5a35cbying tian - Beijing China /* It's a Compact Flash media via CF-to-SATA HDD adapter */
2ce278eb5cbdc9cfe3f361f2144877964b5a35cbying tian - Beijing China sdinfo->satadrv_type = SATA_DTYPE_ATADISK;
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China } else if ((cfg_word & SATA_ATAPI_TYPE_MASK) == SATA_ATAPI_TYPE) {
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China switch (cfg_word & SATA_ATAPI_ID_DEV_TYPE) {
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China case SATA_ATAPI_CDROM_DEV:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_type = SATA_DTYPE_ATAPICD;
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China break;
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China case SATA_ATAPI_SQACC_DEV:
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China sdinfo->satadrv_type = SATA_DTYPE_ATAPITAPE;
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China break;
f8a673ad9145b262edb65a98fb3fb92027d23a05ying tian - Beijing China case SATA_ATAPI_DIRACC_DEV:
f8a673ad9145b262edb65a98fb3fb92027d23a05ying tian - Beijing China sdinfo->satadrv_type = SATA_DTYPE_ATAPIDISK;
f8a673ad9145b262edb65a98fb3fb92027d23a05ying tian - Beijing China break;
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China default:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_type = SATA_DTYPE_UNKNOWN;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China } else {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_type = SATA_DTYPE_UNKNOWN;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sdinfo->satadrv_type == SATA_DTYPE_ATADISK) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sdinfo->satadrv_capacity == 0) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Non-LBA disk. Too bad... */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_log(sata_hba_inst, CE_WARN,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "SATA disk device at port %d does not support LBA",
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_addr.cport);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rval = SATA_FAILURE;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown goto fail_unknown;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown#if 0
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Left for historical reason */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Some initial version of SATA spec indicated that at least
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * UDMA mode 4 has to be supported. It is not metioned in
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * SerialATA 2.6, so this restriction is removed.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Check for Ultra DMA modes 6 through 0 being supported */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown for (i = 6; i >= 0; --i) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sdinfo->satadrv_id.ai_ultradma & (1 << i))
2038334ab26baaa43c9083f35def041511c3cc1fUnknown break;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
7a70ede882eacbae00c8d5209afb443e7755684cpawelw
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * At least UDMA 4 mode has to be supported. If mode 4 or
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * higher are not supported by the device, fail this
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * device.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (i < 4) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* No required Ultra DMA mode supported */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_log(sata_hba_inst, CE_WARN,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "SATA disk device at port %d does not support UDMA "
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "mode 4 or higher", sdinfo->satadrv_addr.cport);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_LOG_D((sata_hba_inst, CE_WARN,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "mode 4 or higher required, %d supported", i));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rval = SATA_FAILURE;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown goto fail_unknown;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
7a70ede882eacbae00c8d5209afb443e7755684cpawelw#endif
7a70ede882eacbae00c8d5209afb443e7755684cpawelw
56a5a29002624d0066b8f8954864ce6212844611ying tian - Beijing China /*
56a5a29002624d0066b8f8954864ce6212844611ying tian - Beijing China * For Disk devices, if it doesn't support UDMA mode, we would
56a5a29002624d0066b8f8954864ce6212844611ying tian - Beijing China * like to return failure directly.
56a5a29002624d0066b8f8954864ce6212844611ying tian - Beijing China */
56a5a29002624d0066b8f8954864ce6212844611ying tian - Beijing China if ((sdinfo->satadrv_type == SATA_DTYPE_ATADISK) &&
56a5a29002624d0066b8f8954864ce6212844611ying tian - Beijing China !((sdinfo->satadrv_id.ai_validinfo & SATA_VALIDINFO_88) != 0 &&
56a5a29002624d0066b8f8954864ce6212844611ying tian - Beijing China (sdinfo->satadrv_id.ai_ultradma & SATA_UDMA_SUP_MASK) != 0)) {
56a5a29002624d0066b8f8954864ce6212844611ying tian - Beijing China sata_log(sata_hba_inst, CE_WARN,
56a5a29002624d0066b8f8954864ce6212844611ying tian - Beijing China "SATA disk device at port %d does not support UDMA",
56a5a29002624d0066b8f8954864ce6212844611ying tian - Beijing China sdinfo->satadrv_addr.cport);
56a5a29002624d0066b8f8954864ce6212844611ying tian - Beijing China rval = SATA_FAILURE;
56a5a29002624d0066b8f8954864ce6212844611ying tian - Beijing China goto fail_unknown;
56a5a29002624d0066b8f8954864ce6212844611ying tian - Beijing China }
56a5a29002624d0066b8f8954864ce6212844611ying tian - Beijing China
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (SATA_SUCCESS);
7a70ede882eacbae00c8d5209afb443e7755684cpawelw
2038334ab26baaa43c9083f35def041511c3cc1fUnknownfail_unknown:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Invalidate sata_drive_info ? */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_type = SATA_DTYPE_UNKNOWN;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_state = SATA_STATE_UNKNOWN;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (rval);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown}
7a70ede882eacbae00c8d5209afb443e7755684cpawelw
2038334ab26baaa43c9083f35def041511c3cc1fUnknown/*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Log/display device information
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic void
2038334ab26baaa43c9083f35def041511c3cc1fUnknownsata_show_drive_info(sata_hba_inst_t *sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_drive_info_t *sdinfo)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown{
2038334ab26baaa43c9083f35def041511c3cc1fUnknown int valid_version;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown char msg_buf[MAXPATHLEN];
2038334ab26baaa43c9083f35def041511c3cc1fUnknown int i;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Show HBA path */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (void) ddi_pathname(SATA_DIP(sata_hba_inst), msg_buf);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cmn_err(CE_CONT, "?%s :\n", msg_buf);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China switch (sdinfo->satadrv_type) {
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China case SATA_DTYPE_ATADISK:
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China (void) sprintf(msg_buf, "SATA disk device at");
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China break;
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China case SATA_DTYPE_ATAPICD:
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China (void) sprintf(msg_buf, "SATA CD/DVD (ATAPI) device at");
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China break;
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China case SATA_DTYPE_ATAPITAPE:
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China (void) sprintf(msg_buf, "SATA tape (ATAPI) device at");
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China break;
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China
f8a673ad9145b262edb65a98fb3fb92027d23a05ying tian - Beijing China case SATA_DTYPE_ATAPIDISK:
f8a673ad9145b262edb65a98fb3fb92027d23a05ying tian - Beijing China (void) sprintf(msg_buf, "SATA disk (ATAPI) device at");
f8a673ad9145b262edb65a98fb3fb92027d23a05ying tian - Beijing China break;
f8a673ad9145b262edb65a98fb3fb92027d23a05ying tian - Beijing China
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China case SATA_DTYPE_UNKNOWN:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (void) sprintf(msg_buf,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "Unsupported SATA device type (cfg 0x%x) at ",
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_id.ai_config);
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China break;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sdinfo->satadrv_addr.qual == SATA_ADDR_DCPORT)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cmn_err(CE_CONT, "?\t%s port %d\n",
2038334ab26baaa43c9083f35def041511c3cc1fUnknown msg_buf, sdinfo->satadrv_addr.cport);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown else
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cmn_err(CE_CONT, "?\t%s port %d:%d\n",
2038334ab26baaa43c9083f35def041511c3cc1fUnknown msg_buf, sdinfo->satadrv_addr.cport,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_addr.pmport);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown bcopy(&sdinfo->satadrv_id.ai_model, msg_buf,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sizeof (sdinfo->satadrv_id.ai_model));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown swab(msg_buf, msg_buf, sizeof (sdinfo->satadrv_id.ai_model));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown msg_buf[sizeof (sdinfo->satadrv_id.ai_model)] = '\0';
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cmn_err(CE_CONT, "?\tmodel %s\n", msg_buf);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown bcopy(&sdinfo->satadrv_id.ai_fw, msg_buf,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sizeof (sdinfo->satadrv_id.ai_fw));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown swab(msg_buf, msg_buf, sizeof (sdinfo->satadrv_id.ai_fw));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown msg_buf[sizeof (sdinfo->satadrv_id.ai_fw)] = '\0';
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cmn_err(CE_CONT, "?\tfirmware %s\n", msg_buf);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown bcopy(&sdinfo->satadrv_id.ai_drvser, msg_buf,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sizeof (sdinfo->satadrv_id.ai_drvser));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown swab(msg_buf, msg_buf, sizeof (sdinfo->satadrv_id.ai_drvser));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown msg_buf[sizeof (sdinfo->satadrv_id.ai_drvser)] = '\0';
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sdinfo->satadrv_type == SATA_DTYPE_ATADISK) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cmn_err(CE_CONT, "?\tserial number %s\n", msg_buf);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China * Some drives do not implement serial number and may
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China * violate the spec by providing spaces rather than zeros
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * in serial number field. Scan the buffer to detect it.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown for (i = 0; i < sizeof (sdinfo->satadrv_id.ai_drvser); i++) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (msg_buf[i] != '\0' && msg_buf[i] != ' ')
2038334ab26baaa43c9083f35def041511c3cc1fUnknown break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (i == sizeof (sdinfo->satadrv_id.ai_drvser)) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cmn_err(CE_CONT, "?\tserial number - none\n");
2038334ab26baaa43c9083f35def041511c3cc1fUnknown } else {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cmn_err(CE_CONT, "?\tserial number %s\n", msg_buf);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown#ifdef SATA_DEBUG
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sdinfo->satadrv_id.ai_majorversion != 0 &&
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_id.ai_majorversion != 0xffff) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown int i;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown for (i = 14; i >= 2; i--) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sdinfo->satadrv_id.ai_majorversion & (1 << i)) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown valid_version = i;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown break;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
4360436b3c604bc28d37be269ad152b4c38157c3pawelw }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cmn_err(CE_CONT,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "?\tATA/ATAPI-%d supported, majver 0x%x minver 0x%x\n",
2038334ab26baaa43c9083f35def041511c3cc1fUnknown valid_version,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_id.ai_majorversion,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_id.ai_minorversion);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown#endif
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Log some info */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cmn_err(CE_CONT, "?\tsupported features:\n");
2038334ab26baaa43c9083f35def041511c3cc1fUnknown msg_buf[0] = '\0';
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sdinfo->satadrv_type == SATA_DTYPE_ATADISK) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sdinfo->satadrv_features_support & SATA_DEV_F_LBA48)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (void) strlcat(msg_buf, "48-bit LBA, ", MAXPATHLEN);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown else if (sdinfo->satadrv_features_support & SATA_DEV_F_LBA28)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (void) strlcat(msg_buf, "28-bit LBA, ", MAXPATHLEN);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sdinfo->satadrv_features_support & SATA_DEV_F_DMA)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (void) strlcat(msg_buf, "DMA", MAXPATHLEN);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sdinfo->satadrv_features_support & SATA_DEV_F_NCQ)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (void) strlcat(msg_buf, ", Native Command Queueing",
2038334ab26baaa43c9083f35def041511c3cc1fUnknown MAXPATHLEN);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sdinfo->satadrv_features_support & SATA_DEV_F_TCQ)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (void) strlcat(msg_buf, ", Legacy Tagged Queuing", MAXPATHLEN);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if ((sdinfo->satadrv_id.ai_cmdset82 & SATA_SMART_SUPPORTED) &&
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (sdinfo->satadrv_id.ai_features85 & SATA_SMART_ENABLED))
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (void) strlcat(msg_buf, ", SMART", MAXPATHLEN);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if ((sdinfo->satadrv_id.ai_cmdset84 & SATA_SMART_SELF_TEST_SUPPORTED) &&
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (sdinfo->satadrv_id.ai_features87 & SATA_SMART_SELF_TEST_SUPPORTED))
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (void) strlcat(msg_buf, ", SMART self-test", MAXPATHLEN);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cmn_err(CE_CONT, "?\t %s\n", msg_buf);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sdinfo->satadrv_features_support & SATA_DEV_F_SATA2)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cmn_err(CE_CONT, "?\tSATA Gen2 signaling speed (3.0Gbps)\n");
2038334ab26baaa43c9083f35def041511c3cc1fUnknown else if (sdinfo->satadrv_features_support & SATA_DEV_F_SATA1)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cmn_err(CE_CONT, "?\tSATA Gen1 signaling speed (1.5Gbps)\n");
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sdinfo->satadrv_features_support &
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (SATA_DEV_F_TCQ | SATA_DEV_F_NCQ)) {
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw msg_buf[0] = '\0';
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw (void) snprintf(msg_buf, MAXPATHLEN,
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw "Supported queue depth %d",
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_queue_depth);
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw if (!(sata_func_enable &
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw (SATA_ENABLE_QUEUING | SATA_ENABLE_NCQ)))
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw (void) strlcat(msg_buf,
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw " - queueing disabled globally", MAXPATHLEN);
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw else if (sdinfo->satadrv_queue_depth >
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw sdinfo->satadrv_max_queue_depth) {
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw (void) snprintf(&msg_buf[strlen(msg_buf)],
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw MAXPATHLEN - strlen(msg_buf), ", limited to %d",
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw (int)sdinfo->satadrv_max_queue_depth);
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw }
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw cmn_err(CE_CONT, "?\t%s\n", msg_buf);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sdinfo->satadrv_type == SATA_DTYPE_ATADISK) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown#ifdef __i386
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (void) sprintf(msg_buf, "\tcapacity = %llu sectors\n",
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_capacity);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown#else
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (void) sprintf(msg_buf, "\tcapacity = %lu sectors\n",
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_capacity);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown#endif
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cmn_err(CE_CONT, "?%s", msg_buf);
4360436b3c604bc28d37be269ad152b4c38157c3pawelw }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang/*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Log/display port multiplier information
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang * No Mutex should be hold.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhangstatic void
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhangsata_show_pmult_info(sata_hba_inst_t *sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device_t *sata_device)
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang{
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang _NOTE(ARGUNUSED(sata_hba_inst))
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang int cport = sata_device->satadev_addr.cport;
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang sata_pmult_info_t *pmultinfo;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang char msg_buf[MAXPATHLEN];
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang uint32_t gscr0, gscr1, gscr2, gscr64;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang mutex_enter(&SATA_CPORT_MUTEX(sata_hba_inst, cport));
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang pmultinfo = SATA_PMULT_INFO(sata_hba_inst, cport);
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang if (pmultinfo == NULL)
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang return;
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang gscr0 = pmultinfo->pmult_gscr.gscr0;
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang gscr1 = pmultinfo->pmult_gscr.gscr1;
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang gscr2 = pmultinfo->pmult_gscr.gscr2;
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang gscr64 = pmultinfo->pmult_gscr.gscr64;
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang mutex_exit(&SATA_CPORT_MUTEX(sata_hba_inst, cport));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cmn_err(CE_CONT, "?Port Multiplier %d device-ports found at port %d",
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device->satadev_add_info, sata_device->satadev_addr.cport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (void) sprintf(msg_buf, "\tVendor_ID 0x%04x, Module_ID 0x%04x",
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang gscr0 & 0xffff, (gscr0 >> 16) & 0xffff);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cmn_err(CE_CONT, "?%s", msg_buf);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (void) strcpy(msg_buf, "\tSupport SATA PMP Spec ");
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (gscr1 & (1 << 3))
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (void) strlcat(msg_buf, "1.2", MAXPATHLEN);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang else if (gscr1 & (1 << 2))
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (void) strlcat(msg_buf, "1.1", MAXPATHLEN);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang else if (gscr1 & (1 << 1))
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (void) strlcat(msg_buf, "1.0", MAXPATHLEN);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang else
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (void) strlcat(msg_buf, "unknown", MAXPATHLEN);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cmn_err(CE_CONT, "?%s", msg_buf);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (void) strcpy(msg_buf, "\tSupport ");
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (gscr64 & (1 << 3))
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (void) strlcat(msg_buf, "Asy-Notif, ",
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang MAXPATHLEN);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (gscr64 & (1 << 2))
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (void) strlcat(msg_buf, "Dyn-SSC, ", MAXPATHLEN);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (gscr64 & (1 << 1))
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (void) strlcat(msg_buf, "Iss-PMREQ, ", MAXPATHLEN);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (gscr64 & (1 << 0))
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (void) strlcat(msg_buf, "BIST", MAXPATHLEN);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if ((gscr64 & 0xf) == 0)
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (void) strlcat(msg_buf, "nothing", MAXPATHLEN);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cmn_err(CE_CONT, "?%s", msg_buf);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (void) sprintf(msg_buf, "\tNumber of exposed device fan-out ports: %d",
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang gscr2 & SATA_PMULT_PORTNUM_MASK);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cmn_err(CE_CONT, "?%s", msg_buf);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown/*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * sata_save_drive_settings extracts current setting of the device and stores
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * it for future reference, in case the device setup would need to be restored
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * after the device reset.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown *
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * For all devices read ahead and write cache settings are saved, if the
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * device supports these features at all.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * For ATAPI devices the Removable Media Status Notification setting is saved.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic void
2038334ab26baaa43c9083f35def041511c3cc1fUnknownsata_save_drive_settings(sata_drive_info_t *sdinfo)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown{
7095af1983f107c8b16839f70101fdf710c4e620ying tian - Beijing China if (SATA_READ_AHEAD_SUPPORTED(sdinfo->satadrv_id) ||
7095af1983f107c8b16839f70101fdf710c4e620ying tian - Beijing China SATA_WRITE_CACHE_SUPPORTED(sdinfo->satadrv_id)) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Current setting of Read Ahead (and Read Cache) */
7095af1983f107c8b16839f70101fdf710c4e620ying tian - Beijing China if (SATA_READ_AHEAD_ENABLED(sdinfo->satadrv_id))
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_settings |= SATA_DEV_READ_AHEAD;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown else
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_settings &= ~SATA_DEV_READ_AHEAD;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Current setting of Write Cache */
7095af1983f107c8b16839f70101fdf710c4e620ying tian - Beijing China if (SATA_WRITE_CACHE_ENABLED(sdinfo->satadrv_id))
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_settings |= SATA_DEV_WRITE_CACHE;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown else
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_settings &= ~SATA_DEV_WRITE_CACHE;
4360436b3c604bc28d37be269ad152b4c38157c3pawelw }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sdinfo->satadrv_type == SATA_DTYPE_ATAPICD) {
7095af1983f107c8b16839f70101fdf710c4e620ying tian - Beijing China if (SATA_RM_NOTIFIC_SUPPORTED(sdinfo->satadrv_id))
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_settings |= SATA_DEV_RMSN;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown else
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_settings &= ~SATA_DEV_RMSN;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
7a70ede882eacbae00c8d5209afb443e7755684cpawelw
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * sata_check_capacity function determines a disk capacity
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * and addressing mode (LBA28/LBA48) by examining a disk identify device data.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * NOTE: CHS mode is not supported! If a device does not support LBA,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * this function is not called.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Returns device capacity in number of blocks, i.e. largest addressable LBA+1
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic uint64_t
2038334ab26baaa43c9083f35def041511c3cc1fUnknownsata_check_capacity(sata_drive_info_t *sdinfo)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
2038334ab26baaa43c9083f35def041511c3cc1fUnknown uint64_t capacity = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown int i;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sdinfo->satadrv_type != SATA_DTYPE_ATADISK ||
2038334ab26baaa43c9083f35def041511c3cc1fUnknown !sdinfo->satadrv_id.ai_cap & SATA_LBA_SUPPORT)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Capacity valid only for LBA-addressable disk devices */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (0);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if ((sdinfo->satadrv_id.ai_validinfo & SATA_VALIDINFO_88) &&
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (sdinfo->satadrv_id.ai_cmdset83 & SATA_EXT48) &&
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (sdinfo->satadrv_id.ai_features86 & SATA_EXT48)) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* LBA48 mode supported and enabled */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_features_support |= SATA_DEV_F_LBA48 |
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_DEV_F_LBA28;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown for (i = 3; i >= 0; --i) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown capacity <<= 16;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown capacity += sdinfo->satadrv_id.ai_addrsecxt[i];
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown capacity = sdinfo->satadrv_id.ai_addrsec[1];
2038334ab26baaa43c9083f35def041511c3cc1fUnknown capacity <<= 16;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown capacity += sdinfo->satadrv_id.ai_addrsec[0];
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (capacity >= 0x1000000)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* LBA28 mode */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_features_support |= SATA_DEV_F_LBA28;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (capacity);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown/*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Allocate consistent buffer for DMA transfer
2038334ab26baaa43c9083f35def041511c3cc1fUnknown *
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Cannot be called from interrupt level or with mutex held - it may sleep.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown *
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Returns pointer to allocated buffer structure, or NULL if allocation failed.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic struct buf *
2038334ab26baaa43c9083f35def041511c3cc1fUnknownsata_alloc_local_buffer(sata_pkt_txlate_t *spx, int len)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown{
2038334ab26baaa43c9083f35def041511c3cc1fUnknown struct scsi_address ap;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown struct buf *bp;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ddi_dma_attr_t cur_dma_attr;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ASSERT(spx->txlt_sata_pkt != NULL);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ap.a_hba_tran = spx->txlt_sata_hba_inst->satahba_scsi_tran;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ap.a_target = SATA_TO_SCSI_TARGET(
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_sata_pkt->satapkt_device.satadev_addr.cport,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_sata_pkt->satapkt_device.satadev_addr.pmport,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_sata_pkt->satapkt_device.satadev_addr.qual);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ap.a_lun = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown bp = scsi_alloc_consistent_buf(&ap, NULL, len,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown B_READ, SLEEP_FUNC, NULL);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (bp != NULL) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Allocate DMA resources for this buffer */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_sata_pkt->satapkt_cmd.satacmd_bp = bp;
6ed1276fb5fe78fb1cce38682748a830ef8bd157pawelw /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * We use a local version of the dma_attr, to account
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * for a device addressing limitations.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * sata_adjust_dma_attr() will handle sdinfo == NULL which
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * will cause dma attributes to be adjusted to a lowest
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * acceptable level.
6ed1276fb5fe78fb1cce38682748a830ef8bd157pawelw */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_adjust_dma_attr(NULL,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_DMA_ATTR(spx->txlt_sata_hba_inst), &cur_dma_attr);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sata_dma_buf_setup(spx, PKT_CONSISTENT,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SLEEP_FUNC, NULL, &cur_dma_attr) != DDI_SUCCESS) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scsi_free_consistent_buf(bp);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_sata_pkt->satapkt_cmd.satacmd_bp = NULL;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown bp = NULL;
6ed1276fb5fe78fb1cce38682748a830ef8bd157pawelw }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (bp);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Release local buffer (consistent buffer for DMA transfer) allocated
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * via sata_alloc_local_buffer().
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic void
2038334ab26baaa43c9083f35def041511c3cc1fUnknownsata_free_local_buffer(sata_pkt_txlate_t *spx)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ASSERT(spx->txlt_sata_pkt != NULL);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ASSERT(spx->txlt_sata_pkt->satapkt_cmd.satacmd_bp != NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_sata_pkt->satapkt_cmd.satacmd_num_dma_cookies = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_sata_pkt->satapkt_cmd.satacmd_dma_cookie_list = NULL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
378b31fa4c69b519b0e53dee7eed925cd397adc1Martin Faltesek sata_common_free_dma_rsrcs(spx);
b5fc475bca6525d8da80728128eefb7100aaf66bap
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Free buffer */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scsi_free_consistent_buf(spx->txlt_sata_pkt->satapkt_cmd.satacmd_bp);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_sata_pkt->satapkt_cmd.satacmd_bp = NULL;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw/*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Allocate sata_pkt
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Pkt structure version and embedded strcutures version are initialized.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * sata_pkt and sata_pkt_txlate structures are cross-linked.
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw *
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Since this may be called in interrupt context by sata_scsi_init_pkt,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * callback argument determines if it can sleep or not.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Hence, it should not be called from interrupt context.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown *
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * If successful, non-NULL pointer to a sata pkt is returned.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Upon failure, NULL pointer is returned.
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw */
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic sata_pkt_t *
2038334ab26baaa43c9083f35def041511c3cc1fUnknownsata_pkt_alloc(sata_pkt_txlate_t *spx, int (*callback)(caddr_t))
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw{
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw sata_pkt_t *spkt;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown int kmsflag;
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw
2038334ab26baaa43c9083f35def041511c3cc1fUnknown kmsflag = (callback == SLEEP_FUNC) ? KM_SLEEP : KM_NOSLEEP;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt = kmem_zalloc(sizeof (sata_pkt_t), kmsflag);
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw if (spkt == NULL) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_LOG_D((spx->txlt_sata_hba_inst, CE_WARN,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "sata_pkt_alloc: failed"));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (NULL);
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_rev = SATA_PKT_REV;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_cmd.satacmd_rev = SATA_CMD_REV;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_device.satadev_rev = SATA_DEVICE_REV;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_framework_private = spx;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_sata_pkt = spkt;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (spkt);
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw}
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Free sata pkt allocated via sata_pkt_alloc()
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void
2038334ab26baaa43c9083f35def041511c3cc1fUnknownsata_pkt_free(sata_pkt_txlate_t *spx)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ASSERT(spx->txlt_sata_pkt != NULL);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ASSERT(spx->txlt_sata_pkt->satapkt_cmd.satacmd_bp == NULL);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown kmem_free(spx->txlt_sata_pkt, sizeof (sata_pkt_t));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_sata_pkt = NULL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Adjust DMA attributes.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * SCSI cmds block count is up to 24 bits, SATA cmd block count vary
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * from 8 bits to 16 bits, depending on a command being used.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Limiting max block count arbitrarily to 256 for all read/write
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * commands may affects performance, so check both the device and
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * controller capability before adjusting dma attributes.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
2038334ab26baaa43c9083f35def041511c3cc1fUnknownvoid
2038334ab26baaa43c9083f35def041511c3cc1fUnknownsata_adjust_dma_attr(sata_drive_info_t *sdinfo, ddi_dma_attr_t *dma_attr,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ddi_dma_attr_t *adj_dma_attr)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
2038334ab26baaa43c9083f35def041511c3cc1fUnknown uint32_t count_max;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Copy original attributes */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown *adj_dma_attr = *dma_attr;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Things to consider: device addressing capability,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * "excessive" controller DMA capabilities.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * If a device is being probed/initialized, there are
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * no device info - use default limits then.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sdinfo == NULL) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown count_max = dma_attr->dma_attr_granular * 0x100;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (dma_attr->dma_attr_count_max > count_max)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown adj_dma_attr->dma_attr_count_max = count_max;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (dma_attr->dma_attr_maxxfer > count_max)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown adj_dma_attr->dma_attr_maxxfer = count_max;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sdinfo->satadrv_type == SATA_DTYPE_ATADISK) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sdinfo->satadrv_features_support & (SATA_DEV_F_LBA48)) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * 16-bit sector count may be used - we rely on
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * the assumption that only read and write cmds
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * will request more than 256 sectors worth of data
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown count_max = adj_dma_attr->dma_attr_granular * 0x10000;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown } else {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * 8-bit sector count will be used - default limits
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * for dma attributes
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown count_max = adj_dma_attr->dma_attr_granular * 0x100;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Adjust controler dma attributes, if necessary
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (dma_attr->dma_attr_count_max > count_max)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown adj_dma_attr->dma_attr_count_max = count_max;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (dma_attr->dma_attr_maxxfer > count_max)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown adj_dma_attr->dma_attr_maxxfer = count_max;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Allocate DMA resources for the buffer
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * This function handles initial DMA resource allocation as well as
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * DMA window shift and may be called repeatedly for the same DMA window
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * until all DMA cookies in the DMA window are processed.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * To guarantee that there is always a coherent set of cookies to process
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * by SATA HBA driver (observing alignment, device granularity, etc.),
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * the number of slots for DMA cookies is equal to lesser of a number of
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * cookies in a DMA window and a max number of scatter/gather entries.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Returns DDI_SUCCESS upon successful operation.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Return failure code of a failing command or DDI_FAILURE when
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * internal cleanup failed.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic int
2038334ab26baaa43c9083f35def041511c3cc1fUnknownsata_dma_buf_setup(sata_pkt_txlate_t *spx, int flags,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown int (*callback)(caddr_t), caddr_t arg,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ddi_dma_attr_t *cur_dma_attr)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
2038334ab26baaa43c9083f35def041511c3cc1fUnknown int rval;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown off_t offset;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown size_t size;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown int max_sg_len, req_len, i;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown uint_t dma_flags;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown struct buf *bp;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown uint64_t cur_txfer_len;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ASSERT(spx->txlt_sata_pkt != NULL);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown bp = spx->txlt_sata_pkt->satapkt_cmd.satacmd_bp;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ASSERT(bp != NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (spx->txlt_buf_dma_handle == NULL) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * No DMA resources allocated so far - this is a first call
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * for this sata pkt.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rval = ddi_dma_alloc_handle(SATA_DIP(spx->txlt_sata_hba_inst),
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cur_dma_attr, callback, arg, &spx->txlt_buf_dma_handle);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (rval != DDI_SUCCESS) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_LOG_D((spx->txlt_sata_hba_inst, CE_WARN,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "sata_dma_buf_setup: no buf DMA resources %x",
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rval));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (rval);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (bp->b_flags & B_READ)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown dma_flags = DDI_DMA_READ;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown else
2038334ab26baaa43c9083f35def041511c3cc1fUnknown dma_flags = DDI_DMA_WRITE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (flags & PKT_CONSISTENT)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown dma_flags |= DDI_DMA_CONSISTENT;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (flags & PKT_DMA_PARTIAL)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown dma_flags |= DDI_DMA_PARTIAL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Check buffer alignment and size against dma attributes
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Consider dma_attr_align only. There may be requests
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * with the size lower than device granularity, but they
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * will not read/write from/to the device, so no adjustment
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * is necessary. The dma_attr_minxfer theoretically should
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * be considered, but no HBA driver is checking it.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (IS_P2ALIGNED(bp->b_un.b_addr,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cur_dma_attr->dma_attr_align)) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rval = ddi_dma_buf_bind_handle(
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_buf_dma_handle,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown bp, dma_flags, callback, arg,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown &spx->txlt_dma_cookie,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown &spx->txlt_curwin_num_dma_cookies);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown } else { /* Buffer is not aligned */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown int (*ddicallback)(caddr_t);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown size_t bufsz;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Check id sleeping is allowed */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ddicallback = (callback == NULL_FUNC) ?
2038334ab26baaa43c9083f35def041511c3cc1fUnknown DDI_DMA_DONTWAIT : DDI_DMA_SLEEP;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATADBG2(SATA_DBG_DMA_SETUP, spx->txlt_sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "mis-aligned buffer: addr=0x%p, cnt=%lu",
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (void *)bp->b_un.b_addr, bp->b_bcount);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (bp->b_flags & (B_PAGEIO|B_PHYS))
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * CPU will need to access data in the buffer
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * (for copying) so map it.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown bp_mapin(bp);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ASSERT(spx->txlt_tmp_buf == NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Buffer may be padded by ddi_dma_mem_alloc()! */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rval = ddi_dma_mem_alloc(
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_buf_dma_handle,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown bp->b_bcount,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown &sata_acc_attr,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown DDI_DMA_STREAMING,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ddicallback, NULL,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown &spx->txlt_tmp_buf,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown &bufsz,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown &spx->txlt_tmp_buf_handle);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (rval != DDI_SUCCESS) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* DMA mapping failed */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (void) ddi_dma_free_handle(
2038334ab26baaa43c9083f35def041511c3cc1fUnknown &spx->txlt_buf_dma_handle);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_buf_dma_handle = NULL;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown#ifdef SATA_DEBUG
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mbuffail_count++;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown#endif
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATADBG1(SATA_DBG_DMA_SETUP,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "sata_dma_buf_setup: "
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "buf dma mem alloc failed %x\n", rval);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (rval);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ASSERT(IS_P2ALIGNED(spx->txlt_tmp_buf,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cur_dma_attr->dma_attr_align));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown#ifdef SATA_DEBUG
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mbuf_count++;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (bp->b_bcount != bufsz)
4360436b3c604bc28d37be269ad152b4c38157c3pawelw /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * This will require special handling, because
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * DMA cookies will be based on the temporary
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * buffer size, not the original buffer
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * b_bcount, so the residue may have to
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * be counted differently.
4360436b3c604bc28d37be269ad152b4c38157c3pawelw */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATADBG2(SATA_DBG_DMA_SETUP,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "sata_dma_buf_setup: bp size %x != "
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "bufsz %x\n", bp->b_bcount, bufsz);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown#endif
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (dma_flags & DDI_DMA_WRITE) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Write operation - copy data into
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * an aligned temporary buffer. Buffer will be
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * synced for device by ddi_dma_addr_bind_handle
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown bcopy(bp->b_un.b_addr, spx->txlt_tmp_buf,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown bp->b_bcount);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rval = ddi_dma_addr_bind_handle(
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_buf_dma_handle,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown NULL,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_tmp_buf,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown bufsz, dma_flags, ddicallback, 0,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown &spx->txlt_dma_cookie,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown &spx->txlt_curwin_num_dma_cookies);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown switch (rval) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown case DDI_DMA_PARTIAL_MAP:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATADBG1(SATA_DBG_DMA_SETUP, spx->txlt_sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "sata_dma_buf_setup: DMA Partial Map\n", NULL);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Partial DMA mapping.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Retrieve number of DMA windows for this request.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (ddi_dma_numwin(spx->txlt_buf_dma_handle,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown &spx->txlt_num_dma_win) != DDI_SUCCESS) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (spx->txlt_tmp_buf != NULL) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ddi_dma_mem_free(
2038334ab26baaa43c9083f35def041511c3cc1fUnknown &spx->txlt_tmp_buf_handle);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_tmp_buf = NULL;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (void) ddi_dma_unbind_handle(
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_buf_dma_handle);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (void) ddi_dma_free_handle(
2038334ab26baaa43c9083f35def041511c3cc1fUnknown &spx->txlt_buf_dma_handle);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_buf_dma_handle = NULL;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_LOG_D((spx->txlt_sata_hba_inst, CE_WARN,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "sata_dma_buf_setup: numwin failed\n"));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (DDI_FAILURE);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATADBG2(SATA_DBG_DMA_SETUP,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "sata_dma_buf_setup: windows: %d, cookies: %d\n",
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_num_dma_win,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_curwin_num_dma_cookies);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_cur_dma_win = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown break;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown case DDI_DMA_MAPPED:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* DMA fully mapped */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_num_dma_win = 1;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_cur_dma_win = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATADBG1(SATA_DBG_DMA_SETUP,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "sata_dma_buf_setup: windows: 1 "
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "cookies: %d\n", spx->txlt_curwin_num_dma_cookies);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown break;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown default:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* DMA mapping failed */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (spx->txlt_tmp_buf != NULL) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ddi_dma_mem_free(
2038334ab26baaa43c9083f35def041511c3cc1fUnknown &spx->txlt_tmp_buf_handle);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_tmp_buf = NULL;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (void) ddi_dma_free_handle(&spx->txlt_buf_dma_handle);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_buf_dma_handle = NULL;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_LOG_D((spx->txlt_sata_hba_inst, CE_WARN,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "sata_dma_buf_setup: buf dma handle binding "
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "failed %x\n", rval));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (rval);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_curwin_processed_dma_cookies = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_dma_cookie_list = NULL;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown } else {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * DMA setup is reused. Check if we need to process more
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * cookies in current window, or to get next window, if any.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ASSERT(spx->txlt_curwin_processed_dma_cookies <=
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_curwin_num_dma_cookies);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (spx->txlt_curwin_processed_dma_cookies ==
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_curwin_num_dma_cookies) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * All cookies from current DMA window were processed.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Get next DMA window.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_cur_dma_win++;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (spx->txlt_cur_dma_win < spx->txlt_num_dma_win) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (void) ddi_dma_getwin(spx->txlt_buf_dma_handle,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_cur_dma_win, &offset, &size,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown &spx->txlt_dma_cookie,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown &spx->txlt_curwin_num_dma_cookies);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_curwin_processed_dma_cookies = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown } else {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* No more windows! End of request! */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* What to do? - panic for now */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ASSERT(spx->txlt_cur_dma_win >=
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_num_dma_win);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_curwin_num_dma_cookies = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_curwin_processed_dma_cookies = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_sata_pkt->
2038334ab26baaa43c9083f35def041511c3cc1fUnknown satapkt_cmd.satacmd_num_dma_cookies = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (DDI_SUCCESS);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* There better be at least one DMA cookie outstanding */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ASSERT((spx->txlt_curwin_num_dma_cookies -
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_curwin_processed_dma_cookies) > 0);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (spx->txlt_dma_cookie_list == &spx->txlt_dma_cookie) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* The default cookie slot was used in previous run */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ASSERT(spx->txlt_curwin_processed_dma_cookies == 0);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_dma_cookie_list = NULL;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_dma_cookie_list_len = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (spx->txlt_curwin_processed_dma_cookies == 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Processing a new DMA window - set-up dma cookies list.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * We may reuse previously allocated cookie array if it is
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * possible.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (spx->txlt_dma_cookie_list != NULL &&
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_dma_cookie_list_len <
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_curwin_num_dma_cookies) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * New DMA window contains more cookies than
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * the previous one. We need larger cookie list - free
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * the old one.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (void) kmem_free(spx->txlt_dma_cookie_list,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_dma_cookie_list_len *
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sizeof (ddi_dma_cookie_t));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_dma_cookie_list = NULL;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_dma_cookie_list_len = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (spx->txlt_dma_cookie_list == NULL) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Calculate lesser of number of cookies in this
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * DMA window and number of s/g entries.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown max_sg_len = cur_dma_attr->dma_attr_sgllen;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown req_len = MIN(max_sg_len,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_curwin_num_dma_cookies);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Allocate new dma cookie array if necessary */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (req_len == 1) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Only one cookie - no need for a list */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_dma_cookie_list =
2038334ab26baaa43c9083f35def041511c3cc1fUnknown &spx->txlt_dma_cookie;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_dma_cookie_list_len = 1;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown } else {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * More than one cookie - try to allocate space.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_dma_cookie_list = kmem_zalloc(
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sizeof (ddi_dma_cookie_t) * req_len,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown callback == NULL_FUNC ? KM_NOSLEEP :
2038334ab26baaa43c9083f35def041511c3cc1fUnknown KM_SLEEP);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (spx->txlt_dma_cookie_list == NULL) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATADBG1(SATA_DBG_DMA_SETUP,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "sata_dma_buf_setup: cookie list "
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "allocation failed\n", NULL);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * We could not allocate space for
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * neccessary number of dma cookies in
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * this window, so we fail this request.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Next invocation would try again to
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * allocate space for cookie list.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Note:Packet residue was not modified.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (DDI_DMA_NORESOURCES);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown } else {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_dma_cookie_list_len = req_len;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Fetch DMA cookies into cookie list in sata_pkt_txlate.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * First cookie was already fetched.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown *(&spx->txlt_dma_cookie_list[0]) = spx->txlt_dma_cookie;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cur_txfer_len =
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (uint64_t)spx->txlt_dma_cookie_list[0].dmac_size;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_sata_pkt->satapkt_cmd.satacmd_num_dma_cookies = 1;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_curwin_processed_dma_cookies++;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown for (i = 1; (i < spx->txlt_dma_cookie_list_len) &&
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (i < spx->txlt_curwin_num_dma_cookies); i++) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ddi_dma_nextcookie(spx->txlt_buf_dma_handle,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown &spx->txlt_dma_cookie_list[i]);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cur_txfer_len +=
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (uint64_t)spx->txlt_dma_cookie_list[i].dmac_size;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_curwin_processed_dma_cookies++;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_sata_pkt->
2038334ab26baaa43c9083f35def041511c3cc1fUnknown satapkt_cmd.satacmd_num_dma_cookies += 1;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown } else {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATADBG2(SATA_DBG_DMA_SETUP, spx->txlt_sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "sata_dma_buf_setup: sliding within DMA window, "
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "cur cookie %d, total cookies %d\n",
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_curwin_processed_dma_cookies,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_curwin_num_dma_cookies);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Not all cookies from the current dma window were used because
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * of s/g limitation.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * There is no need to re-size the list - it was set at
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * optimal size, or only default entry is used (s/g = 1).
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (spx->txlt_dma_cookie_list == NULL) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_dma_cookie_list = &spx->txlt_dma_cookie;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_dma_cookie_list_len = 1;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Since we are processing remaining cookies in a DMA window,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * there may be less of them than the number of entries in the
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * current dma cookie list.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown req_len = MIN(spx->txlt_dma_cookie_list_len,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (spx->txlt_curwin_num_dma_cookies -
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_curwin_processed_dma_cookies));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Fetch the next batch of cookies */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown for (i = 0, cur_txfer_len = 0; i < req_len; i++) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ddi_dma_nextcookie(spx->txlt_buf_dma_handle,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown &spx->txlt_dma_cookie_list[i]);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cur_txfer_len +=
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (uint64_t)spx->txlt_dma_cookie_list[i].dmac_size;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_sata_pkt->
2038334ab26baaa43c9083f35def041511c3cc1fUnknown satapkt_cmd.satacmd_num_dma_cookies++;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_curwin_processed_dma_cookies++;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ASSERT(spx->txlt_sata_pkt->satapkt_cmd.satacmd_num_dma_cookies > 0);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Point sata_cmd to the cookie list */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_sata_pkt->satapkt_cmd.satacmd_dma_cookie_list =
2038334ab26baaa43c9083f35def041511c3cc1fUnknown &spx->txlt_dma_cookie_list[0];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Remember number of DMA cookies passed in sata packet */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_num_dma_cookies =
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_sata_pkt->satapkt_cmd.satacmd_num_dma_cookies;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ASSERT(cur_txfer_len != 0);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (cur_txfer_len <= bp->b_bcount)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_total_residue -= cur_txfer_len;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown else {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Temporary DMA buffer has been padded by
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * ddi_dma_mem_alloc()!
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * This requires special handling, because DMA cookies are
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * based on the temporary buffer size, not the b_bcount,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * and we have extra bytes to transfer - but the packet
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * residue has to stay correct because we will copy only
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * the requested number of bytes.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_total_residue -= bp->b_bcount;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (DDI_SUCCESS);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
b5fc475bca6525d8da80728128eefb7100aaf66bap/*
b5fc475bca6525d8da80728128eefb7100aaf66bap * Common routine for releasing DMA resources
b5fc475bca6525d8da80728128eefb7100aaf66bap */
b5fc475bca6525d8da80728128eefb7100aaf66bapstatic void
b5fc475bca6525d8da80728128eefb7100aaf66bapsata_common_free_dma_rsrcs(sata_pkt_txlate_t *spx)
b5fc475bca6525d8da80728128eefb7100aaf66bap{
b5fc475bca6525d8da80728128eefb7100aaf66bap if (spx->txlt_buf_dma_handle != NULL) {
b5fc475bca6525d8da80728128eefb7100aaf66bap if (spx->txlt_tmp_buf != NULL) {
b5fc475bca6525d8da80728128eefb7100aaf66bap /*
b5fc475bca6525d8da80728128eefb7100aaf66bap * Intermediate DMA buffer was allocated.
b5fc475bca6525d8da80728128eefb7100aaf66bap * Free allocated buffer and associated access handle.
b5fc475bca6525d8da80728128eefb7100aaf66bap */
b5fc475bca6525d8da80728128eefb7100aaf66bap ddi_dma_mem_free(&spx->txlt_tmp_buf_handle);
b5fc475bca6525d8da80728128eefb7100aaf66bap spx->txlt_tmp_buf = NULL;
b5fc475bca6525d8da80728128eefb7100aaf66bap }
b5fc475bca6525d8da80728128eefb7100aaf66bap /*
b5fc475bca6525d8da80728128eefb7100aaf66bap * Free DMA resources - cookies and handles
b5fc475bca6525d8da80728128eefb7100aaf66bap */
b5fc475bca6525d8da80728128eefb7100aaf66bap /* ASSERT(spx->txlt_dma_cookie_list != NULL); */
b5fc475bca6525d8da80728128eefb7100aaf66bap if (spx->txlt_dma_cookie_list != NULL) {
b5fc475bca6525d8da80728128eefb7100aaf66bap if (spx->txlt_dma_cookie_list !=
b5fc475bca6525d8da80728128eefb7100aaf66bap &spx->txlt_dma_cookie) {
b5fc475bca6525d8da80728128eefb7100aaf66bap (void) kmem_free(spx->txlt_dma_cookie_list,
b5fc475bca6525d8da80728128eefb7100aaf66bap spx->txlt_dma_cookie_list_len *
b5fc475bca6525d8da80728128eefb7100aaf66bap sizeof (ddi_dma_cookie_t));
b5fc475bca6525d8da80728128eefb7100aaf66bap spx->txlt_dma_cookie_list = NULL;
b5fc475bca6525d8da80728128eefb7100aaf66bap }
b5fc475bca6525d8da80728128eefb7100aaf66bap }
b5fc475bca6525d8da80728128eefb7100aaf66bap (void) ddi_dma_unbind_handle(spx->txlt_buf_dma_handle);
b5fc475bca6525d8da80728128eefb7100aaf66bap (void) ddi_dma_free_handle(&spx->txlt_buf_dma_handle);
b5fc475bca6525d8da80728128eefb7100aaf66bap spx->txlt_buf_dma_handle = NULL;
b5fc475bca6525d8da80728128eefb7100aaf66bap }
b5fc475bca6525d8da80728128eefb7100aaf66bap}
b5fc475bca6525d8da80728128eefb7100aaf66bap
b5fc475bca6525d8da80728128eefb7100aaf66bap/*
b5fc475bca6525d8da80728128eefb7100aaf66bap * Free DMA resources
b5fc475bca6525d8da80728128eefb7100aaf66bap * Used by the HBA driver to release DMA resources that it does not use.
b5fc475bca6525d8da80728128eefb7100aaf66bap *
b5fc475bca6525d8da80728128eefb7100aaf66bap * Returns Void
b5fc475bca6525d8da80728128eefb7100aaf66bap */
b5fc475bca6525d8da80728128eefb7100aaf66bapvoid
b5fc475bca6525d8da80728128eefb7100aaf66bapsata_free_dma_resources(sata_pkt_t *sata_pkt)
b5fc475bca6525d8da80728128eefb7100aaf66bap{
b5fc475bca6525d8da80728128eefb7100aaf66bap sata_pkt_txlate_t *spx;
b5fc475bca6525d8da80728128eefb7100aaf66bap
b5fc475bca6525d8da80728128eefb7100aaf66bap if (sata_pkt == NULL)
b5fc475bca6525d8da80728128eefb7100aaf66bap return;
b5fc475bca6525d8da80728128eefb7100aaf66bap
b5fc475bca6525d8da80728128eefb7100aaf66bap spx = (sata_pkt_txlate_t *)sata_pkt->satapkt_framework_private;
b5fc475bca6525d8da80728128eefb7100aaf66bap
b5fc475bca6525d8da80728128eefb7100aaf66bap sata_common_free_dma_rsrcs(spx);
b5fc475bca6525d8da80728128eefb7100aaf66bap}
a9d5ae2e08c504913c088349c3d4c144f3c92be8Pawel Wojcik
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Fetch Device Identify data.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Send DEVICE IDENTIFY or IDENTIFY PACKET DEVICE (depending on a device type)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * command to a device and get the device identify data.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * The device_info structure has to be set to device type (for selecting proper
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * device identify command).
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Returns:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * SATA_SUCCESS if cmd succeeded
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * SATA_RETRY if cmd was rejected and could be retried,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * SATA_FAILURE if cmd failed and should not be retried (port error)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown *
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Cannot be called in an interrupt context.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic int
2038334ab26baaa43c9083f35def041511c3cc1fUnknownsata_fetch_device_identify_data(sata_hba_inst_t *sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_drive_info_t *sdinfo)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
2038334ab26baaa43c9083f35def041511c3cc1fUnknown struct buf *bp;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_pkt_t *spkt;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_cmd_t *scmd;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_pkt_txlate_t *spx;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown int rval;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx = kmem_zalloc(sizeof (sata_pkt_txlate_t), KM_SLEEP);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_sata_hba_inst = sata_hba_inst;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_scsi_pkt = NULL; /* No scsi pkt involved */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt = sata_pkt_alloc(spx, SLEEP_FUNC);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (spkt == NULL) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown kmem_free(spx, sizeof (sata_pkt_txlate_t));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (SATA_RETRY); /* may retry later */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* address is needed now */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_device.satadev_addr = sdinfo->satadrv_addr;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Allocate buffer for Identify Data return data
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown bp = sata_alloc_local_buffer(spx, sizeof (sata_id_t));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (bp == NULL) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_pkt_free(spx);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown kmem_free(spx, sizeof (sata_pkt_txlate_t));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_LOG_D((sata_hba_inst, CE_WARN,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "sata_fetch_device_identify_data: "
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "cannot allocate buffer for ID"));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (SATA_RETRY); /* may retry later */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Fill sata_pkt */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_state = SATA_STATE_PROBING;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_device.satadev_addr = sdinfo->satadrv_addr;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_op_mode = SATA_OPMODE_SYNCH | SATA_OPMODE_INTERRUPTS;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Synchronous mode, no callback */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_comp = NULL;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Timeout 30s */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_time = sata_default_pkt_time;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd = &spkt->satapkt_cmd;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_bp = bp;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_flags.sata_data_direction = SATA_DIR_READ;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_flags.sata_ignore_dev_reset = B_TRUE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Build Identify Device cmd in the sata_pkt */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_addr_type = 0; /* N/A */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_sec_count_lsb = 0; /* N/A */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_lba_low_lsb = 0; /* N/A */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_lba_mid_lsb = 0; /* N/A */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_lba_high_lsb = 0; /* N/A */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_features_reg = 0; /* N/A */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_device_reg = 0; /* Always device 0 */
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China if (sdinfo->satadrv_type & SATA_DTYPE_ATAPI) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Identify Packet Device cmd */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_cmd_reg = SATAC_ID_PACKET_DEVICE;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown } else {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Identify Device cmd - mandatory for all other devices */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_cmd_reg = SATAC_ID_DEVICE;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Send pkt to SATA HBA driver */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rval = (*SATA_START_FUNC(sata_hba_inst))(SATA_DIP(sata_hba_inst), spkt);
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw#ifdef SATA_INJECT_FAULTS
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik sata_inject_pkt_fault(spkt, &rval, sata_fault_type);
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw#endif
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (rval == SATA_TRAN_ACCEPTED &&
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_reason == SATA_PKT_COMPLETED) {
b5fc475bca6525d8da80728128eefb7100aaf66bap if (spx->txlt_buf_dma_handle != NULL) {
b5fc475bca6525d8da80728128eefb7100aaf66bap rval = ddi_dma_sync(spx->txlt_buf_dma_handle, 0, 0,
b5fc475bca6525d8da80728128eefb7100aaf66bap DDI_DMA_SYNC_FORKERNEL);
b5fc475bca6525d8da80728128eefb7100aaf66bap ASSERT(rval == DDI_SUCCESS);
b5fc475bca6525d8da80728128eefb7100aaf66bap }
c75976d12071ddd21443266260066ba036671682pawelw if ((((sata_id_t *)(bp->b_un.b_addr))->ai_config &
c75976d12071ddd21443266260066ba036671682pawelw SATA_INCOMPLETE_DATA) == SATA_INCOMPLETE_DATA) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_LOG_D((sata_hba_inst, CE_WARN,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "SATA disk device at port %d - "
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "partial Identify Data",
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_addr.cport));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rval = SATA_RETRY; /* may retry later */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown goto fail;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Update sata_drive_info */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown bcopy(bp->b_un.b_addr, &sdinfo->satadrv_id,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sizeof (sata_id_t));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_features_support = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sdinfo->satadrv_type == SATA_DTYPE_ATADISK) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Retrieve capacity (disks only) and addressing mode
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_capacity = sata_check_capacity(sdinfo);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * For ATAPI devices one would have to issue
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Get Capacity cmd for media capacity. Not here.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_capacity = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Check what cdb length is supported
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if ((sdinfo->satadrv_id.ai_config &
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_ATAPI_ID_PKT_SZ) == SATA_ATAPI_ID_PKT_16B)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_atapi_cdb_len = 16;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown else
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_atapi_cdb_len = 12;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Setup supported features flags */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sdinfo->satadrv_id.ai_cap & SATA_DMA_SUPPORT)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_features_support |= SATA_DEV_F_DMA;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Check for SATA GEN and NCQ support */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sdinfo->satadrv_id.ai_satacap != 0 &&
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_id.ai_satacap != 0xffff) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* SATA compliance */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sdinfo->satadrv_id.ai_satacap & SATA_NCQ)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_features_support |=
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_DEV_F_NCQ;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sdinfo->satadrv_id.ai_satacap &
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (SATA_1_SPEED | SATA_2_SPEED)) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sdinfo->satadrv_id.ai_satacap &
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_2_SPEED)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_features_support |=
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_DEV_F_SATA2;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sdinfo->satadrv_id.ai_satacap &
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_1_SPEED)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_features_support |=
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_DEV_F_SATA1;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_features_support |=
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_DEV_F_SATA1;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if ((sdinfo->satadrv_id.ai_cmdset83 & SATA_RW_DMA_QUEUED_CMD) &&
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (sdinfo->satadrv_id.ai_features86 & SATA_RW_DMA_QUEUED_CMD))
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_features_support |= SATA_DEV_F_TCQ;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_queue_depth = sdinfo->satadrv_id.ai_qdepth;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if ((sdinfo->satadrv_features_support & SATA_DEV_F_NCQ) ||
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw (sdinfo->satadrv_features_support & SATA_DEV_F_TCQ)) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ++sdinfo->satadrv_queue_depth;
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw /* Adjust according to controller capabilities */
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw sdinfo->satadrv_max_queue_depth = MIN(
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw sdinfo->satadrv_queue_depth,
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw SATA_QDEPTH(sata_hba_inst));
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw /* Adjust according to global queue depth limit */
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw sdinfo->satadrv_max_queue_depth = MIN(
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw sdinfo->satadrv_max_queue_depth,
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw sata_current_max_qdepth);
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw if (sdinfo->satadrv_max_queue_depth == 0)
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw sdinfo->satadrv_max_queue_depth = 1;
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw } else
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw sdinfo->satadrv_max_queue_depth = 1;
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rval = SATA_SUCCESS;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown } else {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Woops, no Identify Data.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (rval == SATA_TRAN_BUSY || rval == SATA_TRAN_QUEUE_FULL) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rval = SATA_RETRY; /* may retry later */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown } else if (rval == SATA_TRAN_ACCEPTED) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (spkt->satapkt_reason == SATA_PKT_DEV_ERROR ||
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_reason == SATA_PKT_ABORTED ||
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_reason == SATA_PKT_TIMEOUT ||
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_reason == SATA_PKT_RESET)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rval = SATA_RETRY; /* may retry later */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown else
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rval = SATA_FAILURE;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown } else {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rval = SATA_FAILURE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknownfail:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Free allocated resources */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_free_local_buffer(spx);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_pkt_free(spx);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown kmem_free(spx, sizeof (sata_pkt_txlate_t));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (rval);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown/*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Some devices may not come-up with default DMA mode (UDMA or MWDMA).
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * UDMA mode is checked first, followed by MWDMA mode.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * set correctly, so this function is setting it to the highest supported level.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Older SATA spec required that the device supports at least DMA 4 mode and
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * UDMA mode is selected. It is not mentioned in SerialATA 2.6, so this
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * restriction has been removed.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown *
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Returns SATA_SUCCESS if proper DMA mode is selected or no DMA is supported.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Returns SATA_FAILURE if proper DMA mode could not be selected.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown *
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * NOTE: This function should be called only if DMA mode is supported.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic int
2038334ab26baaa43c9083f35def041511c3cc1fUnknownsata_set_dma_mode(sata_hba_inst_t *sata_hba_inst, sata_drive_info_t *sdinfo)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown{
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_pkt_t *spkt;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_cmd_t *scmd;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_pkt_txlate_t *spx;
56a5a29002624d0066b8f8954864ce6212844611ying tian - Beijing China int mode;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown uint8_t subcmd;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown int rval = SATA_SUCCESS;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ASSERT(sdinfo != NULL);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ASSERT(sata_hba_inst != NULL);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if ((sdinfo->satadrv_id.ai_validinfo & SATA_VALIDINFO_88) != 0 &&
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (sdinfo->satadrv_id.ai_ultradma & SATA_UDMA_SUP_MASK) != 0) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Find highest Ultra DMA mode supported */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown for (mode = 6; mode >= 0; --mode) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sdinfo->satadrv_id.ai_ultradma & (1 << mode))
2038334ab26baaa43c9083f35def041511c3cc1fUnknown break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown#if 0
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Left for historical reasons */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Some initial version of SATA spec indicated that at least
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * UDMA mode 4 has to be supported. It is not mentioned in
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * SerialATA 2.6, so this restriction is removed.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (mode < 4)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (SATA_FAILURE);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown#endif
56a5a29002624d0066b8f8954864ce6212844611ying tian - Beijing China
56a5a29002624d0066b8f8954864ce6212844611ying tian - Beijing China /*
56a5a29002624d0066b8f8954864ce6212844611ying tian - Beijing China * We're still going to set DMA mode whatever is selected
56a5a29002624d0066b8f8954864ce6212844611ying tian - Beijing China * by default
56a5a29002624d0066b8f8954864ce6212844611ying tian - Beijing China *
56a5a29002624d0066b8f8954864ce6212844611ying tian - Beijing China * We saw an old maxtor sata drive will select Ultra DMA and
56a5a29002624d0066b8f8954864ce6212844611ying tian - Beijing China * Multi-Word DMA simultaneouly by default, which is going
56a5a29002624d0066b8f8954864ce6212844611ying tian - Beijing China * to cause DMA command timed out, so we need to select DMA
56a5a29002624d0066b8f8954864ce6212844611ying tian - Beijing China * mode even when it's already done by default
56a5a29002624d0066b8f8954864ce6212844611ying tian - Beijing China */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown subcmd = SATAC_TRANSFER_MODE_ULTRA_DMA;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown } else if ((sdinfo->satadrv_id.ai_dworddma & SATA_MDMA_SUP_MASK) != 0) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Find highest MultiWord DMA mode supported */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown for (mode = 2; mode >= 0; --mode) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sdinfo->satadrv_id.ai_dworddma & (1 << mode))
2038334ab26baaa43c9083f35def041511c3cc1fUnknown break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
56a5a29002624d0066b8f8954864ce6212844611ying tian - Beijing China
56a5a29002624d0066b8f8954864ce6212844611ying tian - Beijing China /*
56a5a29002624d0066b8f8954864ce6212844611ying tian - Beijing China * We're still going to set DMA mode whatever is selected
56a5a29002624d0066b8f8954864ce6212844611ying tian - Beijing China * by default
56a5a29002624d0066b8f8954864ce6212844611ying tian - Beijing China *
56a5a29002624d0066b8f8954864ce6212844611ying tian - Beijing China * We saw an old maxtor sata drive will select Ultra DMA and
56a5a29002624d0066b8f8954864ce6212844611ying tian - Beijing China * Multi-Word DMA simultaneouly by default, which is going
56a5a29002624d0066b8f8954864ce6212844611ying tian - Beijing China * to cause DMA command timed out, so we need to select DMA
56a5a29002624d0066b8f8954864ce6212844611ying tian - Beijing China * mode even when it's already done by default
56a5a29002624d0066b8f8954864ce6212844611ying tian - Beijing China */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown subcmd = SATAC_TRANSFER_MODE_MULTI_WORD_DMA;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown } else
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (SATA_SUCCESS);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Set DMA mode via SET FEATURES COMMAND.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Prepare packet for SET FEATURES COMMAND.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx = kmem_zalloc(sizeof (sata_pkt_txlate_t), KM_SLEEP);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_sata_hba_inst = sata_hba_inst;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_scsi_pkt = NULL; /* No scsi pkt involved */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt = sata_pkt_alloc(spx, SLEEP_FUNC);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (spkt == NULL) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_LOG_D((sata_hba_inst, CE_WARN,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "sata_set_dma_mode: could not set DMA mode %", mode));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rval = SATA_FAILURE;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown goto done;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Fill sata_pkt */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_device.satadev_addr = sdinfo->satadrv_addr;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Timeout 30s */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_time = sata_default_pkt_time;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Synchronous mode, no callback, interrupts */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_op_mode = SATA_OPMODE_SYNCH | SATA_OPMODE_INTERRUPTS;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_comp = NULL;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd = &spkt->satapkt_cmd;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_flags.sata_data_direction = SATA_DIR_NODATA_XFER;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_flags.sata_ignore_dev_reset = B_TRUE;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_addr_type = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_device_reg = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_status_reg = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_error_reg = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_cmd_reg = SATAC_SET_FEATURES;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_features_reg = SATAC_SF_TRANSFER_MODE;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_sec_count_lsb = subcmd | mode;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Transfer command to HBA */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if ((*SATA_START_FUNC(sata_hba_inst))(SATA_DIP(sata_hba_inst),
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt) != SATA_TRAN_ACCEPTED ||
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_reason != SATA_PKT_COMPLETED) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Pkt execution failed */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rval = SATA_FAILURE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
2038334ab26baaa43c9083f35def041511c3cc1fUnknowndone:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Free allocated resources */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (spkt != NULL)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_pkt_free(spx);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (void) kmem_free(spx, sizeof (sata_pkt_txlate_t));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (rval);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Set device caching mode.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * One of the following operations should be specified:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * SATAC_SF_ENABLE_READ_AHEAD
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * SATAC_SF_DISABLE_READ_AHEAD
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * SATAC_SF_ENABLE_WRITE_CACHE
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * SATAC_SF_DISABLE_WRITE_CACHE
2038334ab26baaa43c9083f35def041511c3cc1fUnknown *
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * If operation fails, system log messgage is emitted.
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik * Returns SATA_SUCCESS when the operation succeeds, SATA_RETRY if
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik * command was sent but did not succeed, and SATA_FAILURE otherwise.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic int
2038334ab26baaa43c9083f35def041511c3cc1fUnknownsata_set_cache_mode(sata_hba_inst_t *sata_hba_inst, sata_drive_info_t *sdinfo,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown int cache_op)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_pkt_t *spkt;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_cmd_t *scmd;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_pkt_txlate_t *spx;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown int rval = SATA_SUCCESS;
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik int hba_rval;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown char *infop;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ASSERT(sdinfo != NULL);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ASSERT(sata_hba_inst != NULL);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ASSERT(cache_op == SATAC_SF_ENABLE_READ_AHEAD ||
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cache_op == SATAC_SF_DISABLE_READ_AHEAD ||
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cache_op == SATAC_SF_ENABLE_WRITE_CACHE ||
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cache_op == SATAC_SF_DISABLE_WRITE_CACHE);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Prepare packet for SET FEATURES COMMAND */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx = kmem_zalloc(sizeof (sata_pkt_txlate_t), KM_SLEEP);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_sata_hba_inst = sata_hba_inst;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_scsi_pkt = NULL; /* No scsi pkt involved */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt = sata_pkt_alloc(spx, SLEEP_FUNC);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (spkt == NULL) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rval = SATA_FAILURE;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown goto failure;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Fill sata_pkt */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_device.satadev_addr = sdinfo->satadrv_addr;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Timeout 30s */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_time = sata_default_pkt_time;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Synchronous mode, no callback, interrupts */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_op_mode =
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_OPMODE_SYNCH | SATA_OPMODE_INTERRUPTS;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_comp = NULL;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd = &spkt->satapkt_cmd;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_flags.sata_data_direction = SATA_DIR_NODATA_XFER;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_flags.sata_ignore_dev_reset = B_TRUE;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_addr_type = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_device_reg = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_status_reg = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_error_reg = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_cmd_reg = SATAC_SET_FEATURES;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_features_reg = cache_op;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Transfer command to HBA */
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik hba_rval = (*SATA_START_FUNC(sata_hba_inst))(
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik SATA_DIP(sata_hba_inst), spkt);
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik#ifdef SATA_INJECT_FAULTS
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik sata_inject_pkt_fault(spkt, &rval, sata_fault_type);
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik#endif
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik if ((hba_rval != SATA_TRAN_ACCEPTED) ||
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (spkt->satapkt_reason != SATA_PKT_COMPLETED)) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Pkt execution failed */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown switch (cache_op) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown case SATAC_SF_ENABLE_READ_AHEAD:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown infop = "enabling read ahead failed";
2038334ab26baaa43c9083f35def041511c3cc1fUnknown break;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown case SATAC_SF_DISABLE_READ_AHEAD:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown infop = "disabling read ahead failed";
2038334ab26baaa43c9083f35def041511c3cc1fUnknown break;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown case SATAC_SF_ENABLE_WRITE_CACHE:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown infop = "enabling write cache failed";
2038334ab26baaa43c9083f35def041511c3cc1fUnknown break;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown case SATAC_SF_DISABLE_WRITE_CACHE:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown infop = "disabling write cache failed";
2038334ab26baaa43c9083f35def041511c3cc1fUnknown break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_LOG_D((sata_hba_inst, CE_WARN, "%s", infop));
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik rval = SATA_RETRY;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknownfailure:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Free allocated resources */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (spkt != NULL)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_pkt_free(spx);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (void) kmem_free(spx, sizeof (sata_pkt_txlate_t));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (rval);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown/*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Set Removable Media Status Notification (enable/disable)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * state == 0 , disable
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * state != 0 , enable
2038334ab26baaa43c9083f35def041511c3cc1fUnknown *
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * If operation fails, system log messgage is emitted.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Returns SATA_SUCCESS when the operation succeeds, SATA_FAILURE otherwise.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic int
2038334ab26baaa43c9083f35def041511c3cc1fUnknownsata_set_rmsn(sata_hba_inst_t *sata_hba_inst, sata_drive_info_t *sdinfo,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown int state)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown{
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_pkt_t *spkt;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_cmd_t *scmd;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_pkt_txlate_t *spx;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown int rval = SATA_SUCCESS;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown char *infop;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ASSERT(sdinfo != NULL);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ASSERT(sata_hba_inst != NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Prepare packet for SET FEATURES COMMAND */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx = kmem_zalloc(sizeof (sata_pkt_txlate_t), KM_SLEEP);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_sata_hba_inst = sata_hba_inst;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_scsi_pkt = NULL; /* No scsi pkt involved */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt = sata_pkt_alloc(spx, SLEEP_FUNC);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (spkt == NULL) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rval = SATA_FAILURE;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown goto failure;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Fill sata_pkt */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_device.satadev_addr = sdinfo->satadrv_addr;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Timeout 30s */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_time = sata_default_pkt_time;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Synchronous mode, no callback, interrupts */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_op_mode =
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_OPMODE_SYNCH | SATA_OPMODE_INTERRUPTS;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_comp = NULL;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd = &spkt->satapkt_cmd;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_flags.sata_data_direction = SATA_DIR_NODATA_XFER;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_flags.sata_ignore_dev_reset = B_TRUE;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_addr_type = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_device_reg = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_status_reg = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_error_reg = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_cmd_reg = SATAC_SET_FEATURES;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (state == 0)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_features_reg = SATAC_SF_DISABLE_RMSN;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown else
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_features_reg = SATAC_SF_ENABLE_RMSN;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Transfer command to HBA */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (((*SATA_START_FUNC(sata_hba_inst))(
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_DIP(sata_hba_inst), spkt) != SATA_TRAN_ACCEPTED) ||
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (spkt->satapkt_reason != SATA_PKT_COMPLETED)) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Pkt execution failed */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (state == 0)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown infop = "disabling Removable Media Status "
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "Notification failed";
2038334ab26baaa43c9083f35def041511c3cc1fUnknown else
2038334ab26baaa43c9083f35def041511c3cc1fUnknown infop = "enabling Removable Media Status "
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "Notification failed";
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_LOG_D((sata_hba_inst, CE_WARN, "%s", infop));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rval = SATA_FAILURE;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknownfailure:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Free allocated resources */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (spkt != NULL)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_pkt_free(spx);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (void) kmem_free(spx, sizeof (sata_pkt_txlate_t));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (rval);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
c75976d12071ddd21443266260066ba036671682pawelw/*
c75976d12071ddd21443266260066ba036671682pawelw * Update state and copy port ss* values from passed sata_device structure.
c75976d12071ddd21443266260066ba036671682pawelw * sata_address is validated - if not valid, nothing is changed in sata_scsi
c75976d12071ddd21443266260066ba036671682pawelw * configuration struct.
c75976d12071ddd21443266260066ba036671682pawelw *
c75976d12071ddd21443266260066ba036671682pawelw * SATA_PSTATE_SHUTDOWN in port state is not reset to 0 by this function
c75976d12071ddd21443266260066ba036671682pawelw * regardless of the state in device argument.
c75976d12071ddd21443266260066ba036671682pawelw *
c75976d12071ddd21443266260066ba036671682pawelw * Port mutex should be held while calling this function.
c75976d12071ddd21443266260066ba036671682pawelw */
c75976d12071ddd21443266260066ba036671682pawelwstatic void
c75976d12071ddd21443266260066ba036671682pawelwsata_update_port_info(sata_hba_inst_t *sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device_t *sata_device)
c75976d12071ddd21443266260066ba036671682pawelw{
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_cport_info_t *cportinfo;
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw if (sata_device->satadev_addr.qual == SATA_ADDR_CPORT ||
c75976d12071ddd21443266260066ba036671682pawelw sata_device->satadev_addr.qual == SATA_ADDR_DCPORT) {
c75976d12071ddd21443266260066ba036671682pawelw if (SATA_NUM_CPORTS(sata_hba_inst) <=
c75976d12071ddd21443266260066ba036671682pawelw sata_device->satadev_addr.cport)
c75976d12071ddd21443266260066ba036671682pawelw return;
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw cportinfo = SATA_CPORT_INFO(sata_hba_inst,
c75976d12071ddd21443266260066ba036671682pawelw sata_device->satadev_addr.cport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang ASSERT(mutex_owned(&cportinfo->cport_mutex));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cportinfo->cport_scr = sata_device->satadev_scr;
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw /* Preserve SATA_PSTATE_SHUTDOWN flag */
c75976d12071ddd21443266260066ba036671682pawelw cportinfo->cport_state &= ~(SATA_PSTATE_PWRON |
c75976d12071ddd21443266260066ba036671682pawelw SATA_PSTATE_PWROFF | SATA_PSTATE_FAILED);
c75976d12071ddd21443266260066ba036671682pawelw cportinfo->cport_state |=
c75976d12071ddd21443266260066ba036671682pawelw sata_device->satadev_state & SATA_PSTATE_VALID;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang}
c75976d12071ddd21443266260066ba036671682pawelw
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhangvoid
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhangsata_update_pmport_info(sata_hba_inst_t *sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device_t *sata_device)
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang{
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_pmport_info_t *pmportinfo;
c75976d12071ddd21443266260066ba036671682pawelw
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if ((sata_device->satadev_addr.qual != SATA_ADDR_PMPORT &&
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device->satadev_addr.qual != SATA_ADDR_DPMPORT) ||
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_NUM_PMPORTS(sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device->satadev_addr.cport) <
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device->satadev_addr.pmport) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATADBG1(SATA_DBG_PMULT, sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "sata_update_port_info: error address %p.",
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang &sata_device->satadev_addr);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang return;
c75976d12071ddd21443266260066ba036671682pawelw }
c75976d12071ddd21443266260066ba036671682pawelw
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo = SATA_PMPORT_INFO(sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device->satadev_addr.cport,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device->satadev_addr.pmport);
c75976d12071ddd21443266260066ba036671682pawelw
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang ASSERT(mutex_owned(&pmportinfo->pmport_mutex));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo->pmport_scr = sata_device->satadev_scr;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Preserve SATA_PSTATE_SHUTDOWN flag */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo->pmport_state &=
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang ~(SATA_PSTATE_PWRON | SATA_PSTATE_PWROFF | SATA_PSTATE_FAILED);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo->pmport_state |=
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device->satadev_state & SATA_PSTATE_VALID;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang}
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw/*
c75976d12071ddd21443266260066ba036671682pawelw * Extract SATA port specification from an IOCTL argument.
c75976d12071ddd21443266260066ba036671682pawelw *
c75976d12071ddd21443266260066ba036671682pawelw * This function return the port the user land send us as is, unless it
c75976d12071ddd21443266260066ba036671682pawelw * cannot retrieve port spec, then -1 is returned.
c75976d12071ddd21443266260066ba036671682pawelw *
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Support port multiplier.
c75976d12071ddd21443266260066ba036671682pawelw */
c75976d12071ddd21443266260066ba036671682pawelwstatic int32_t
c75976d12071ddd21443266260066ba036671682pawelwsata_get_port_num(sata_hba_inst_t *sata_hba_inst, struct devctl_iocdata *dcp)
c75976d12071ddd21443266260066ba036671682pawelw{
c75976d12071ddd21443266260066ba036671682pawelw int32_t port;
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw /* Extract port number from nvpair in dca structure */
c75976d12071ddd21443266260066ba036671682pawelw if (nvlist_lookup_int32(ndi_dc_get_ap_data(dcp), "port", &port) != 0) {
c75976d12071ddd21443266260066ba036671682pawelw SATA_LOG_D((sata_hba_inst, CE_NOTE,
c75976d12071ddd21443266260066ba036671682pawelw "sata_get_port_num: invalid port spec 0x%x in ioctl",
c75976d12071ddd21443266260066ba036671682pawelw port));
c75976d12071ddd21443266260066ba036671682pawelw port = -1;
c75976d12071ddd21443266260066ba036671682pawelw }
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw return (port);
c75976d12071ddd21443266260066ba036671682pawelw}
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw/*
c75976d12071ddd21443266260066ba036671682pawelw * Get dev_info_t pointer to the device node pointed to by port argument.
c75976d12071ddd21443266260066ba036671682pawelw * NOTE: target argument is a value used in ioctls to identify
c75976d12071ddd21443266260066ba036671682pawelw * the AP - it is not a sata_address.
c75976d12071ddd21443266260066ba036671682pawelw * It is a combination of cport, pmport and address qualifier, encodded same
c75976d12071ddd21443266260066ba036671682pawelw * way as a scsi target number.
c75976d12071ddd21443266260066ba036671682pawelw * At this moment it carries only cport number.
c75976d12071ddd21443266260066ba036671682pawelw *
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * PMult hotplug is supported now.
c75976d12071ddd21443266260066ba036671682pawelw *
c75976d12071ddd21443266260066ba036671682pawelw * Returns dev_info_t pointer if target device was found, NULL otherwise.
c75976d12071ddd21443266260066ba036671682pawelw */
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelwstatic dev_info_t *
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhangsata_get_target_dip(dev_info_t *dip, uint8_t cport, uint8_t pmport)
c75976d12071ddd21443266260066ba036671682pawelw{
c75976d12071ddd21443266260066ba036671682pawelw dev_info_t *cdip = NULL;
c75976d12071ddd21443266260066ba036671682pawelw int target, tgt;
c75976d12071ddd21443266260066ba036671682pawelw int circ;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang uint8_t qual;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_hba_inst_t *sata_hba_inst;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang scsi_hba_tran_t *scsi_hba_tran;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Get target id */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang scsi_hba_tran = ddi_get_driver_private(dip);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (scsi_hba_tran == NULL)
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang return (NULL);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_hba_inst = scsi_hba_tran->tran_hba_private;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (sata_hba_inst == NULL)
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang return (NULL);
c75976d12071ddd21443266260066ba036671682pawelw
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Identify a port-mult by cport_info.cport_dev_type */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (SATA_CPORT_DEV_TYPE(sata_hba_inst, cport) == SATA_DTYPE_PMULT)
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang qual = SATA_ADDR_DPMPORT;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang else
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang qual = SATA_ADDR_DCPORT;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang target = SATA_TO_SCSI_TARGET(cport, pmport, qual);
c75976d12071ddd21443266260066ba036671682pawelw
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Retrieve target dip */
c75976d12071ddd21443266260066ba036671682pawelw ndi_devi_enter(dip, &circ);
c75976d12071ddd21443266260066ba036671682pawelw for (cdip = ddi_get_child(dip); cdip != NULL; ) {
c75976d12071ddd21443266260066ba036671682pawelw dev_info_t *next = ddi_get_next_sibling(cdip);
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw tgt = ddi_prop_get_int(DDI_DEV_T_ANY, cdip,
c75976d12071ddd21443266260066ba036671682pawelw DDI_PROP_DONTPASS, "target", -1);
c75976d12071ddd21443266260066ba036671682pawelw if (tgt == -1) {
c75976d12071ddd21443266260066ba036671682pawelw /*
c75976d12071ddd21443266260066ba036671682pawelw * This is actually an error condition, but not
c75976d12071ddd21443266260066ba036671682pawelw * a fatal one. Just continue the search.
c75976d12071ddd21443266260066ba036671682pawelw */
c75976d12071ddd21443266260066ba036671682pawelw cdip = next;
c75976d12071ddd21443266260066ba036671682pawelw continue;
c75976d12071ddd21443266260066ba036671682pawelw }
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw if (tgt == target)
c75976d12071ddd21443266260066ba036671682pawelw break;
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw cdip = next;
c75976d12071ddd21443266260066ba036671682pawelw }
c75976d12071ddd21443266260066ba036671682pawelw ndi_devi_exit(dip, circ);
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw return (cdip);
c75976d12071ddd21443266260066ba036671682pawelw}
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw/*
c75976d12071ddd21443266260066ba036671682pawelw * Get dev_info_t pointer to the device node pointed to by port argument.
c75976d12071ddd21443266260066ba036671682pawelw * NOTE: target argument is a value used in ioctls to identify
c75976d12071ddd21443266260066ba036671682pawelw * the AP - it is not a sata_address.
c75976d12071ddd21443266260066ba036671682pawelw * It is a combination of cport, pmport and address qualifier, encoded same
c75976d12071ddd21443266260066ba036671682pawelw * way as a scsi target number.
c75976d12071ddd21443266260066ba036671682pawelw *
c75976d12071ddd21443266260066ba036671682pawelw * Returns dev_info_t pointer if target device was found, NULL otherwise.
c75976d12071ddd21443266260066ba036671682pawelw */
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelwstatic dev_info_t *
c75976d12071ddd21443266260066ba036671682pawelwsata_get_scsi_target_dip(dev_info_t *dip, sata_address_t *saddr)
c75976d12071ddd21443266260066ba036671682pawelw{
c75976d12071ddd21443266260066ba036671682pawelw dev_info_t *cdip = NULL;
c75976d12071ddd21443266260066ba036671682pawelw int target, tgt;
c75976d12071ddd21443266260066ba036671682pawelw int circ;
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw target = SATA_TO_SCSI_TARGET(saddr->cport, saddr->pmport, saddr->qual);
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw ndi_devi_enter(dip, &circ);
c75976d12071ddd21443266260066ba036671682pawelw for (cdip = ddi_get_child(dip); cdip != NULL; ) {
c75976d12071ddd21443266260066ba036671682pawelw dev_info_t *next = ddi_get_next_sibling(cdip);
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw tgt = ddi_prop_get_int(DDI_DEV_T_ANY, cdip,
c75976d12071ddd21443266260066ba036671682pawelw DDI_PROP_DONTPASS, "target", -1);
c75976d12071ddd21443266260066ba036671682pawelw if (tgt == -1) {
c75976d12071ddd21443266260066ba036671682pawelw /*
c75976d12071ddd21443266260066ba036671682pawelw * This is actually an error condition, but not
c75976d12071ddd21443266260066ba036671682pawelw * a fatal one. Just continue the search.
c75976d12071ddd21443266260066ba036671682pawelw */
c75976d12071ddd21443266260066ba036671682pawelw cdip = next;
c75976d12071ddd21443266260066ba036671682pawelw continue;
c75976d12071ddd21443266260066ba036671682pawelw }
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw if (tgt == target)
c75976d12071ddd21443266260066ba036671682pawelw break;
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw cdip = next;
c75976d12071ddd21443266260066ba036671682pawelw }
c75976d12071ddd21443266260066ba036671682pawelw ndi_devi_exit(dip, circ);
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw return (cdip);
c75976d12071ddd21443266260066ba036671682pawelw}
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw/*
c75976d12071ddd21443266260066ba036671682pawelw * Process sata port disconnect request.
c75976d12071ddd21443266260066ba036671682pawelw * Normally, cfgadm sata plugin will try to offline (unconfigure) the device
c75976d12071ddd21443266260066ba036671682pawelw * before this request. Nevertheless, if a device is still configured,
c75976d12071ddd21443266260066ba036671682pawelw * we need to attempt to offline and unconfigure device.
c75976d12071ddd21443266260066ba036671682pawelw * Regardless of the unconfigure operation results the port is marked as
c75976d12071ddd21443266260066ba036671682pawelw * deactivated and no access to the attached device is possible.
c75976d12071ddd21443266260066ba036671682pawelw * If the target node remains because unconfigure operation failed, its state
c75976d12071ddd21443266260066ba036671682pawelw * will be set to DEVICE_REMOVED, preventing it to be used again when a device
c75976d12071ddd21443266260066ba036671682pawelw * is inserted/re-inserted. The event daemon will repeatedly try to unconfigure
c75976d12071ddd21443266260066ba036671682pawelw * the device and remove old target node.
c75976d12071ddd21443266260066ba036671682pawelw *
c75976d12071ddd21443266260066ba036671682pawelw * This function invokes sata_hba_inst->satahba_tran->
c75976d12071ddd21443266260066ba036671682pawelw * sata_tran_hotplug_ops->sata_tran_port_deactivate().
c75976d12071ddd21443266260066ba036671682pawelw * If successful, the device structure (if any) attached to the specified port
c75976d12071ddd21443266260066ba036671682pawelw * is removed and state of the port marked appropriately.
c75976d12071ddd21443266260066ba036671682pawelw * Failure of the port_deactivate may keep port in the physically active state,
c75976d12071ddd21443266260066ba036671682pawelw * or may fail the port.
c75976d12071ddd21443266260066ba036671682pawelw *
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * NOTE: Port multiplier is supported.
c75976d12071ddd21443266260066ba036671682pawelw */
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelwstatic int
c75976d12071ddd21443266260066ba036671682pawelwsata_ioctl_disconnect(sata_hba_inst_t *sata_hba_inst,
c75976d12071ddd21443266260066ba036671682pawelw sata_device_t *sata_device)
c75976d12071ddd21443266260066ba036671682pawelw{
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_drive_info_t *sdinfo = NULL, *subsdinfo = NULL;
c75976d12071ddd21443266260066ba036671682pawelw sata_cport_info_t *cportinfo = NULL;
c75976d12071ddd21443266260066ba036671682pawelw sata_pmport_info_t *pmportinfo = NULL;
c75976d12071ddd21443266260066ba036671682pawelw sata_pmult_info_t *pmultinfo = NULL;
a9d5ae2e08c504913c088349c3d4c144f3c92be8Pawel Wojcik sata_device_t subsdevice;
c75976d12071ddd21443266260066ba036671682pawelw int cport, pmport, qual;
c75976d12071ddd21443266260066ba036671682pawelw int rval = SATA_SUCCESS;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang int npmport = 0;
c75976d12071ddd21443266260066ba036671682pawelw int rv = 0;
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw cport = sata_device->satadev_addr.cport;
c75976d12071ddd21443266260066ba036671682pawelw pmport = sata_device->satadev_addr.pmport;
c75976d12071ddd21443266260066ba036671682pawelw qual = sata_device->satadev_addr.qual;
c75976d12071ddd21443266260066ba036671682pawelw
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang ASSERT(qual == SATA_ADDR_DCPORT || qual == SATA_ADDR_DPMPORT);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (qual == SATA_ADDR_DCPORT)
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang qual = SATA_ADDR_CPORT;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang else
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang qual = SATA_ADDR_PMPORT;
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw /*
c75976d12071ddd21443266260066ba036671682pawelw * DEVCTL_AP_DISCONNECT invokes sata_hba_inst->satahba_tran->
c75976d12071ddd21443266260066ba036671682pawelw * sata_tran_hotplug_ops->sata_tran_port_deactivate().
c75976d12071ddd21443266260066ba036671682pawelw * Do the sanity check.
c75976d12071ddd21443266260066ba036671682pawelw */
c75976d12071ddd21443266260066ba036671682pawelw if (SATA_PORT_DEACTIVATE_FUNC(sata_hba_inst) == NULL) {
c75976d12071ddd21443266260066ba036671682pawelw /* No physical port deactivation supported. */
c75976d12071ddd21443266260066ba036671682pawelw return (EINVAL);
c75976d12071ddd21443266260066ba036671682pawelw }
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw /* Check the current state of the port */
c75976d12071ddd21443266260066ba036671682pawelw rval = (*SATA_PROBE_PORT_FUNC(sata_hba_inst))
c75976d12071ddd21443266260066ba036671682pawelw (SATA_DIP(sata_hba_inst), sata_device);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cportinfo = SATA_CPORT_INFO(sata_hba_inst, cport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Processing port mulitiplier
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (qual == SATA_ADDR_CPORT &&
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_CPORT_DEV_TYPE(sata_hba_inst, cport) == SATA_DTYPE_PMULT) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&cportinfo->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Check controller port status */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_update_port_info(sata_hba_inst, sata_device);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (rval != SATA_SUCCESS ||
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (sata_device->satadev_state & SATA_PSTATE_FAILED) != 0) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Device port status is unknown or it is in failed
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * state
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_CPORT_STATE(sata_hba_inst, cport) =
c75976d12071ddd21443266260066ba036671682pawelw SATA_PSTATE_FAILED;
c75976d12071ddd21443266260066ba036671682pawelw SATADBG1(SATA_DBG_IOCTL_IF, sata_hba_inst,
c75976d12071ddd21443266260066ba036671682pawelw "sata_hba_ioctl: connect: failed to deactivate "
c75976d12071ddd21443266260066ba036671682pawelw "SATA port %d", cport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&cportinfo->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang return (EIO);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Disconnect all sub-devices. */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmultinfo = SATA_CPORTINFO_PMULT_INFO(cportinfo);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (pmultinfo != NULL) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang for (npmport = 0; npmport < SATA_NUM_PMPORTS(
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_hba_inst, cport); npmport ++) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang subsdinfo = SATA_PMPORT_DRV_INFO(
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_hba_inst, cport, npmport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (subsdinfo == NULL)
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang continue;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang subsdevice.satadev_addr = subsdinfo->
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang satadrv_addr;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&cportinfo->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (sata_ioctl_disconnect(sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang &subsdevice) == SATA_SUCCESS) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATADBG2(SATA_DBG_PMULT, sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "[Remove] device at port %d:%d "
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "successfully.", cport, npmport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&cportinfo->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Disconnect the port multiplier */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cportinfo->cport_state &= ~SATA_STATE_READY;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&cportinfo->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device->satadev_addr.qual = qual;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang rval = (*SATA_PORT_DEACTIVATE_FUNC(sata_hba_inst))
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (SATA_DIP(sata_hba_inst), sata_device);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_gen_sysevent(sata_hba_inst, &sata_device->satadev_addr,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SE_NO_HINT);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&cportinfo->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_update_port_info(sata_hba_inst, sata_device);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (rval != SATA_SUCCESS &&
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device->satadev_state & SATA_PSTATE_FAILED) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cportinfo->cport_state = SATA_PSTATE_FAILED;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang rv = EIO;
c75976d12071ddd21443266260066ba036671682pawelw } else {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cportinfo->cport_state |= SATA_PSTATE_SHUTDOWN;
c75976d12071ddd21443266260066ba036671682pawelw }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&cportinfo->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang return (rv);
c75976d12071ddd21443266260066ba036671682pawelw }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
c75976d12071ddd21443266260066ba036671682pawelw /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Process non-port-multiplier device - it could be a drive connected
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * to a port multiplier port or a controller port.
c75976d12071ddd21443266260066ba036671682pawelw */
c75976d12071ddd21443266260066ba036671682pawelw if (qual == SATA_ADDR_PMPORT) {
c75976d12071ddd21443266260066ba036671682pawelw pmportinfo = SATA_PMPORT_INFO(sata_hba_inst, cport, pmport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_update_pmport_info(sata_hba_inst, sata_device);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (rval != SATA_SUCCESS ||
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (sata_device->satadev_state & SATA_PSTATE_FAILED) != 0) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_PMPORT_STATE(sata_hba_inst, cport, pmport) =
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_PSTATE_FAILED;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATADBG2(SATA_DBG_IOCTL_IF, sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "sata_hba_ioctl: connect: failed to deactivate "
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "SATA port %d:%d", cport, pmport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang return (EIO);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
c75976d12071ddd21443266260066ba036671682pawelw if (pmportinfo->pmport_dev_type != SATA_DTYPE_NONE) {
c75976d12071ddd21443266260066ba036671682pawelw sdinfo = pmportinfo->pmport_sata_drive;
c75976d12071ddd21443266260066ba036671682pawelw ASSERT(sdinfo != NULL);
c75976d12071ddd21443266260066ba036671682pawelw }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Set port's dev_state to not ready - this will disable
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * an access to a potentially attached device.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
c75976d12071ddd21443266260066ba036671682pawelw pmportinfo->pmport_state &= ~SATA_STATE_READY;
c75976d12071ddd21443266260066ba036671682pawelw
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Remove and release sata_drive info structure. */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (sdinfo != NULL) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if ((sdinfo->satadrv_type &
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_VALID_DEV_TYPE) != 0) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * If a target node exists, try to offline
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * a device and remove target node.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (void) sata_offline_device(sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device, sdinfo);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&pmportinfo->pmport_mutex);
c75976d12071ddd21443266260066ba036671682pawelw }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_PMPORTINFO_DRV_INFO(pmportinfo) = NULL;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo->pmport_dev_type = SATA_DTYPE_NONE;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (void) kmem_free((void *)sdinfo,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sizeof (sata_drive_info_t));
c75976d12071ddd21443266260066ba036671682pawelw }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang } else if (qual == SATA_ADDR_CPORT) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&cportinfo->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_update_port_info(sata_hba_inst, sata_device);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (rval != SATA_SUCCESS ||
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (sata_device->satadev_state & SATA_PSTATE_FAILED) != 0) {
c75976d12071ddd21443266260066ba036671682pawelw /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Device port status is unknown or it is in failed
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * state
c75976d12071ddd21443266260066ba036671682pawelw */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_CPORT_STATE(sata_hba_inst, cport) =
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_PSTATE_FAILED;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATADBG1(SATA_DBG_IOCTL_IF, sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "sata_hba_ioctl: connect: failed to deactivate "
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "SATA port %d", cport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&cportinfo->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang return (EIO);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (cportinfo->cport_dev_type == SATA_DTYPE_PMULT) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmultinfo = SATA_CPORTINFO_PMULT_INFO(cportinfo);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang ASSERT(pmultinfo != NULL);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang } else if (cportinfo->cport_dev_type != SATA_DTYPE_NONE) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sdinfo = SATA_CPORTINFO_DRV_INFO(cportinfo);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang ASSERT(sdinfo != NULL);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cportinfo->cport_state &= ~SATA_STATE_READY;
c75976d12071ddd21443266260066ba036671682pawelw
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (sdinfo != NULL) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if ((sdinfo->satadrv_type &
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_VALID_DEV_TYPE) != 0) {
c75976d12071ddd21443266260066ba036671682pawelw /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * If a target node exists, try to offline
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * a device and remove target node.
c75976d12071ddd21443266260066ba036671682pawelw */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&cportinfo->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (void) sata_offline_device(sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device, sdinfo);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&cportinfo->cport_mutex);
c75976d12071ddd21443266260066ba036671682pawelw }
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw SATA_CPORTINFO_DRV_INFO(cportinfo) = NULL;
c75976d12071ddd21443266260066ba036671682pawelw cportinfo->cport_dev_type = SATA_DTYPE_NONE;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (void) kmem_free((void *)sdinfo,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sizeof (sata_drive_info_t));
c75976d12071ddd21443266260066ba036671682pawelw }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&cportinfo->cport_mutex);
c75976d12071ddd21443266260066ba036671682pawelw }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
c75976d12071ddd21443266260066ba036671682pawelw /* Just ask HBA driver to deactivate port */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device->satadev_addr.qual = qual;
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw rval = (*SATA_PORT_DEACTIVATE_FUNC(sata_hba_inst))
c75976d12071ddd21443266260066ba036671682pawelw (SATA_DIP(sata_hba_inst), sata_device);
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw /*
c75976d12071ddd21443266260066ba036671682pawelw * Generate sysevent - EC_DR / ESC_DR_AP_STATE_CHANGE
c75976d12071ddd21443266260066ba036671682pawelw * without the hint (to force listener to investivate the state).
c75976d12071ddd21443266260066ba036671682pawelw */
c75976d12071ddd21443266260066ba036671682pawelw sata_gen_sysevent(sata_hba_inst, &sata_device->satadev_addr,
c75976d12071ddd21443266260066ba036671682pawelw SE_NO_HINT);
c75976d12071ddd21443266260066ba036671682pawelw
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (qual == SATA_ADDR_PMPORT) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_update_pmport_info(sata_hba_inst, sata_device);
c75976d12071ddd21443266260066ba036671682pawelw
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (rval != SATA_SUCCESS &&
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device->satadev_state & SATA_PSTATE_FAILED) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Port deactivation failure - do not change port
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * state unless the state returned by HBA indicates a
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * port failure.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang *
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * NOTE: device structures were released, so devices
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * now are invisible! Port reset is needed to
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * re-enumerate devices.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo->pmport_state = SATA_PSTATE_FAILED;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang rv = EIO;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang } else {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Deactivation succeded. From now on the sata framework
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * will not care what is happening to the device, until
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * the port is activated again.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo->pmport_state |= SATA_PSTATE_SHUTDOWN;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang } else if (qual == SATA_ADDR_CPORT) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&cportinfo->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_update_port_info(sata_hba_inst, sata_device);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (rval != SATA_SUCCESS &&
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device->satadev_state & SATA_PSTATE_FAILED) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cportinfo->cport_state = SATA_PSTATE_FAILED;
c75976d12071ddd21443266260066ba036671682pawelw rv = EIO;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang } else {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cportinfo->cport_state |= SATA_PSTATE_SHUTDOWN;
c75976d12071ddd21443266260066ba036671682pawelw }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&cportinfo->cport_mutex);
c75976d12071ddd21443266260066ba036671682pawelw }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
c75976d12071ddd21443266260066ba036671682pawelw return (rv);
c75976d12071ddd21443266260066ba036671682pawelw}
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw/*
c75976d12071ddd21443266260066ba036671682pawelw * Process sata port connect request
c75976d12071ddd21443266260066ba036671682pawelw * The sata cfgadm pluging will invoke this operation only if port was found
c75976d12071ddd21443266260066ba036671682pawelw * in the disconnect state (failed state is also treated as the disconnected
c75976d12071ddd21443266260066ba036671682pawelw * state).
c75976d12071ddd21443266260066ba036671682pawelw * DEVCTL_AP_CONNECT would invoke sata_hba_inst->satahba_tran->
c75976d12071ddd21443266260066ba036671682pawelw * sata_tran_hotplug_ops->sata_tran_port_activate().
c75976d12071ddd21443266260066ba036671682pawelw * If successful and a device is found attached to the port,
c75976d12071ddd21443266260066ba036671682pawelw * the initialization sequence is executed to attach a device structure to
c75976d12071ddd21443266260066ba036671682pawelw * a port structure. The state of the port and a device would be set
c75976d12071ddd21443266260066ba036671682pawelw * appropriately.
c75976d12071ddd21443266260066ba036671682pawelw * The device is not set in configured state (system-wise) by this operation.
c75976d12071ddd21443266260066ba036671682pawelw *
c75976d12071ddd21443266260066ba036671682pawelw * Note, that activating the port may generate link events,
c75976d12071ddd21443266260066ba036671682pawelw * so it is important that following processing and the
c75976d12071ddd21443266260066ba036671682pawelw * event processing does not interfere with each other!
c75976d12071ddd21443266260066ba036671682pawelw *
c75976d12071ddd21443266260066ba036671682pawelw * This operation may remove port failed state and will
c75976d12071ddd21443266260066ba036671682pawelw * try to make port active and in good standing.
c75976d12071ddd21443266260066ba036671682pawelw *
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * NOTE: Port multiplier is supported.
c75976d12071ddd21443266260066ba036671682pawelw */
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelwstatic int
c75976d12071ddd21443266260066ba036671682pawelwsata_ioctl_connect(sata_hba_inst_t *sata_hba_inst,
c75976d12071ddd21443266260066ba036671682pawelw sata_device_t *sata_device)
c75976d12071ddd21443266260066ba036671682pawelw{
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_pmport_info_t *pmportinfo = NULL;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang uint8_t cport, pmport, qual;
c75976d12071ddd21443266260066ba036671682pawelw int rv = 0;
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw cport = sata_device->satadev_addr.cport;
c75976d12071ddd21443266260066ba036671682pawelw pmport = sata_device->satadev_addr.pmport;
c75976d12071ddd21443266260066ba036671682pawelw qual = sata_device->satadev_addr.qual;
c75976d12071ddd21443266260066ba036671682pawelw
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang ASSERT(qual == SATA_ADDR_DCPORT || qual == SATA_ADDR_DPMPORT);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (qual == SATA_ADDR_DCPORT)
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang qual = SATA_ADDR_CPORT;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang else
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang qual = SATA_ADDR_PMPORT;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (qual == SATA_ADDR_PMPORT)
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo = SATA_PMPORT_INFO(sata_hba_inst, cport, pmport);
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw /*
c75976d12071ddd21443266260066ba036671682pawelw * DEVCTL_AP_CONNECT would invoke sata_hba_inst->
c75976d12071ddd21443266260066ba036671682pawelw * satahba_tran->sata_tran_hotplug_ops->sata_tran_port_activate().
c75976d12071ddd21443266260066ba036671682pawelw * Perform sanity check now.
c75976d12071ddd21443266260066ba036671682pawelw */
c75976d12071ddd21443266260066ba036671682pawelw if (SATA_PORT_ACTIVATE_FUNC(sata_hba_inst) == NULL) {
c75976d12071ddd21443266260066ba036671682pawelw /* No physical port activation supported. */
c75976d12071ddd21443266260066ba036671682pawelw return (EINVAL);
c75976d12071ddd21443266260066ba036671682pawelw }
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw /* Just ask HBA driver to activate port */
c75976d12071ddd21443266260066ba036671682pawelw if ((*SATA_PORT_ACTIVATE_FUNC(sata_hba_inst))
c75976d12071ddd21443266260066ba036671682pawelw (SATA_DIP(sata_hba_inst), sata_device) != SATA_SUCCESS) {
c75976d12071ddd21443266260066ba036671682pawelw /*
c75976d12071ddd21443266260066ba036671682pawelw * Port activation failure.
c75976d12071ddd21443266260066ba036671682pawelw */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (qual == SATA_ADDR_CPORT) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&SATA_CPORT_INFO(sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cport)->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_update_port_info(sata_hba_inst, sata_device);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (sata_device->satadev_state & SATA_PSTATE_FAILED) {
c75976d12071ddd21443266260066ba036671682pawelw SATA_CPORT_STATE(sata_hba_inst, cport) =
c75976d12071ddd21443266260066ba036671682pawelw SATA_PSTATE_FAILED;
c75976d12071ddd21443266260066ba036671682pawelw SATADBG1(SATA_DBG_IOCTL_IF, sata_hba_inst,
c75976d12071ddd21443266260066ba036671682pawelw "sata_hba_ioctl: connect: failed to "
c75976d12071ddd21443266260066ba036671682pawelw "activate SATA port %d", cport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&SATA_CPORT_INFO(sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cport)->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang } else { /* port multiplier device port */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_update_pmport_info(sata_hba_inst, sata_device);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (sata_device->satadev_state & SATA_PSTATE_FAILED) {
c75976d12071ddd21443266260066ba036671682pawelw SATA_PMPORT_STATE(sata_hba_inst, cport,
c75976d12071ddd21443266260066ba036671682pawelw pmport) = SATA_PSTATE_FAILED;
c75976d12071ddd21443266260066ba036671682pawelw SATADBG2(SATA_DBG_IOCTL_IF, sata_hba_inst,
c75976d12071ddd21443266260066ba036671682pawelw "sata_hba_ioctl: connect: failed to "
c75976d12071ddd21443266260066ba036671682pawelw "activate SATA port %d:%d", cport, pmport);
c75976d12071ddd21443266260066ba036671682pawelw }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&pmportinfo->pmport_mutex);
c75976d12071ddd21443266260066ba036671682pawelw }
c75976d12071ddd21443266260066ba036671682pawelw return (EIO);
c75976d12071ddd21443266260066ba036671682pawelw }
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw /* Virgin port state - will be updated by the port re-probe. */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (qual == SATA_ADDR_CPORT) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&SATA_CPORT_INFO(sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cport)->cport_mutex);
c75976d12071ddd21443266260066ba036671682pawelw SATA_CPORT_STATE(sata_hba_inst, cport) = 0;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&SATA_CPORT_INFO(sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cport)->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang } else { /* port multiplier device port */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&pmportinfo->pmport_mutex);
c75976d12071ddd21443266260066ba036671682pawelw SATA_PMPORT_STATE(sata_hba_inst, cport, pmport) = 0;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw /*
c75976d12071ddd21443266260066ba036671682pawelw * Probe the port to find its state and attached device.
c75976d12071ddd21443266260066ba036671682pawelw */
c75976d12071ddd21443266260066ba036671682pawelw if (sata_reprobe_port(sata_hba_inst, sata_device,
c75976d12071ddd21443266260066ba036671682pawelw SATA_DEV_IDENTIFY_RETRY) == SATA_FAILURE)
c75976d12071ddd21443266260066ba036671682pawelw rv = EIO;
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw /*
c75976d12071ddd21443266260066ba036671682pawelw * Generate sysevent - EC_DR / ESC_DR_AP_STATE_CHANGE
c75976d12071ddd21443266260066ba036671682pawelw * without the hint
c75976d12071ddd21443266260066ba036671682pawelw */
c75976d12071ddd21443266260066ba036671682pawelw sata_gen_sysevent(sata_hba_inst, &sata_device->satadev_addr,
c75976d12071ddd21443266260066ba036671682pawelw SE_NO_HINT);
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw /*
c75976d12071ddd21443266260066ba036671682pawelw * If there is a device attached to the port, emit
c75976d12071ddd21443266260066ba036671682pawelw * a message.
c75976d12071ddd21443266260066ba036671682pawelw */
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw if (sata_device->satadev_type != SATA_DTYPE_NONE) {
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw if (qual == SATA_ADDR_CPORT) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (sata_device->satadev_type == SATA_DTYPE_PMULT) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_log(sata_hba_inst, CE_WARN,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "SATA port multiplier detected "
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "at port %d", cport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang } else {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_log(sata_hba_inst, CE_WARN,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "SATA device detected at port %d", cport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (sata_device->satadev_type ==
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_DTYPE_UNKNOWN) {
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw /*
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw * A device was not successfully identified
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw */
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw sata_log(sata_hba_inst, CE_WARN,
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw "Could not identify SATA "
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw "device at port %d", cport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw }
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw } else { /* port multiplier device port */
c75976d12071ddd21443266260066ba036671682pawelw sata_log(sata_hba_inst, CE_WARN,
c75976d12071ddd21443266260066ba036671682pawelw "SATA device detected at port %d:%d",
c75976d12071ddd21443266260066ba036671682pawelw cport, pmport);
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw if (sata_device->satadev_type == SATA_DTYPE_UNKNOWN) {
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw /*
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw * A device was not successfully identified
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw */
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw sata_log(sata_hba_inst, CE_WARN,
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw "Could not identify SATA "
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw "device at port %d:%d", cport, pmport);
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw }
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw }
c75976d12071ddd21443266260066ba036671682pawelw }
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw return (rv);
c75976d12071ddd21443266260066ba036671682pawelw}
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw/*
c75976d12071ddd21443266260066ba036671682pawelw * Process sata device unconfigure request.
c75976d12071ddd21443266260066ba036671682pawelw * The unconfigure operation uses generic nexus operation to
c75976d12071ddd21443266260066ba036671682pawelw * offline a device. It leaves a target device node attached.
c75976d12071ddd21443266260066ba036671682pawelw * and obviously sata_drive_info attached as well, because
c75976d12071ddd21443266260066ba036671682pawelw * from the hardware point of view nothing has changed.
c75976d12071ddd21443266260066ba036671682pawelw */
c75976d12071ddd21443266260066ba036671682pawelwstatic int
c75976d12071ddd21443266260066ba036671682pawelwsata_ioctl_unconfigure(sata_hba_inst_t *sata_hba_inst,
c75976d12071ddd21443266260066ba036671682pawelw sata_device_t *sata_device)
c75976d12071ddd21443266260066ba036671682pawelw{
c75976d12071ddd21443266260066ba036671682pawelw int rv = 0;
c75976d12071ddd21443266260066ba036671682pawelw dev_info_t *tdip;
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw /* We are addressing attached device, not a port */
c75976d12071ddd21443266260066ba036671682pawelw if (sata_device->satadev_addr.qual == SATA_ADDR_CPORT)
c75976d12071ddd21443266260066ba036671682pawelw sata_device->satadev_addr.qual = SATA_ADDR_DCPORT;
c75976d12071ddd21443266260066ba036671682pawelw else if (sata_device->satadev_addr.qual == SATA_ADDR_PMPORT)
c75976d12071ddd21443266260066ba036671682pawelw sata_device->satadev_addr.qual = SATA_ADDR_DPMPORT;
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw if ((tdip = sata_get_scsi_target_dip(SATA_DIP(sata_hba_inst),
c75976d12071ddd21443266260066ba036671682pawelw &sata_device->satadev_addr)) != NULL) {
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw if (ndi_devi_offline(tdip, NDI_UNCONFIG) != NDI_SUCCESS) {
c75976d12071ddd21443266260066ba036671682pawelw SATA_LOG_D((sata_hba_inst, CE_WARN,
c75976d12071ddd21443266260066ba036671682pawelw "sata_hba_ioctl: unconfigure: "
c75976d12071ddd21443266260066ba036671682pawelw "failed to unconfigure device at SATA port %d:%d",
c75976d12071ddd21443266260066ba036671682pawelw sata_device->satadev_addr.cport,
c75976d12071ddd21443266260066ba036671682pawelw sata_device->satadev_addr.pmport));
c75976d12071ddd21443266260066ba036671682pawelw rv = EIO;
c75976d12071ddd21443266260066ba036671682pawelw }
c75976d12071ddd21443266260066ba036671682pawelw /*
c75976d12071ddd21443266260066ba036671682pawelw * The target node devi_state should be marked with
c75976d12071ddd21443266260066ba036671682pawelw * DEVI_DEVICE_OFFLINE by ndi_devi_offline().
c75976d12071ddd21443266260066ba036671682pawelw * This would be the indication for cfgadm that
c75976d12071ddd21443266260066ba036671682pawelw * the AP node occupant state is 'unconfigured'.
c75976d12071ddd21443266260066ba036671682pawelw */
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw } else {
c75976d12071ddd21443266260066ba036671682pawelw /*
c75976d12071ddd21443266260066ba036671682pawelw * This would indicate a failure on the part of cfgadm
c75976d12071ddd21443266260066ba036671682pawelw * to detect correct state of the node prior to this
c75976d12071ddd21443266260066ba036671682pawelw * call - one cannot unconfigure non-existing device.
c75976d12071ddd21443266260066ba036671682pawelw */
c75976d12071ddd21443266260066ba036671682pawelw SATA_LOG_D((sata_hba_inst, CE_WARN,
c75976d12071ddd21443266260066ba036671682pawelw "sata_hba_ioctl: unconfigure: "
c75976d12071ddd21443266260066ba036671682pawelw "attempt to unconfigure non-existing device "
c75976d12071ddd21443266260066ba036671682pawelw "at SATA port %d:%d",
c75976d12071ddd21443266260066ba036671682pawelw sata_device->satadev_addr.cport,
c75976d12071ddd21443266260066ba036671682pawelw sata_device->satadev_addr.pmport));
c75976d12071ddd21443266260066ba036671682pawelw rv = ENXIO;
c75976d12071ddd21443266260066ba036671682pawelw }
c75976d12071ddd21443266260066ba036671682pawelw return (rv);
c75976d12071ddd21443266260066ba036671682pawelw}
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw/*
c75976d12071ddd21443266260066ba036671682pawelw * Process sata device configure request
c75976d12071ddd21443266260066ba036671682pawelw * If port is in a failed state, operation is aborted - one has to use
c75976d12071ddd21443266260066ba036671682pawelw * an explicit connect or port activate request to try to get a port into
c75976d12071ddd21443266260066ba036671682pawelw * non-failed mode. Port reset wil also work in such situation.
c75976d12071ddd21443266260066ba036671682pawelw * If the port is in disconnected (shutdown) state, the connect operation is
c75976d12071ddd21443266260066ba036671682pawelw * attempted prior to any other action.
c75976d12071ddd21443266260066ba036671682pawelw * When port is in the active state, there is a device attached and the target
c75976d12071ddd21443266260066ba036671682pawelw * node exists, a device was most likely offlined.
c75976d12071ddd21443266260066ba036671682pawelw * If target node does not exist, a new target node is created. In both cases
c75976d12071ddd21443266260066ba036671682pawelw * an attempt is made to online (configure) the device.
c75976d12071ddd21443266260066ba036671682pawelw *
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * NOTE: Port multiplier is supported.
c75976d12071ddd21443266260066ba036671682pawelw */
c75976d12071ddd21443266260066ba036671682pawelwstatic int
c75976d12071ddd21443266260066ba036671682pawelwsata_ioctl_configure(sata_hba_inst_t *sata_hba_inst,
c75976d12071ddd21443266260066ba036671682pawelw sata_device_t *sata_device)
c75976d12071ddd21443266260066ba036671682pawelw{
c75976d12071ddd21443266260066ba036671682pawelw int cport, pmport, qual;
c75976d12071ddd21443266260066ba036671682pawelw int rval;
c75976d12071ddd21443266260066ba036671682pawelw boolean_t target = TRUE;
c75976d12071ddd21443266260066ba036671682pawelw sata_cport_info_t *cportinfo;
c75976d12071ddd21443266260066ba036671682pawelw sata_pmport_info_t *pmportinfo = NULL;
c75976d12071ddd21443266260066ba036671682pawelw dev_info_t *tdip;
c75976d12071ddd21443266260066ba036671682pawelw sata_drive_info_t *sdinfo;
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw cport = sata_device->satadev_addr.cport;
c75976d12071ddd21443266260066ba036671682pawelw pmport = sata_device->satadev_addr.pmport;
c75976d12071ddd21443266260066ba036671682pawelw qual = sata_device->satadev_addr.qual;
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw /* Get current port state */
c75976d12071ddd21443266260066ba036671682pawelw rval = (*SATA_PROBE_PORT_FUNC(sata_hba_inst))
c75976d12071ddd21443266260066ba036671682pawelw (SATA_DIP(sata_hba_inst), sata_device);
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw cportinfo = SATA_CPORT_INFO(sata_hba_inst, cport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (qual == SATA_ADDR_DPMPORT) {
c75976d12071ddd21443266260066ba036671682pawelw pmportinfo = SATA_PMPORT_INFO(sata_hba_inst, cport, pmport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_update_pmport_info(sata_hba_inst, sata_device);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (rval != SATA_SUCCESS ||
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (sata_device->satadev_state & SATA_PSTATE_FAILED) != 0) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Obviously, device on a failed port is not visible
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang return (ENXIO);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang } else {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&SATA_CPORT_INFO(sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cport)->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_update_port_info(sata_hba_inst, sata_device);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (rval != SATA_SUCCESS ||
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (sata_device->satadev_state & SATA_PSTATE_FAILED) != 0) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Obviously, device on a failed port is not visible
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&SATA_CPORT_INFO(sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cport)->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang return (ENXIO);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&SATA_CPORT_INFO(sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cport)->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw if ((sata_device->satadev_state & SATA_PSTATE_SHUTDOWN) != 0) {
c75976d12071ddd21443266260066ba036671682pawelw /* need to activate port */
c75976d12071ddd21443266260066ba036671682pawelw target = FALSE;
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw /* Sanity check */
c75976d12071ddd21443266260066ba036671682pawelw if (SATA_PORT_ACTIVATE_FUNC(sata_hba_inst) == NULL)
c75976d12071ddd21443266260066ba036671682pawelw return (ENXIO);
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw /* Just let HBA driver to activate port */
c75976d12071ddd21443266260066ba036671682pawelw if ((*SATA_PORT_ACTIVATE_FUNC(sata_hba_inst))
c75976d12071ddd21443266260066ba036671682pawelw (SATA_DIP(sata_hba_inst), sata_device) != SATA_SUCCESS) {
c75976d12071ddd21443266260066ba036671682pawelw /*
c75976d12071ddd21443266260066ba036671682pawelw * Port activation failure - do not change port state
c75976d12071ddd21443266260066ba036671682pawelw * unless the state returned by HBA indicates a port
c75976d12071ddd21443266260066ba036671682pawelw * failure.
c75976d12071ddd21443266260066ba036671682pawelw */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (qual == SATA_ADDR_DPMPORT) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_update_pmport_info(sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (sata_device->satadev_state &
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_PSTATE_FAILED)
c75976d12071ddd21443266260066ba036671682pawelw pmportinfo->pmport_state =
c75976d12071ddd21443266260066ba036671682pawelw SATA_PSTATE_FAILED;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang } else {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&SATA_CPORT_INFO(sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cport)->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_update_port_info(sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (sata_device->satadev_state &
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_PSTATE_FAILED)
c75976d12071ddd21443266260066ba036671682pawelw cportinfo->cport_state =
c75976d12071ddd21443266260066ba036671682pawelw SATA_PSTATE_FAILED;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&SATA_CPORT_INFO(
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_hba_inst, cport)->cport_mutex);
c75976d12071ddd21443266260066ba036671682pawelw }
c75976d12071ddd21443266260066ba036671682pawelw }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_LOG_D((sata_hba_inst, CE_WARN,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "sata_hba_ioctl: configure: "
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "failed to activate SATA port %d:%d",
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cport, pmport));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang return (EIO);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Generate sysevent - EC_DR / ESC_DR_AP_STATE_CHANGE
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * without the hint.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_gen_sysevent(sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang &sata_device->satadev_addr, SE_NO_HINT);
c75976d12071ddd21443266260066ba036671682pawelw
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Virgin port state */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (qual == SATA_ADDR_DPMPORT) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo->pmport_state = 0;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang } else {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&SATA_CPORT_INFO(sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cport)-> cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cportinfo->cport_state = 0;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&SATA_CPORT_INFO(sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cport)->cport_mutex);
c75976d12071ddd21443266260066ba036671682pawelw }
c75976d12071ddd21443266260066ba036671682pawelw /*
c75976d12071ddd21443266260066ba036671682pawelw * Always reprobe port, to get current device info.
c75976d12071ddd21443266260066ba036671682pawelw */
c75976d12071ddd21443266260066ba036671682pawelw if (sata_reprobe_port(sata_hba_inst, sata_device,
c75976d12071ddd21443266260066ba036671682pawelw SATA_DEV_IDENTIFY_RETRY) != SATA_SUCCESS)
c75976d12071ddd21443266260066ba036671682pawelw return (EIO);
c75976d12071ddd21443266260066ba036671682pawelw
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw if (sata_device->satadev_type != SATA_DTYPE_NONE && target == FALSE) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (qual == SATA_ADDR_DPMPORT) {
c75976d12071ddd21443266260066ba036671682pawelw /*
c75976d12071ddd21443266260066ba036671682pawelw * That's the transition from "inactive" port
c75976d12071ddd21443266260066ba036671682pawelw * to active one with device attached.
c75976d12071ddd21443266260066ba036671682pawelw */
c75976d12071ddd21443266260066ba036671682pawelw sata_log(sata_hba_inst, CE_WARN,
c75976d12071ddd21443266260066ba036671682pawelw "SATA device detected at port %d:%d",
c75976d12071ddd21443266260066ba036671682pawelw cport, pmport);
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw } else {
c75976d12071ddd21443266260066ba036671682pawelw /*
c75976d12071ddd21443266260066ba036671682pawelw * When PM is attached to the cport and cport is
c75976d12071ddd21443266260066ba036671682pawelw * activated, every PM device port needs to be reprobed.
c75976d12071ddd21443266260066ba036671682pawelw * We need to emit message for all devices detected
c75976d12071ddd21443266260066ba036671682pawelw * at port multiplier's device ports.
c75976d12071ddd21443266260066ba036671682pawelw * Add such code here.
c75976d12071ddd21443266260066ba036671682pawelw * For now, just inform about device attached to
c75976d12071ddd21443266260066ba036671682pawelw * cport.
c75976d12071ddd21443266260066ba036671682pawelw */
c75976d12071ddd21443266260066ba036671682pawelw sata_log(sata_hba_inst, CE_WARN,
c75976d12071ddd21443266260066ba036671682pawelw "SATA device detected at port %d", cport);
c75976d12071ddd21443266260066ba036671682pawelw }
c75976d12071ddd21443266260066ba036671682pawelw }
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw /*
c75976d12071ddd21443266260066ba036671682pawelw * This is where real configuration operation starts.
c75976d12071ddd21443266260066ba036671682pawelw *
c75976d12071ddd21443266260066ba036671682pawelw * When PM is attached to the cport and cport is activated,
c75976d12071ddd21443266260066ba036671682pawelw * devices attached PM device ports may have to be configured
c75976d12071ddd21443266260066ba036671682pawelw * explicitly. This may change when port multiplier is supported.
c75976d12071ddd21443266260066ba036671682pawelw * For now, configure only disks and other valid target devices.
c75976d12071ddd21443266260066ba036671682pawelw */
c75976d12071ddd21443266260066ba036671682pawelw if (!(sata_device->satadev_type & SATA_VALID_DEV_TYPE)) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (qual == SATA_ADDR_DCPORT) {
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw if (sata_device->satadev_type == SATA_DTYPE_UNKNOWN) {
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw /*
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw * A device was not successfully identified
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw */
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw sata_log(sata_hba_inst, CE_WARN,
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw "Could not identify SATA "
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw "device at port %d", cport);
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw }
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw } else { /* port multiplier device port */
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw if (sata_device->satadev_type == SATA_DTYPE_UNKNOWN) {
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw /*
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw * A device was not successfully identified
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw */
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw sata_log(sata_hba_inst, CE_WARN,
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw "Could not identify SATA "
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw "device at port %d:%d", cport, pmport);
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw }
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw }
c75976d12071ddd21443266260066ba036671682pawelw return (ENXIO); /* No device to configure */
c75976d12071ddd21443266260066ba036671682pawelw }
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw /*
c75976d12071ddd21443266260066ba036671682pawelw * Here we may have a device in reset condition,
c75976d12071ddd21443266260066ba036671682pawelw * but because we are just configuring it, there is
c75976d12071ddd21443266260066ba036671682pawelw * no need to process the reset other than just
c75976d12071ddd21443266260066ba036671682pawelw * to clear device reset condition in the HBA driver.
c75976d12071ddd21443266260066ba036671682pawelw * Setting the flag SATA_EVNT_CLEAR_DEVICE_RESET will
c75976d12071ddd21443266260066ba036671682pawelw * cause a first command sent the HBA driver with the request
c75976d12071ddd21443266260066ba036671682pawelw * to clear device reset condition.
c75976d12071ddd21443266260066ba036671682pawelw */
c75976d12071ddd21443266260066ba036671682pawelw mutex_enter(&SATA_CPORT_INFO(sata_hba_inst, cport)->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (qual == SATA_ADDR_DPMPORT)
c75976d12071ddd21443266260066ba036671682pawelw sata_device->satadev_addr.qual = SATA_ADDR_DPMPORT;
c75976d12071ddd21443266260066ba036671682pawelw else
c75976d12071ddd21443266260066ba036671682pawelw sata_device->satadev_addr.qual = SATA_ADDR_DCPORT;
c75976d12071ddd21443266260066ba036671682pawelw sdinfo = sata_get_device_info(sata_hba_inst, sata_device);
c75976d12071ddd21443266260066ba036671682pawelw if (sdinfo == NULL) {
c75976d12071ddd21443266260066ba036671682pawelw mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, cport)->cport_mutex);
c75976d12071ddd21443266260066ba036671682pawelw return (ENXIO);
c75976d12071ddd21443266260066ba036671682pawelw }
c75976d12071ddd21443266260066ba036671682pawelw if (sdinfo->satadrv_event_flags &
c75976d12071ddd21443266260066ba036671682pawelw (SATA_EVNT_DEVICE_RESET | SATA_EVNT_INPROC_DEVICE_RESET)) {
c75976d12071ddd21443266260066ba036671682pawelw sdinfo->satadrv_event_flags = 0;
c75976d12071ddd21443266260066ba036671682pawelw }
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw sdinfo->satadrv_event_flags |= SATA_EVNT_CLEAR_DEVICE_RESET;
c75976d12071ddd21443266260066ba036671682pawelw mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, cport)->cport_mutex);
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw if ((tdip = sata_get_scsi_target_dip(SATA_DIP(sata_hba_inst),
c75976d12071ddd21443266260066ba036671682pawelw &sata_device->satadev_addr)) != NULL) {
c75976d12071ddd21443266260066ba036671682pawelw /*
c75976d12071ddd21443266260066ba036671682pawelw * Target node exists. Verify, that it belongs
c75976d12071ddd21443266260066ba036671682pawelw * to existing, attached device and not to
c75976d12071ddd21443266260066ba036671682pawelw * a removed device.
c75976d12071ddd21443266260066ba036671682pawelw */
c75976d12071ddd21443266260066ba036671682pawelw if (sata_check_device_removed(tdip) == B_TRUE) {
c75976d12071ddd21443266260066ba036671682pawelw if (qual == SATA_ADDR_DPMPORT)
c75976d12071ddd21443266260066ba036671682pawelw sata_log(sata_hba_inst, CE_WARN,
c75976d12071ddd21443266260066ba036671682pawelw "SATA device at port %d cannot be "
c75976d12071ddd21443266260066ba036671682pawelw "configured. "
c75976d12071ddd21443266260066ba036671682pawelw "Application(s) accessing "
c75976d12071ddd21443266260066ba036671682pawelw "previously attached device "
c75976d12071ddd21443266260066ba036671682pawelw "have to release it before newly "
c75976d12071ddd21443266260066ba036671682pawelw "inserted device can be made accessible.",
c75976d12071ddd21443266260066ba036671682pawelw cport);
c75976d12071ddd21443266260066ba036671682pawelw else
c75976d12071ddd21443266260066ba036671682pawelw sata_log(sata_hba_inst, CE_WARN,
c75976d12071ddd21443266260066ba036671682pawelw "SATA device at port %d:%d cannot be"
c75976d12071ddd21443266260066ba036671682pawelw "configured. "
c75976d12071ddd21443266260066ba036671682pawelw "Application(s) accessing "
c75976d12071ddd21443266260066ba036671682pawelw "previously attached device "
c75976d12071ddd21443266260066ba036671682pawelw "have to release it before newly "
c75976d12071ddd21443266260066ba036671682pawelw "inserted device can be made accessible.",
c75976d12071ddd21443266260066ba036671682pawelw cport, pmport);
c75976d12071ddd21443266260066ba036671682pawelw return (EIO);
c75976d12071ddd21443266260066ba036671682pawelw }
c75976d12071ddd21443266260066ba036671682pawelw /*
c75976d12071ddd21443266260066ba036671682pawelw * Device was not removed and re-inserted.
c75976d12071ddd21443266260066ba036671682pawelw * Try to online it.
c75976d12071ddd21443266260066ba036671682pawelw */
c75976d12071ddd21443266260066ba036671682pawelw if (ndi_devi_online(tdip, 0) != NDI_SUCCESS) {
c75976d12071ddd21443266260066ba036671682pawelw SATA_LOG_D((sata_hba_inst, CE_WARN,
c75976d12071ddd21443266260066ba036671682pawelw "sata_hba_ioctl: configure: "
c75976d12071ddd21443266260066ba036671682pawelw "onlining device at SATA port "
c75976d12071ddd21443266260066ba036671682pawelw "%d:%d failed", cport, pmport));
c75976d12071ddd21443266260066ba036671682pawelw return (EIO);
c75976d12071ddd21443266260066ba036671682pawelw }
c75976d12071ddd21443266260066ba036671682pawelw
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (qual == SATA_ADDR_DPMPORT) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&pmportinfo->pmport_mutex);
c75976d12071ddd21443266260066ba036671682pawelw pmportinfo->pmport_tgtnode_clean = B_TRUE;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang } else {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&SATA_CPORT_INFO(sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cport)->cport_mutex);
c75976d12071ddd21443266260066ba036671682pawelw cportinfo-> cport_tgtnode_clean = B_TRUE;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&SATA_CPORT_INFO(
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_hba_inst, cport)->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
c75976d12071ddd21443266260066ba036671682pawelw } else {
c75976d12071ddd21443266260066ba036671682pawelw /*
c75976d12071ddd21443266260066ba036671682pawelw * No target node - need to create a new target node.
c75976d12071ddd21443266260066ba036671682pawelw */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (qual == SATA_ADDR_DPMPORT) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&pmportinfo->pmport_mutex);
c75976d12071ddd21443266260066ba036671682pawelw pmportinfo->pmport_tgtnode_clean = B_TRUE;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang } else {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&SATA_CPORT_INFO(sata_hba_inst, cport)->
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cport_mutex);
c75976d12071ddd21443266260066ba036671682pawelw cportinfo-> cport_tgtnode_clean = B_TRUE;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, cport)->
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw tdip = sata_create_target_node(SATA_DIP(sata_hba_inst),
c75976d12071ddd21443266260066ba036671682pawelw sata_hba_inst, &sata_device->satadev_addr);
c75976d12071ddd21443266260066ba036671682pawelw if (tdip == NULL) {
c75976d12071ddd21443266260066ba036671682pawelw /* Configure operation failed */
c75976d12071ddd21443266260066ba036671682pawelw SATA_LOG_D((sata_hba_inst, CE_WARN,
c75976d12071ddd21443266260066ba036671682pawelw "sata_hba_ioctl: configure: "
c75976d12071ddd21443266260066ba036671682pawelw "configuring SATA device at port %d:%d "
c75976d12071ddd21443266260066ba036671682pawelw "failed", cport, pmport));
c75976d12071ddd21443266260066ba036671682pawelw return (EIO);
c75976d12071ddd21443266260066ba036671682pawelw }
c75976d12071ddd21443266260066ba036671682pawelw }
c75976d12071ddd21443266260066ba036671682pawelw return (0);
c75976d12071ddd21443266260066ba036671682pawelw}
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw/*
c75976d12071ddd21443266260066ba036671682pawelw * Process ioctl deactivate port request.
c75976d12071ddd21443266260066ba036671682pawelw * Arbitrarily unconfigure attached device, if any.
c75976d12071ddd21443266260066ba036671682pawelw * Even if the unconfigure fails, proceed with the
c75976d12071ddd21443266260066ba036671682pawelw * port deactivation.
c75976d12071ddd21443266260066ba036671682pawelw *
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * NOTE: Port Multiplier is supported now.
c75976d12071ddd21443266260066ba036671682pawelw */
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelwstatic int
c75976d12071ddd21443266260066ba036671682pawelwsata_ioctl_deactivate(sata_hba_inst_t *sata_hba_inst,
c75976d12071ddd21443266260066ba036671682pawelw sata_device_t *sata_device)
c75976d12071ddd21443266260066ba036671682pawelw{
c75976d12071ddd21443266260066ba036671682pawelw int cport, pmport, qual;
c75976d12071ddd21443266260066ba036671682pawelw int rval, rv = 0;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang int npmport;
c75976d12071ddd21443266260066ba036671682pawelw sata_cport_info_t *cportinfo;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_pmport_info_t *pmportinfo;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_pmult_info_t *pmultinfo;
c75976d12071ddd21443266260066ba036671682pawelw dev_info_t *tdip;
c75976d12071ddd21443266260066ba036671682pawelw sata_drive_info_t *sdinfo = NULL;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device_t subsdevice;
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw /* Sanity check */
c75976d12071ddd21443266260066ba036671682pawelw if (SATA_PORT_DEACTIVATE_FUNC(sata_hba_inst) == NULL)
c75976d12071ddd21443266260066ba036671682pawelw return (ENOTSUP);
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw cport = sata_device->satadev_addr.cport;
c75976d12071ddd21443266260066ba036671682pawelw pmport = sata_device->satadev_addr.pmport;
c75976d12071ddd21443266260066ba036671682pawelw qual = sata_device->satadev_addr.qual;
c75976d12071ddd21443266260066ba036671682pawelw
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* SCSI_TO_SATA_ADDR_QUAL() translate ap_id into a device qualifier */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang ASSERT(qual == SATA_ADDR_DCPORT || qual == SATA_ADDR_DPMPORT);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (qual == SATA_ADDR_DCPORT)
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang qual = SATA_ADDR_CPORT;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang else
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang qual = SATA_ADDR_PMPORT;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
c75976d12071ddd21443266260066ba036671682pawelw cportinfo = SATA_CPORT_INFO(sata_hba_inst, cport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (qual == SATA_ADDR_PMPORT)
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo = SATA_PMPORT_INFO(sata_hba_inst, cport, pmport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Processing port multiplier
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (qual == SATA_ADDR_CPORT &&
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_CPORT_DEV_TYPE(sata_hba_inst, cport) == SATA_DTYPE_PMULT) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&cportinfo->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Deactivate all sub-deices */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmultinfo = SATA_CPORTINFO_PMULT_INFO(cportinfo);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (pmultinfo != NULL) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang for (npmport = 0; npmport < SATA_NUM_PMPORTS(
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_hba_inst, cport); npmport++) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang subsdevice.satadev_addr.cport = cport;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang subsdevice.satadev_addr.pmport =
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (uint8_t)npmport;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang subsdevice.satadev_addr.qual =
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_ADDR_DPMPORT;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATADBG2(SATA_DBG_PMULT, sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "sata_hba_ioctl: deactivate: trying to "
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "deactivate SATA port %d:%d",
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cport, npmport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&cportinfo->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (sata_ioctl_deactivate(sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang &subsdevice) == SATA_SUCCESS) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATADBG2(SATA_DBG_PMULT, sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "[Deactivate] device at port %d:%d "
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "successfully.", cport, npmport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&cportinfo->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Deactivate the port multiplier now. */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cportinfo->cport_state &= ~SATA_STATE_READY;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&cportinfo->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device->satadev_addr.qual = qual;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang rval = (*SATA_PORT_DEACTIVATE_FUNC(sata_hba_inst))
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (SATA_DIP(sata_hba_inst), sata_device);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_gen_sysevent(sata_hba_inst, &sata_device->satadev_addr,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SE_NO_HINT);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&cportinfo->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_update_port_info(sata_hba_inst, sata_device);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (rval != SATA_SUCCESS) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (sata_device->satadev_state & SATA_PSTATE_FAILED) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cportinfo->cport_state = SATA_PSTATE_FAILED;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang rv = EIO;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang } else {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cportinfo->cport_state |= SATA_PSTATE_SHUTDOWN;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&cportinfo->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang return (rv);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Process non-port-multiplier device - it could be a drive connected
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * to a port multiplier port or a controller port.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&SATA_CPORT_INFO(sata_hba_inst, cport)->cport_mutex);
c75976d12071ddd21443266260066ba036671682pawelw if (qual == SATA_ADDR_CPORT) {
c75976d12071ddd21443266260066ba036671682pawelw sata_device->satadev_addr.qual = SATA_ADDR_DCPORT;
c75976d12071ddd21443266260066ba036671682pawelw if (cportinfo->cport_dev_type != SATA_DTYPE_NONE) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* deal only with valid devices */
c75976d12071ddd21443266260066ba036671682pawelw if ((cportinfo->cport_dev_type &
c75976d12071ddd21443266260066ba036671682pawelw SATA_VALID_DEV_TYPE) != 0)
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw sdinfo = SATA_CPORTINFO_DRV_INFO(cportinfo);
c75976d12071ddd21443266260066ba036671682pawelw }
c75976d12071ddd21443266260066ba036671682pawelw cportinfo->cport_state &= ~SATA_STATE_READY;
c75976d12071ddd21443266260066ba036671682pawelw } else {
c75976d12071ddd21443266260066ba036671682pawelw /* Port multiplier device port */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&pmportinfo->pmport_mutex);
c75976d12071ddd21443266260066ba036671682pawelw sata_device->satadev_addr.qual = SATA_ADDR_DPMPORT;
c75976d12071ddd21443266260066ba036671682pawelw if (pmportinfo->pmport_dev_type != SATA_DTYPE_NONE &&
c75976d12071ddd21443266260066ba036671682pawelw (pmportinfo->pmport_dev_type & SATA_VALID_DEV_TYPE) != 0)
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw sdinfo = SATA_PMPORTINFO_DRV_INFO(pmportinfo);
c75976d12071ddd21443266260066ba036671682pawelw pmportinfo->pmport_state &= ~SATA_STATE_READY;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&pmportinfo->pmport_mutex);
c75976d12071ddd21443266260066ba036671682pawelw }
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw if (sdinfo != NULL) {
c75976d12071ddd21443266260066ba036671682pawelw /*
c75976d12071ddd21443266260066ba036671682pawelw * If a target node exists, try to offline a device and
c75976d12071ddd21443266260066ba036671682pawelw * to remove a target node.
c75976d12071ddd21443266260066ba036671682pawelw */
c75976d12071ddd21443266260066ba036671682pawelw mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, cport)->
c75976d12071ddd21443266260066ba036671682pawelw cport_mutex);
c75976d12071ddd21443266260066ba036671682pawelw tdip = sata_get_scsi_target_dip(SATA_DIP(sata_hba_inst),
c75976d12071ddd21443266260066ba036671682pawelw &sata_device->satadev_addr);
c75976d12071ddd21443266260066ba036671682pawelw if (tdip != NULL) {
c75976d12071ddd21443266260066ba036671682pawelw /* target node exist */
c75976d12071ddd21443266260066ba036671682pawelw SATADBG1(SATA_DBG_IOCTL_IF, sata_hba_inst,
c75976d12071ddd21443266260066ba036671682pawelw "sata_hba_ioctl: port deactivate: "
c75976d12071ddd21443266260066ba036671682pawelw "target node exists.", NULL);
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw if (ndi_devi_offline(tdip, NDI_DEVI_REMOVE) !=
c75976d12071ddd21443266260066ba036671682pawelw NDI_SUCCESS) {
c75976d12071ddd21443266260066ba036671682pawelw SATA_LOG_D((sata_hba_inst, CE_WARN,
c75976d12071ddd21443266260066ba036671682pawelw "sata_hba_ioctl: port deactivate: "
c75976d12071ddd21443266260066ba036671682pawelw "failed to unconfigure device at port "
c75976d12071ddd21443266260066ba036671682pawelw "%d:%d before deactivating the port",
c75976d12071ddd21443266260066ba036671682pawelw cport, pmport));
c75976d12071ddd21443266260066ba036671682pawelw /*
c75976d12071ddd21443266260066ba036671682pawelw * Set DEVICE REMOVED state in the target
c75976d12071ddd21443266260066ba036671682pawelw * node. It will prevent an access to
c75976d12071ddd21443266260066ba036671682pawelw * the device even when a new device is
c75976d12071ddd21443266260066ba036671682pawelw * attached, until the old target node is
c75976d12071ddd21443266260066ba036671682pawelw * released, removed and recreated for a new
c75976d12071ddd21443266260066ba036671682pawelw * device.
c75976d12071ddd21443266260066ba036671682pawelw */
c75976d12071ddd21443266260066ba036671682pawelw sata_set_device_removed(tdip);
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw /*
c75976d12071ddd21443266260066ba036671682pawelw * Instruct the event daemon to try the
c75976d12071ddd21443266260066ba036671682pawelw * target node cleanup later.
c75976d12071ddd21443266260066ba036671682pawelw */
c75976d12071ddd21443266260066ba036671682pawelw sata_set_target_node_cleanup(sata_hba_inst,
c75976d12071ddd21443266260066ba036671682pawelw &sata_device->satadev_addr);
c75976d12071ddd21443266260066ba036671682pawelw }
c75976d12071ddd21443266260066ba036671682pawelw }
c75976d12071ddd21443266260066ba036671682pawelw mutex_enter(&SATA_CPORT_INFO(sata_hba_inst, cport)->
c75976d12071ddd21443266260066ba036671682pawelw cport_mutex);
c75976d12071ddd21443266260066ba036671682pawelw /*
c75976d12071ddd21443266260066ba036671682pawelw * In any case, remove and release sata_drive_info
c75976d12071ddd21443266260066ba036671682pawelw * structure.
c75976d12071ddd21443266260066ba036671682pawelw */
c75976d12071ddd21443266260066ba036671682pawelw if (qual == SATA_ADDR_CPORT) {
c75976d12071ddd21443266260066ba036671682pawelw SATA_CPORTINFO_DRV_INFO(cportinfo) = NULL;
c75976d12071ddd21443266260066ba036671682pawelw cportinfo->cport_dev_type = SATA_DTYPE_NONE;
c75976d12071ddd21443266260066ba036671682pawelw } else { /* port multiplier device port */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&pmportinfo->pmport_mutex);
c75976d12071ddd21443266260066ba036671682pawelw SATA_PMPORTINFO_DRV_INFO(pmportinfo) = NULL;
c75976d12071ddd21443266260066ba036671682pawelw pmportinfo->pmport_dev_type = SATA_DTYPE_NONE;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&pmportinfo->pmport_mutex);
c75976d12071ddd21443266260066ba036671682pawelw }
c75976d12071ddd21443266260066ba036671682pawelw (void) kmem_free((void *)sdinfo, sizeof (sata_drive_info_t));
c75976d12071ddd21443266260066ba036671682pawelw }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
c75976d12071ddd21443266260066ba036671682pawelw if (qual == SATA_ADDR_CPORT) {
c75976d12071ddd21443266260066ba036671682pawelw cportinfo->cport_state &= ~(SATA_STATE_PROBED |
c75976d12071ddd21443266260066ba036671682pawelw SATA_STATE_PROBING);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang } else if (qual == SATA_ADDR_PMPORT) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&pmportinfo->pmport_mutex);
c75976d12071ddd21443266260066ba036671682pawelw pmportinfo->pmport_state &= ~(SATA_STATE_PROBED |
c75976d12071ddd21443266260066ba036671682pawelw SATA_STATE_PROBING);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&pmportinfo->pmport_mutex);
c75976d12071ddd21443266260066ba036671682pawelw }
c75976d12071ddd21443266260066ba036671682pawelw mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, cport)->cport_mutex);
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw /* Just let HBA driver to deactivate port */
c75976d12071ddd21443266260066ba036671682pawelw sata_device->satadev_addr.qual = qual;
c75976d12071ddd21443266260066ba036671682pawelw rval = (*SATA_PORT_DEACTIVATE_FUNC(sata_hba_inst))
c75976d12071ddd21443266260066ba036671682pawelw (SATA_DIP(sata_hba_inst), sata_device);
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw /*
c75976d12071ddd21443266260066ba036671682pawelw * Generate sysevent - EC_DR / ESC_DR_AP_STATE_CHANGE
c75976d12071ddd21443266260066ba036671682pawelw * without the hint
c75976d12071ddd21443266260066ba036671682pawelw */
c75976d12071ddd21443266260066ba036671682pawelw sata_gen_sysevent(sata_hba_inst, &sata_device->satadev_addr,
c75976d12071ddd21443266260066ba036671682pawelw SE_NO_HINT);
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw mutex_enter(&SATA_CPORT_INFO(sata_hba_inst, cport)->cport_mutex);
c75976d12071ddd21443266260066ba036671682pawelw sata_update_port_info(sata_hba_inst, sata_device);
c75976d12071ddd21443266260066ba036671682pawelw if (qual == SATA_ADDR_CPORT) {
c75976d12071ddd21443266260066ba036671682pawelw if (rval != SATA_SUCCESS) {
c75976d12071ddd21443266260066ba036671682pawelw /*
c75976d12071ddd21443266260066ba036671682pawelw * Port deactivation failure - do not change port state
c75976d12071ddd21443266260066ba036671682pawelw * unless the state returned by HBA indicates a port
c75976d12071ddd21443266260066ba036671682pawelw * failure.
c75976d12071ddd21443266260066ba036671682pawelw */
c75976d12071ddd21443266260066ba036671682pawelw if (sata_device->satadev_state & SATA_PSTATE_FAILED) {
c75976d12071ddd21443266260066ba036671682pawelw SATA_CPORT_STATE(sata_hba_inst, cport) =
c75976d12071ddd21443266260066ba036671682pawelw SATA_PSTATE_FAILED;
c75976d12071ddd21443266260066ba036671682pawelw }
c75976d12071ddd21443266260066ba036671682pawelw SATA_LOG_D((sata_hba_inst, CE_WARN,
c75976d12071ddd21443266260066ba036671682pawelw "sata_hba_ioctl: port deactivate: "
c75976d12071ddd21443266260066ba036671682pawelw "cannot deactivate SATA port %d", cport));
c75976d12071ddd21443266260066ba036671682pawelw rv = EIO;
c75976d12071ddd21443266260066ba036671682pawelw } else {
c75976d12071ddd21443266260066ba036671682pawelw cportinfo->cport_state |= SATA_PSTATE_SHUTDOWN;
c75976d12071ddd21443266260066ba036671682pawelw }
c75976d12071ddd21443266260066ba036671682pawelw } else {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&pmportinfo->pmport_mutex);
c75976d12071ddd21443266260066ba036671682pawelw if (rval != SATA_SUCCESS) {
c75976d12071ddd21443266260066ba036671682pawelw if (sata_device->satadev_state & SATA_PSTATE_FAILED) {
c75976d12071ddd21443266260066ba036671682pawelw SATA_PMPORT_STATE(sata_hba_inst, cport,
c75976d12071ddd21443266260066ba036671682pawelw pmport) = SATA_PSTATE_FAILED;
c75976d12071ddd21443266260066ba036671682pawelw }
c75976d12071ddd21443266260066ba036671682pawelw SATA_LOG_D((sata_hba_inst, CE_WARN,
c75976d12071ddd21443266260066ba036671682pawelw "sata_hba_ioctl: port deactivate: "
c75976d12071ddd21443266260066ba036671682pawelw "cannot deactivate SATA port %d:%d",
c75976d12071ddd21443266260066ba036671682pawelw cport, pmport));
c75976d12071ddd21443266260066ba036671682pawelw rv = EIO;
c75976d12071ddd21443266260066ba036671682pawelw } else {
c75976d12071ddd21443266260066ba036671682pawelw pmportinfo->pmport_state |= SATA_PSTATE_SHUTDOWN;
c75976d12071ddd21443266260066ba036671682pawelw }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&pmportinfo->pmport_mutex);
c75976d12071ddd21443266260066ba036671682pawelw }
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, cport)->cport_mutex);
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw return (rv);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown/*
c75976d12071ddd21443266260066ba036671682pawelw * Process ioctl port activate request.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown *
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * NOTE: Port multiplier is supported now.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
c75976d12071ddd21443266260066ba036671682pawelwstatic int
c75976d12071ddd21443266260066ba036671682pawelwsata_ioctl_activate(sata_hba_inst_t *sata_hba_inst,
c75976d12071ddd21443266260066ba036671682pawelw sata_device_t *sata_device)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown{
c75976d12071ddd21443266260066ba036671682pawelw int cport, pmport, qual;
c75976d12071ddd21443266260066ba036671682pawelw sata_cport_info_t *cportinfo;
c75976d12071ddd21443266260066ba036671682pawelw sata_pmport_info_t *pmportinfo = NULL;
c75976d12071ddd21443266260066ba036671682pawelw boolean_t dev_existed = TRUE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
c75976d12071ddd21443266260066ba036671682pawelw /* Sanity check */
c75976d12071ddd21443266260066ba036671682pawelw if (SATA_PORT_ACTIVATE_FUNC(sata_hba_inst) == NULL)
c75976d12071ddd21443266260066ba036671682pawelw return (ENOTSUP);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
c75976d12071ddd21443266260066ba036671682pawelw cport = sata_device->satadev_addr.cport;
c75976d12071ddd21443266260066ba036671682pawelw pmport = sata_device->satadev_addr.pmport;
c75976d12071ddd21443266260066ba036671682pawelw qual = sata_device->satadev_addr.qual;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
c75976d12071ddd21443266260066ba036671682pawelw cportinfo = SATA_CPORT_INFO(sata_hba_inst, cport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * The qual translate from ap_id (by SCSI_TO_SATA_ADDR_QUAL())
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * is a device. But what we are dealing with is port/pmport.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang ASSERT(qual == SATA_ADDR_DCPORT || qual == SATA_ADDR_DPMPORT);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (qual == SATA_ADDR_DCPORT)
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device->satadev_addr.qual = qual = SATA_ADDR_CPORT;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang else
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device->satadev_addr.qual = qual = SATA_ADDR_PMPORT;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&SATA_CPORT_INFO(sata_hba_inst, cport)->cport_mutex);
c75976d12071ddd21443266260066ba036671682pawelw if (qual == SATA_ADDR_PMPORT) {
c75976d12071ddd21443266260066ba036671682pawelw pmportinfo = SATA_PMPORT_INFO(sata_hba_inst, cport, pmport);
c75976d12071ddd21443266260066ba036671682pawelw if (pmportinfo->pmport_state & SATA_PSTATE_SHUTDOWN ||
c75976d12071ddd21443266260066ba036671682pawelw pmportinfo->pmport_dev_type == SATA_DTYPE_NONE)
c75976d12071ddd21443266260066ba036671682pawelw dev_existed = FALSE;
c75976d12071ddd21443266260066ba036671682pawelw } else { /* cport */
c75976d12071ddd21443266260066ba036671682pawelw if (cportinfo->cport_state & SATA_PSTATE_SHUTDOWN ||
c75976d12071ddd21443266260066ba036671682pawelw cportinfo->cport_dev_type == SATA_DTYPE_NONE)
c75976d12071ddd21443266260066ba036671682pawelw dev_existed = FALSE;
c75976d12071ddd21443266260066ba036671682pawelw }
c75976d12071ddd21443266260066ba036671682pawelw mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, cport)->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
c75976d12071ddd21443266260066ba036671682pawelw /* Just let HBA driver to activate port, if necessary */
c75976d12071ddd21443266260066ba036671682pawelw if ((*SATA_PORT_ACTIVATE_FUNC(sata_hba_inst))
c75976d12071ddd21443266260066ba036671682pawelw (SATA_DIP(sata_hba_inst), sata_device) != SATA_SUCCESS) {
c75976d12071ddd21443266260066ba036671682pawelw /*
c75976d12071ddd21443266260066ba036671682pawelw * Port activation failure - do not change port state unless
c75976d12071ddd21443266260066ba036671682pawelw * the state returned by HBA indicates a port failure.
c75976d12071ddd21443266260066ba036671682pawelw */
c75976d12071ddd21443266260066ba036671682pawelw mutex_enter(&SATA_CPORT_INFO(sata_hba_inst,
c75976d12071ddd21443266260066ba036671682pawelw cport)->cport_mutex);
c75976d12071ddd21443266260066ba036671682pawelw sata_update_port_info(sata_hba_inst, sata_device);
c75976d12071ddd21443266260066ba036671682pawelw if (sata_device->satadev_state & SATA_PSTATE_FAILED) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (qual == SATA_ADDR_PMPORT) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&pmportinfo->pmport_mutex);
c75976d12071ddd21443266260066ba036671682pawelw pmportinfo->pmport_state = SATA_PSTATE_FAILED;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang } else
c75976d12071ddd21443266260066ba036671682pawelw cportinfo->cport_state = SATA_PSTATE_FAILED;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
c75976d12071ddd21443266260066ba036671682pawelw mutex_exit(&SATA_CPORT_INFO(sata_hba_inst,
c75976d12071ddd21443266260066ba036671682pawelw cport)->cport_mutex);
c75976d12071ddd21443266260066ba036671682pawelw SATA_LOG_D((sata_hba_inst, CE_WARN,
c75976d12071ddd21443266260066ba036671682pawelw "sata_hba_ioctl: port activate: cannot activate "
c75976d12071ddd21443266260066ba036671682pawelw "SATA port %d:%d", cport, pmport));
c75976d12071ddd21443266260066ba036671682pawelw return (EIO);
c75976d12071ddd21443266260066ba036671682pawelw }
c75976d12071ddd21443266260066ba036671682pawelw mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, cport)->cport_mutex);
c75976d12071ddd21443266260066ba036671682pawelw }
c75976d12071ddd21443266260066ba036671682pawelw mutex_enter(&SATA_CPORT_INFO(sata_hba_inst, cport)->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (qual == SATA_ADDR_PMPORT) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&pmportinfo->pmport_mutex);
c75976d12071ddd21443266260066ba036671682pawelw pmportinfo->pmport_state &= ~SATA_PSTATE_SHUTDOWN;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang } else
c75976d12071ddd21443266260066ba036671682pawelw cportinfo->cport_state &= ~SATA_PSTATE_SHUTDOWN;
c75976d12071ddd21443266260066ba036671682pawelw mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, cport)->cport_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
c75976d12071ddd21443266260066ba036671682pawelw /*
c75976d12071ddd21443266260066ba036671682pawelw * Re-probe port to find its current state and possibly attached device.
c75976d12071ddd21443266260066ba036671682pawelw * Port re-probing may change the cportinfo device type if device is
c75976d12071ddd21443266260066ba036671682pawelw * found attached.
c75976d12071ddd21443266260066ba036671682pawelw * If port probing failed, the device type would be set to
c75976d12071ddd21443266260066ba036671682pawelw * SATA_DTYPE_NONE.
c75976d12071ddd21443266260066ba036671682pawelw */
c75976d12071ddd21443266260066ba036671682pawelw (void) sata_reprobe_port(sata_hba_inst, sata_device,
c75976d12071ddd21443266260066ba036671682pawelw SATA_DEV_IDENTIFY_RETRY);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
c75976d12071ddd21443266260066ba036671682pawelw /*
c75976d12071ddd21443266260066ba036671682pawelw * Generate sysevent - EC_DR / ESC_DR_AP_STATE_CHANGE
c75976d12071ddd21443266260066ba036671682pawelw * without the hint.
c75976d12071ddd21443266260066ba036671682pawelw */
c75976d12071ddd21443266260066ba036671682pawelw sata_gen_sysevent(sata_hba_inst, &sata_device->satadev_addr,
c75976d12071ddd21443266260066ba036671682pawelw SE_NO_HINT);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
c75976d12071ddd21443266260066ba036671682pawelw if (dev_existed == FALSE) {
c75976d12071ddd21443266260066ba036671682pawelw if (qual == SATA_ADDR_PMPORT &&
c75976d12071ddd21443266260066ba036671682pawelw pmportinfo->pmport_dev_type != SATA_DTYPE_NONE) {
c75976d12071ddd21443266260066ba036671682pawelw /*
c75976d12071ddd21443266260066ba036671682pawelw * That's the transition from the "inactive" port state
c75976d12071ddd21443266260066ba036671682pawelw * or the active port without a device attached to the
c75976d12071ddd21443266260066ba036671682pawelw * active port state with a device attached.
c75976d12071ddd21443266260066ba036671682pawelw */
c75976d12071ddd21443266260066ba036671682pawelw sata_log(sata_hba_inst, CE_WARN,
c75976d12071ddd21443266260066ba036671682pawelw "SATA device detected at port %d:%d",
c75976d12071ddd21443266260066ba036671682pawelw cport, pmport);
c75976d12071ddd21443266260066ba036671682pawelw } else if (qual == SATA_ADDR_CPORT &&
c75976d12071ddd21443266260066ba036671682pawelw cportinfo->cport_dev_type != SATA_DTYPE_NONE) {
c75976d12071ddd21443266260066ba036671682pawelw /*
c75976d12071ddd21443266260066ba036671682pawelw * That's the transition from the "inactive" port state
c75976d12071ddd21443266260066ba036671682pawelw * or the active port without a device attached to the
c75976d12071ddd21443266260066ba036671682pawelw * active port state with a device attached.
c75976d12071ddd21443266260066ba036671682pawelw */
c75976d12071ddd21443266260066ba036671682pawelw if (cportinfo->cport_dev_type != SATA_DTYPE_PMULT) {
c75976d12071ddd21443266260066ba036671682pawelw sata_log(sata_hba_inst, CE_WARN,
c75976d12071ddd21443266260066ba036671682pawelw "SATA device detected at port %d", cport);
c75976d12071ddd21443266260066ba036671682pawelw } else {
c75976d12071ddd21443266260066ba036671682pawelw sata_log(sata_hba_inst, CE_WARN,
c75976d12071ddd21443266260066ba036671682pawelw "SATA port multiplier detected at port %d",
c75976d12071ddd21443266260066ba036671682pawelw cport);
c75976d12071ddd21443266260066ba036671682pawelw }
c75976d12071ddd21443266260066ba036671682pawelw }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
c75976d12071ddd21443266260066ba036671682pawelw return (0);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
c75976d12071ddd21443266260066ba036671682pawelw * Process ioctl reset port request.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown *
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * NOTE: Port-Multiplier is supported.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
c75976d12071ddd21443266260066ba036671682pawelwstatic int
c75976d12071ddd21443266260066ba036671682pawelwsata_ioctl_reset_port(sata_hba_inst_t *sata_hba_inst,
c75976d12071ddd21443266260066ba036671682pawelw sata_device_t *sata_device)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
c75976d12071ddd21443266260066ba036671682pawelw int cport, pmport, qual;
c75976d12071ddd21443266260066ba036671682pawelw int rv = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
c75976d12071ddd21443266260066ba036671682pawelw cport = sata_device->satadev_addr.cport;
c75976d12071ddd21443266260066ba036671682pawelw pmport = sata_device->satadev_addr.pmport;
c75976d12071ddd21443266260066ba036671682pawelw qual = sata_device->satadev_addr.qual;
c75976d12071ddd21443266260066ba036671682pawelw
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * The qual translate from ap_id (by SCSI_TO_SATA_ADDR_QUAL())
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * is a device. But what we are dealing with is port/pmport.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (qual == SATA_ADDR_DCPORT)
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device->satadev_addr.qual = qual = SATA_ADDR_CPORT;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang else
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device->satadev_addr.qual = qual = SATA_ADDR_PMPORT;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang ASSERT(qual == SATA_ADDR_CPORT || qual == SATA_ADDR_PMPORT);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
c75976d12071ddd21443266260066ba036671682pawelw /* Sanity check */
c75976d12071ddd21443266260066ba036671682pawelw if (SATA_RESET_DPORT_FUNC(sata_hba_inst) == NULL) {
c75976d12071ddd21443266260066ba036671682pawelw SATA_LOG_D((sata_hba_inst, CE_WARN,
c75976d12071ddd21443266260066ba036671682pawelw "sata_hba_ioctl: sata_hba_tran missing required "
c75976d12071ddd21443266260066ba036671682pawelw "function sata_tran_reset_dport"));
c75976d12071ddd21443266260066ba036671682pawelw return (ENOTSUP);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
c75976d12071ddd21443266260066ba036671682pawelw /* Ask HBA to reset port */
c75976d12071ddd21443266260066ba036671682pawelw if ((*SATA_RESET_DPORT_FUNC(sata_hba_inst))(SATA_DIP(sata_hba_inst),
c75976d12071ddd21443266260066ba036671682pawelw sata_device) != SATA_SUCCESS) {
c75976d12071ddd21443266260066ba036671682pawelw SATA_LOG_D((sata_hba_inst, CE_WARN,
c75976d12071ddd21443266260066ba036671682pawelw "sata_hba_ioctl: reset port: failed %d:%d",
c75976d12071ddd21443266260066ba036671682pawelw cport, pmport));
c75976d12071ddd21443266260066ba036671682pawelw mutex_enter(&SATA_CPORT_INFO(sata_hba_inst, cport)->
c75976d12071ddd21443266260066ba036671682pawelw cport_mutex);
c75976d12071ddd21443266260066ba036671682pawelw sata_update_port_info(sata_hba_inst, sata_device);
c75976d12071ddd21443266260066ba036671682pawelw if (qual == SATA_ADDR_CPORT)
c75976d12071ddd21443266260066ba036671682pawelw SATA_CPORT_STATE(sata_hba_inst, cport) =
c75976d12071ddd21443266260066ba036671682pawelw SATA_PSTATE_FAILED;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang else {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&SATA_PMPORT_MUTEX(sata_hba_inst, cport,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmport));
c75976d12071ddd21443266260066ba036671682pawelw SATA_PMPORT_STATE(sata_hba_inst, cport, pmport) =
c75976d12071ddd21443266260066ba036671682pawelw SATA_PSTATE_FAILED;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&SATA_PMPORT_MUTEX(sata_hba_inst, cport,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmport));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
c75976d12071ddd21443266260066ba036671682pawelw mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, cport)->
c75976d12071ddd21443266260066ba036671682pawelw cport_mutex);
c75976d12071ddd21443266260066ba036671682pawelw rv = EIO;
c75976d12071ddd21443266260066ba036671682pawelw }
c75976d12071ddd21443266260066ba036671682pawelw /*
c75976d12071ddd21443266260066ba036671682pawelw * Beacuse the port was reset, it should be probed and
c75976d12071ddd21443266260066ba036671682pawelw * attached device reinitialized. At this point the
c75976d12071ddd21443266260066ba036671682pawelw * port state is unknown - it's state is HBA-specific.
c75976d12071ddd21443266260066ba036671682pawelw * Re-probe port to get its state.
c75976d12071ddd21443266260066ba036671682pawelw */
c75976d12071ddd21443266260066ba036671682pawelw if (sata_reprobe_port(sata_hba_inst, sata_device,
c75976d12071ddd21443266260066ba036671682pawelw SATA_DEV_IDENTIFY_RETRY) != SATA_SUCCESS) {
c75976d12071ddd21443266260066ba036671682pawelw rv = EIO;
c75976d12071ddd21443266260066ba036671682pawelw }
c75976d12071ddd21443266260066ba036671682pawelw return (rv);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
c75976d12071ddd21443266260066ba036671682pawelw * Process ioctl reset device request.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown *
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * NOTE: Port multiplier is supported.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
c75976d12071ddd21443266260066ba036671682pawelwstatic int
c75976d12071ddd21443266260066ba036671682pawelwsata_ioctl_reset_device(sata_hba_inst_t *sata_hba_inst,
c75976d12071ddd21443266260066ba036671682pawelw sata_device_t *sata_device)
c75976d12071ddd21443266260066ba036671682pawelw{
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_drive_info_t *sdinfo = NULL;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_pmult_info_t *pmultinfo = NULL;
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw int cport, pmport;
c75976d12071ddd21443266260066ba036671682pawelw int rv = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
c75976d12071ddd21443266260066ba036671682pawelw /* Sanity check */
c75976d12071ddd21443266260066ba036671682pawelw if (SATA_RESET_DPORT_FUNC(sata_hba_inst) == NULL) {
c75976d12071ddd21443266260066ba036671682pawelw SATA_LOG_D((sata_hba_inst, CE_WARN,
c75976d12071ddd21443266260066ba036671682pawelw "sata_hba_ioctl: sata_hba_tran missing required "
c75976d12071ddd21443266260066ba036671682pawelw "function sata_tran_reset_dport"));
c75976d12071ddd21443266260066ba036671682pawelw return (ENOTSUP);
c75976d12071ddd21443266260066ba036671682pawelw }
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw cport = sata_device->satadev_addr.cport;
c75976d12071ddd21443266260066ba036671682pawelw pmport = sata_device->satadev_addr.pmport;
c75976d12071ddd21443266260066ba036671682pawelw
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw mutex_enter(&SATA_CPORT_INFO(sata_hba_inst, cport)->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (sata_device->satadev_addr.qual == SATA_ADDR_DCPORT) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (SATA_CPORT_DEV_TYPE(sata_hba_inst, cport) ==
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_DTYPE_PMULT)
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmultinfo = SATA_CPORT_INFO(sata_hba_inst, cport)->
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cport_devp.cport_sata_pmult;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang else
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sdinfo = SATA_CPORT_DRV_INFO(sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device->satadev_addr.cport);
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw } else { /* port multiplier */
c75976d12071ddd21443266260066ba036671682pawelw sata_device->satadev_addr.qual = SATA_ADDR_DPMPORT;
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw sdinfo = SATA_PMPORT_DRV_INFO(sata_hba_inst,
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw sata_device->satadev_addr.cport,
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw sata_device->satadev_addr.pmport);
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (sdinfo == NULL && pmultinfo == NULL) {
c75976d12071ddd21443266260066ba036671682pawelw mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, cport)->cport_mutex);
c75976d12071ddd21443266260066ba036671682pawelw return (EINVAL);
c75976d12071ddd21443266260066ba036671682pawelw }
c75976d12071ddd21443266260066ba036671682pawelw mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, cport)->cport_mutex);
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw /* Ask HBA to reset device */
c75976d12071ddd21443266260066ba036671682pawelw if ((*SATA_RESET_DPORT_FUNC(sata_hba_inst))
c75976d12071ddd21443266260066ba036671682pawelw (SATA_DIP(sata_hba_inst), sata_device) != SATA_SUCCESS) {
c75976d12071ddd21443266260066ba036671682pawelw SATA_LOG_D((sata_hba_inst, CE_WARN,
c75976d12071ddd21443266260066ba036671682pawelw "sata_hba_ioctl: reset device: failed at port %d:%d",
c75976d12071ddd21443266260066ba036671682pawelw cport, pmport));
c75976d12071ddd21443266260066ba036671682pawelw mutex_enter(&SATA_CPORT_INFO(sata_hba_inst, cport)->
c75976d12071ddd21443266260066ba036671682pawelw cport_mutex);
c75976d12071ddd21443266260066ba036671682pawelw sata_update_port_info(sata_hba_inst, sata_device);
c75976d12071ddd21443266260066ba036671682pawelw /*
c75976d12071ddd21443266260066ba036671682pawelw * Device info structure remains attached. Another device reset
c75976d12071ddd21443266260066ba036671682pawelw * or port disconnect/connect and re-probing is
c75976d12071ddd21443266260066ba036671682pawelw * needed to change it's state
c75976d12071ddd21443266260066ba036671682pawelw */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (sdinfo != NULL) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sdinfo->satadrv_state &= ~SATA_STATE_READY;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sdinfo->satadrv_state |= SATA_DSTATE_FAILED;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang } else if (pmultinfo != NULL) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmultinfo->pmult_state &= ~SATA_STATE_READY;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmultinfo->pmult_state |= SATA_DSTATE_FAILED;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
c75976d12071ddd21443266260066ba036671682pawelw mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, cport)->cport_mutex);
c75976d12071ddd21443266260066ba036671682pawelw rv = EIO;
c75976d12071ddd21443266260066ba036671682pawelw }
c75976d12071ddd21443266260066ba036671682pawelw /*
c75976d12071ddd21443266260066ba036671682pawelw * If attached device was a port multiplier, some extra processing
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * may be needed to bring it back. SATA specification requies a
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * mandatory software reset on host port to reliably enumerate a port
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * multiplier, the HBA driver should handle that after reset
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * operation.
c75976d12071ddd21443266260066ba036671682pawelw */
c75976d12071ddd21443266260066ba036671682pawelw return (rv);
c75976d12071ddd21443266260066ba036671682pawelw}
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw/*
c75976d12071ddd21443266260066ba036671682pawelw * Process ioctl reset all request.
c75976d12071ddd21443266260066ba036671682pawelw */
c75976d12071ddd21443266260066ba036671682pawelwstatic int
c75976d12071ddd21443266260066ba036671682pawelwsata_ioctl_reset_all(sata_hba_inst_t *sata_hba_inst)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
c75976d12071ddd21443266260066ba036671682pawelw sata_device_t sata_device;
c75976d12071ddd21443266260066ba036671682pawelw int rv = 0;
c75976d12071ddd21443266260066ba036671682pawelw int tcport;
c75976d12071ddd21443266260066ba036671682pawelw int tpmport = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
c75976d12071ddd21443266260066ba036671682pawelw sata_device.satadev_rev = SATA_DEVICE_REV;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
c75976d12071ddd21443266260066ba036671682pawelw /*
c75976d12071ddd21443266260066ba036671682pawelw * There is no protection here for configured devices.
c75976d12071ddd21443266260066ba036671682pawelw */
c75976d12071ddd21443266260066ba036671682pawelw /* Sanity check */
c75976d12071ddd21443266260066ba036671682pawelw if (SATA_RESET_DPORT_FUNC(sata_hba_inst) == NULL) {
c75976d12071ddd21443266260066ba036671682pawelw SATA_LOG_D((sata_hba_inst, CE_WARN,
c75976d12071ddd21443266260066ba036671682pawelw "sata_hba_ioctl: sata_hba_tran missing required "
c75976d12071ddd21443266260066ba036671682pawelw "function sata_tran_reset_dport"));
c75976d12071ddd21443266260066ba036671682pawelw return (ENOTSUP);
c75976d12071ddd21443266260066ba036671682pawelw }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
c75976d12071ddd21443266260066ba036671682pawelw /*
c75976d12071ddd21443266260066ba036671682pawelw * Need to lock all ports, not just one.
c75976d12071ddd21443266260066ba036671682pawelw * If any port is locked by event processing, fail the whole operation.
c75976d12071ddd21443266260066ba036671682pawelw * One port is already locked, but for simplicity lock it again.
c75976d12071ddd21443266260066ba036671682pawelw */
c75976d12071ddd21443266260066ba036671682pawelw for (tcport = 0; tcport < SATA_NUM_CPORTS(sata_hba_inst); tcport++) {
c75976d12071ddd21443266260066ba036671682pawelw mutex_enter(&SATA_CPORT_INFO(sata_hba_inst, tcport)->
c75976d12071ddd21443266260066ba036671682pawelw cport_mutex);
c75976d12071ddd21443266260066ba036671682pawelw if (((SATA_CPORT_INFO(sata_hba_inst, tcport)->
c75976d12071ddd21443266260066ba036671682pawelw cport_event_flags) & SATA_EVNT_LOCK_PORT_BUSY) != 0) {
c75976d12071ddd21443266260066ba036671682pawelw mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, tcport)->
c75976d12071ddd21443266260066ba036671682pawelw cport_mutex);
c75976d12071ddd21443266260066ba036671682pawelw rv = EBUSY;
c75976d12071ddd21443266260066ba036671682pawelw break;
c75976d12071ddd21443266260066ba036671682pawelw } else {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * It is enough to lock cport in command-based
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * switching mode.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_CPORT_INFO(sata_hba_inst, tcport)->
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cport_event_flags |= SATA_APCTL_LOCK_PORT_BUSY;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
c75976d12071ddd21443266260066ba036671682pawelw mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, tcport)->
c75976d12071ddd21443266260066ba036671682pawelw cport_mutex);
c75976d12071ddd21443266260066ba036671682pawelw }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
c75976d12071ddd21443266260066ba036671682pawelw if (rv == 0) {
c75976d12071ddd21443266260066ba036671682pawelw /*
c75976d12071ddd21443266260066ba036671682pawelw * All cports were successfully locked.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Reset main SATA controller.
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw * Set the device address to port 0, to have a valid device
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw * address.
c75976d12071ddd21443266260066ba036671682pawelw */
c75976d12071ddd21443266260066ba036671682pawelw sata_device.satadev_addr.qual = SATA_ADDR_CNTRL;
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw sata_device.satadev_addr.cport = 0;
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw sata_device.satadev_addr.pmport = 0;
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw if ((*SATA_RESET_DPORT_FUNC(sata_hba_inst))
c75976d12071ddd21443266260066ba036671682pawelw (SATA_DIP(sata_hba_inst), &sata_device) != SATA_SUCCESS) {
c75976d12071ddd21443266260066ba036671682pawelw SATA_LOG_D((sata_hba_inst, CE_WARN,
c75976d12071ddd21443266260066ba036671682pawelw "sata_hba_ioctl: reset controller failed"));
c75976d12071ddd21443266260066ba036671682pawelw return (EIO);
c75976d12071ddd21443266260066ba036671682pawelw }
c75976d12071ddd21443266260066ba036671682pawelw /*
c75976d12071ddd21443266260066ba036671682pawelw * Because ports were reset, port states are unknown.
c75976d12071ddd21443266260066ba036671682pawelw * They should be re-probed to get their state and
c75976d12071ddd21443266260066ba036671682pawelw * attached devices should be reinitialized.
c75976d12071ddd21443266260066ba036671682pawelw */
c75976d12071ddd21443266260066ba036671682pawelw for (tcport = 0; tcport < SATA_NUM_CPORTS(sata_hba_inst);
c75976d12071ddd21443266260066ba036671682pawelw tcport++) {
c75976d12071ddd21443266260066ba036671682pawelw sata_device.satadev_addr.cport = tcport;
c75976d12071ddd21443266260066ba036671682pawelw sata_device.satadev_addr.pmport = tpmport;
c75976d12071ddd21443266260066ba036671682pawelw sata_device.satadev_addr.qual = SATA_ADDR_CPORT;
c75976d12071ddd21443266260066ba036671682pawelw
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * The sata_reprobe_port() will mark a
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * SATA_EVNT_DEVICE_RESET event on the port
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * multiplier, all its sub-ports will be probed by
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * sata daemon afterwards.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
c75976d12071ddd21443266260066ba036671682pawelw if (sata_reprobe_port(sata_hba_inst, &sata_device,
c75976d12071ddd21443266260066ba036671682pawelw SATA_DEV_IDENTIFY_RETRY) != SATA_SUCCESS)
c75976d12071ddd21443266260066ba036671682pawelw rv = EIO;
c75976d12071ddd21443266260066ba036671682pawelw }
c75976d12071ddd21443266260066ba036671682pawelw }
c75976d12071ddd21443266260066ba036671682pawelw /*
c75976d12071ddd21443266260066ba036671682pawelw * Unlock all ports
c75976d12071ddd21443266260066ba036671682pawelw */
c75976d12071ddd21443266260066ba036671682pawelw for (tcport = 0; tcport < SATA_NUM_CPORTS(sata_hba_inst); tcport++) {
c75976d12071ddd21443266260066ba036671682pawelw mutex_enter(&SATA_CPORT_INFO(sata_hba_inst, tcport)->
c75976d12071ddd21443266260066ba036671682pawelw cport_mutex);
c75976d12071ddd21443266260066ba036671682pawelw SATA_CPORT_INFO(sata_hba_inst, tcport)->
c75976d12071ddd21443266260066ba036671682pawelw cport_event_flags &= ~SATA_APCTL_LOCK_PORT_BUSY;
c75976d12071ddd21443266260066ba036671682pawelw mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, tcport)->
c75976d12071ddd21443266260066ba036671682pawelw cport_mutex);
c75976d12071ddd21443266260066ba036671682pawelw }
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw /*
c75976d12071ddd21443266260066ba036671682pawelw * This operation returns EFAULT if either reset
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw * controller failed or a re-probing of any port failed.
c75976d12071ddd21443266260066ba036671682pawelw */
c75976d12071ddd21443266260066ba036671682pawelw return (rv);
c75976d12071ddd21443266260066ba036671682pawelw}
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw/*
c75976d12071ddd21443266260066ba036671682pawelw * Process ioctl port self test request.
c75976d12071ddd21443266260066ba036671682pawelw *
c75976d12071ddd21443266260066ba036671682pawelw * NOTE: Port multiplier code is not completed nor tested.
c75976d12071ddd21443266260066ba036671682pawelw */
c75976d12071ddd21443266260066ba036671682pawelwstatic int
c75976d12071ddd21443266260066ba036671682pawelwsata_ioctl_port_self_test(sata_hba_inst_t *sata_hba_inst,
c75976d12071ddd21443266260066ba036671682pawelw sata_device_t *sata_device)
c75976d12071ddd21443266260066ba036671682pawelw{
c75976d12071ddd21443266260066ba036671682pawelw int cport, pmport, qual;
c75976d12071ddd21443266260066ba036671682pawelw int rv = 0;
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw /* Sanity check */
c75976d12071ddd21443266260066ba036671682pawelw if (SATA_SELFTEST_FUNC(sata_hba_inst) == NULL)
c75976d12071ddd21443266260066ba036671682pawelw return (ENOTSUP);
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw cport = sata_device->satadev_addr.cport;
c75976d12071ddd21443266260066ba036671682pawelw pmport = sata_device->satadev_addr.pmport;
c75976d12071ddd21443266260066ba036671682pawelw qual = sata_device->satadev_addr.qual;
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw /*
c75976d12071ddd21443266260066ba036671682pawelw * There is no protection here for a configured
c75976d12071ddd21443266260066ba036671682pawelw * device attached to this port.
c75976d12071ddd21443266260066ba036671682pawelw */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
c75976d12071ddd21443266260066ba036671682pawelw if ((*SATA_SELFTEST_FUNC(sata_hba_inst))
c75976d12071ddd21443266260066ba036671682pawelw (SATA_DIP(sata_hba_inst), sata_device) != SATA_SUCCESS) {
c75976d12071ddd21443266260066ba036671682pawelw SATA_LOG_D((sata_hba_inst, CE_WARN,
c75976d12071ddd21443266260066ba036671682pawelw "sata_hba_ioctl: port selftest: "
c75976d12071ddd21443266260066ba036671682pawelw "failed port %d:%d", cport, pmport));
c75976d12071ddd21443266260066ba036671682pawelw mutex_enter(&SATA_CPORT_INFO(sata_hba_inst, cport)->
c75976d12071ddd21443266260066ba036671682pawelw cport_mutex);
c75976d12071ddd21443266260066ba036671682pawelw sata_update_port_info(sata_hba_inst, sata_device);
c75976d12071ddd21443266260066ba036671682pawelw if (qual == SATA_ADDR_CPORT)
c75976d12071ddd21443266260066ba036671682pawelw SATA_CPORT_STATE(sata_hba_inst, cport) =
c75976d12071ddd21443266260066ba036671682pawelw SATA_PSTATE_FAILED;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang else { /* port multiplier device port */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&SATA_PMPORT_MUTEX(sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cport, pmport));
c75976d12071ddd21443266260066ba036671682pawelw SATA_PMPORT_STATE(sata_hba_inst, cport, pmport) =
c75976d12071ddd21443266260066ba036671682pawelw SATA_PSTATE_FAILED;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&SATA_PMPORT_MUTEX(sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cport, pmport));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, cport)->
c75976d12071ddd21443266260066ba036671682pawelw cport_mutex);
c75976d12071ddd21443266260066ba036671682pawelw return (EIO);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
c75976d12071ddd21443266260066ba036671682pawelw /*
c75976d12071ddd21443266260066ba036671682pawelw * Beacuse the port was reset in the course of testing, it should be
c75976d12071ddd21443266260066ba036671682pawelw * re-probed and attached device state should be restored. At this
c75976d12071ddd21443266260066ba036671682pawelw * point the port state is unknown - it's state is HBA-specific.
c75976d12071ddd21443266260066ba036671682pawelw * Force port re-probing to get it into a known state.
c75976d12071ddd21443266260066ba036671682pawelw */
c75976d12071ddd21443266260066ba036671682pawelw if (sata_reprobe_port(sata_hba_inst, sata_device,
c75976d12071ddd21443266260066ba036671682pawelw SATA_DEV_IDENTIFY_RETRY) != SATA_SUCCESS)
c75976d12071ddd21443266260066ba036671682pawelw rv = EIO;
c75976d12071ddd21443266260066ba036671682pawelw return (rv);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * sata_cfgadm_state:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Use the sata port state and state of the target node to figure out
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * the cfgadm_state.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown *
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * The port argument is a value with encoded cport,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * pmport and address qualifier, in the same manner as a scsi target number.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * SCSI_TO_SATA_CPORT macro extracts cport number,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * SCSI_TO_SATA_PMPORT extracts pmport number and
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * SCSI_TO_SATA_ADDR_QUAL extracts port mulitplier qualifier flag.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown *
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Port multiplier is supported.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void
2038334ab26baaa43c9083f35def041511c3cc1fUnknownsata_cfgadm_state(sata_hba_inst_t *sata_hba_inst, int32_t port,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown devctl_ap_state_t *ap_state)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang uint8_t cport, pmport, qual;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang uint32_t port_state, pmult_state;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang uint32_t dev_type;
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw sata_drive_info_t *sdinfo;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cport = SCSI_TO_SATA_CPORT(port);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmport = SCSI_TO_SATA_PMPORT(port);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang qual = SCSI_TO_SATA_ADDR_QUAL(port);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Check cport state */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown port_state = SATA_CPORT_STATE(sata_hba_inst, cport);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (port_state & SATA_PSTATE_SHUTDOWN ||
2038334ab26baaa43c9083f35def041511c3cc1fUnknown port_state & SATA_PSTATE_FAILED) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ap_state->ap_rstate = AP_RSTATE_DISCONNECTED;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ap_state->ap_ostate = AP_OSTATE_UNCONFIGURED;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (port_state & SATA_PSTATE_FAILED)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ap_state->ap_condition = AP_COND_FAILED;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown else
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ap_state->ap_condition = AP_COND_UNKNOWN;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* cport state is okay. Now check pmport state */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (qual == SATA_ADDR_DPMPORT || qual == SATA_ADDR_PMPORT) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Sanity check */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (SATA_CPORT_DEV_TYPE(sata_hba_inst, cport) !=
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_DTYPE_PMULT || SATA_PMPORT_INFO(sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cport, pmport) == NULL)
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang return;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang port_state = SATA_PMPORT_STATE(sata_hba_inst, cport, pmport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (port_state & SATA_PSTATE_SHUTDOWN ||
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang port_state & SATA_PSTATE_FAILED) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang ap_state->ap_rstate = AP_RSTATE_DISCONNECTED;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang ap_state->ap_ostate = AP_OSTATE_UNCONFIGURED;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (port_state & SATA_PSTATE_FAILED)
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang ap_state->ap_condition = AP_COND_FAILED;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang else
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang ap_state->ap_condition = AP_COND_UNKNOWN;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang return;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Port is enabled and ready */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (qual == SATA_ADDR_DCPORT || qual == SATA_ADDR_CPORT)
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang dev_type = SATA_CPORT_DEV_TYPE(sata_hba_inst, cport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang else
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang dev_type = SATA_PMPORT_DEV_TYPE(sata_hba_inst, cport, pmport);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang switch (dev_type) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown case SATA_DTYPE_NONE:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ap_state->ap_ostate = AP_OSTATE_UNCONFIGURED;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ap_state->ap_condition = AP_COND_OK;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* No device attached */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ap_state->ap_rstate = AP_RSTATE_EMPTY;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown break;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang case SATA_DTYPE_PMULT:
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Need to check port multiplier state */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang ASSERT(qual == SATA_ADDR_DCPORT);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmult_state = SATA_PMULT_INFO(sata_hba_inst, cport)->
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmult_state;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (pmult_state & (SATA_PSTATE_SHUTDOWN|SATA_PSTATE_FAILED)) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang ap_state->ap_rstate = AP_RSTATE_DISCONNECTED;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang ap_state->ap_ostate = AP_OSTATE_UNCONFIGURED;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (pmult_state & SATA_PSTATE_FAILED)
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang ap_state->ap_condition = AP_COND_FAILED;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang else
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang ap_state->ap_condition = AP_COND_UNKNOWN;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang return;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Port multiplier is not configurable */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang ap_state->ap_ostate = AP_OSTATE_CONFIGURED;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang ap_state->ap_rstate = AP_RSTATE_CONNECTED;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang ap_state->ap_condition = AP_COND_OK;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang break;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
2038334ab26baaa43c9083f35def041511c3cc1fUnknown case SATA_DTYPE_ATADISK:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown case SATA_DTYPE_ATAPICD:
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China case SATA_DTYPE_ATAPITAPE:
f8a673ad9145b262edb65a98fb3fb92027d23a05ying tian - Beijing China case SATA_DTYPE_ATAPIDISK:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown dev_info_t *tdip = NULL;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown dev_info_t *dip = NULL;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown int circ;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown dip = SATA_DIP(sata_hba_inst);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang tdip = sata_get_target_dip(dip, cport, pmport);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ap_state->ap_rstate = AP_RSTATE_CONNECTED;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (tdip != NULL) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ndi_devi_enter(dip, &circ);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_enter(&(DEVI(tdip)->devi_lock));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (DEVI_IS_DEVICE_REMOVED(tdip)) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * There could be the case where previously
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * configured and opened device was removed
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * and unknown device was plugged.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * In such case we want to show a device, and
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * its configured or unconfigured state but
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * indicate unusable condition untill the
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * old target node is released and removed.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ap_state->ap_condition = AP_COND_UNUSABLE;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown } else {
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw mutex_enter(&SATA_CPORT_MUTEX(sata_hba_inst,
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw cport));
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw sdinfo = SATA_CPORT_DRV_INFO(sata_hba_inst,
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw cport);
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw if (sdinfo != NULL) {
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw if ((sdinfo->satadrv_state &
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw SATA_DSTATE_FAILED) != 0)
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw ap_state->ap_condition =
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw AP_COND_FAILED;
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw else
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw ap_state->ap_condition =
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw AP_COND_OK;
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw } else {
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw ap_state->ap_condition =
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw AP_COND_UNKNOWN;
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw }
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw mutex_exit(&SATA_CPORT_MUTEX(sata_hba_inst,
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw cport));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if ((DEVI_IS_DEVICE_OFFLINE(tdip)) ||
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (DEVI_IS_DEVICE_DOWN(tdip))) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ap_state->ap_ostate =
2038334ab26baaa43c9083f35def041511c3cc1fUnknown AP_OSTATE_UNCONFIGURED;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown } else {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ap_state->ap_ostate =
2038334ab26baaa43c9083f35def041511c3cc1fUnknown AP_OSTATE_CONFIGURED;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&(DEVI(tdip)->devi_lock));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ndi_devi_exit(dip, circ);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown } else {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ap_state->ap_ostate = AP_OSTATE_UNCONFIGURED;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ap_state->ap_condition = AP_COND_UNKNOWN;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown break;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown default:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ap_state->ap_rstate = AP_RSTATE_CONNECTED;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ap_state->ap_ostate = AP_OSTATE_UNCONFIGURED;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ap_state->ap_condition = AP_COND_UNKNOWN;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * This is actually internal error condition (non fatal),
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * because we have already checked all defined device types.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_LOG_D((sata_hba_inst, CE_WARN,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "sata_cfgadm_state: Internal error: "
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "unknown device type"));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown break;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
c75976d12071ddd21443266260066ba036671682pawelw/*
c75976d12071ddd21443266260066ba036671682pawelw * Process ioctl get device path request.
c75976d12071ddd21443266260066ba036671682pawelw *
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * NOTE: Port multiplier has no target dip. Devices connected to port
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * multiplier have target node attached to the HBA node. The only difference
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * between them and the directly-attached device node is a target address.
c75976d12071ddd21443266260066ba036671682pawelw */
c75976d12071ddd21443266260066ba036671682pawelwstatic int
c75976d12071ddd21443266260066ba036671682pawelwsata_ioctl_get_device_path(sata_hba_inst_t *sata_hba_inst,
c75976d12071ddd21443266260066ba036671682pawelw sata_device_t *sata_device, sata_ioctl_data_t *ioc, int mode)
c75976d12071ddd21443266260066ba036671682pawelw{
c75976d12071ddd21443266260066ba036671682pawelw char path[MAXPATHLEN];
c75976d12071ddd21443266260066ba036671682pawelw uint32_t size;
c75976d12071ddd21443266260066ba036671682pawelw dev_info_t *tdip;
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw (void) strcpy(path, "/devices");
c75976d12071ddd21443266260066ba036671682pawelw if ((tdip = sata_get_scsi_target_dip(SATA_DIP(sata_hba_inst),
c75976d12071ddd21443266260066ba036671682pawelw &sata_device->satadev_addr)) == NULL) {
c75976d12071ddd21443266260066ba036671682pawelw /*
c75976d12071ddd21443266260066ba036671682pawelw * No such device. If this is a request for a size, do not
c75976d12071ddd21443266260066ba036671682pawelw * return EINVAL for non-existing target, because cfgadm
c75976d12071ddd21443266260066ba036671682pawelw * will then indicate a meaningless ioctl failure.
c75976d12071ddd21443266260066ba036671682pawelw * If this is a request for a path, indicate invalid
c75976d12071ddd21443266260066ba036671682pawelw * argument.
c75976d12071ddd21443266260066ba036671682pawelw */
c75976d12071ddd21443266260066ba036671682pawelw if (ioc->get_size == 0)
c75976d12071ddd21443266260066ba036671682pawelw return (EINVAL);
c75976d12071ddd21443266260066ba036671682pawelw } else {
c75976d12071ddd21443266260066ba036671682pawelw (void) ddi_pathname(tdip, path + strlen(path));
c75976d12071ddd21443266260066ba036671682pawelw }
c75976d12071ddd21443266260066ba036671682pawelw size = strlen(path) + 1;
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw if (ioc->get_size != 0) {
c75976d12071ddd21443266260066ba036671682pawelw if (ddi_copyout((void *)&size, ioc->buf, ioc->bufsiz,
c75976d12071ddd21443266260066ba036671682pawelw mode) != 0)
c75976d12071ddd21443266260066ba036671682pawelw return (EFAULT);
c75976d12071ddd21443266260066ba036671682pawelw } else {
c75976d12071ddd21443266260066ba036671682pawelw if (ioc->bufsiz != size)
c75976d12071ddd21443266260066ba036671682pawelw return (EINVAL);
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw else if (ddi_copyout((void *)&path, ioc->buf, ioc->bufsiz,
c75976d12071ddd21443266260066ba036671682pawelw mode) != 0)
c75976d12071ddd21443266260066ba036671682pawelw return (EFAULT);
c75976d12071ddd21443266260066ba036671682pawelw }
c75976d12071ddd21443266260066ba036671682pawelw return (0);
c75976d12071ddd21443266260066ba036671682pawelw}
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw/*
c75976d12071ddd21443266260066ba036671682pawelw * Process ioctl get attachment point type request.
c75976d12071ddd21443266260066ba036671682pawelw *
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * NOTE: Port multiplier is supported.
c75976d12071ddd21443266260066ba036671682pawelw */
c75976d12071ddd21443266260066ba036671682pawelwstatic int
c75976d12071ddd21443266260066ba036671682pawelwsata_ioctl_get_ap_type(sata_hba_inst_t *sata_hba_inst,
c75976d12071ddd21443266260066ba036671682pawelw sata_device_t *sata_device, sata_ioctl_data_t *ioc, int mode)
c75976d12071ddd21443266260066ba036671682pawelw{
c75976d12071ddd21443266260066ba036671682pawelw uint32_t type_len;
c75976d12071ddd21443266260066ba036671682pawelw const char *ap_type;
c75976d12071ddd21443266260066ba036671682pawelw int dev_type;
c75976d12071ddd21443266260066ba036671682pawelw
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (sata_device->satadev_addr.qual == SATA_ADDR_DCPORT)
c75976d12071ddd21443266260066ba036671682pawelw dev_type = SATA_CPORT_DEV_TYPE(sata_hba_inst,
c75976d12071ddd21443266260066ba036671682pawelw sata_device->satadev_addr.cport);
c75976d12071ddd21443266260066ba036671682pawelw else /* pmport */
c75976d12071ddd21443266260066ba036671682pawelw dev_type = SATA_PMPORT_DEV_TYPE(sata_hba_inst,
c75976d12071ddd21443266260066ba036671682pawelw sata_device->satadev_addr.cport,
c75976d12071ddd21443266260066ba036671682pawelw sata_device->satadev_addr.pmport);
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw switch (dev_type) {
c75976d12071ddd21443266260066ba036671682pawelw case SATA_DTYPE_NONE:
c75976d12071ddd21443266260066ba036671682pawelw ap_type = "port";
c75976d12071ddd21443266260066ba036671682pawelw break;
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw case SATA_DTYPE_ATADISK:
f8a673ad9145b262edb65a98fb3fb92027d23a05ying tian - Beijing China case SATA_DTYPE_ATAPIDISK:
c75976d12071ddd21443266260066ba036671682pawelw ap_type = "disk";
c75976d12071ddd21443266260066ba036671682pawelw break;
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw case SATA_DTYPE_ATAPICD:
c75976d12071ddd21443266260066ba036671682pawelw ap_type = "cd/dvd";
c75976d12071ddd21443266260066ba036671682pawelw break;
c75976d12071ddd21443266260066ba036671682pawelw
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China case SATA_DTYPE_ATAPITAPE:
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China ap_type = "tape";
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China break;
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China
c75976d12071ddd21443266260066ba036671682pawelw case SATA_DTYPE_PMULT:
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang ap_type = "sata-pmult";
c75976d12071ddd21443266260066ba036671682pawelw break;
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw case SATA_DTYPE_UNKNOWN:
c75976d12071ddd21443266260066ba036671682pawelw ap_type = "unknown";
c75976d12071ddd21443266260066ba036671682pawelw break;
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw default:
c75976d12071ddd21443266260066ba036671682pawelw ap_type = "unsupported";
c75976d12071ddd21443266260066ba036671682pawelw break;
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw } /* end of dev_type switch */
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw type_len = strlen(ap_type) + 1;
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw if (ioc->get_size) {
c75976d12071ddd21443266260066ba036671682pawelw if (ddi_copyout((void *)&type_len, ioc->buf, ioc->bufsiz,
c75976d12071ddd21443266260066ba036671682pawelw mode) != 0)
c75976d12071ddd21443266260066ba036671682pawelw return (EFAULT);
c75976d12071ddd21443266260066ba036671682pawelw } else {
c75976d12071ddd21443266260066ba036671682pawelw if (ioc->bufsiz != type_len)
c75976d12071ddd21443266260066ba036671682pawelw return (EINVAL);
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw if (ddi_copyout((void *)ap_type, ioc->buf,
c75976d12071ddd21443266260066ba036671682pawelw ioc->bufsiz, mode) != 0)
c75976d12071ddd21443266260066ba036671682pawelw return (EFAULT);
c75976d12071ddd21443266260066ba036671682pawelw }
c75976d12071ddd21443266260066ba036671682pawelw return (0);
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw}
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw/*
c75976d12071ddd21443266260066ba036671682pawelw * Process ioctl get device model info request.
c75976d12071ddd21443266260066ba036671682pawelw * This operation should return to cfgadm the device model
c75976d12071ddd21443266260066ba036671682pawelw * information string
c75976d12071ddd21443266260066ba036671682pawelw *
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * NOTE: Port multiplier is supported.
c75976d12071ddd21443266260066ba036671682pawelw */
c75976d12071ddd21443266260066ba036671682pawelwstatic int
c75976d12071ddd21443266260066ba036671682pawelwsata_ioctl_get_model_info(sata_hba_inst_t *sata_hba_inst,
c75976d12071ddd21443266260066ba036671682pawelw sata_device_t *sata_device, sata_ioctl_data_t *ioc, int mode)
c75976d12071ddd21443266260066ba036671682pawelw{
c75976d12071ddd21443266260066ba036671682pawelw sata_drive_info_t *sdinfo;
c75976d12071ddd21443266260066ba036671682pawelw uint32_t info_len;
c75976d12071ddd21443266260066ba036671682pawelw char ap_info[SATA_ID_MODEL_LEN + 1];
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw mutex_enter(&SATA_CPORT_INFO(sata_hba_inst,
c75976d12071ddd21443266260066ba036671682pawelw sata_device->satadev_addr.cport)->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (sata_device->satadev_addr.qual == SATA_ADDR_DCPORT)
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw sdinfo = SATA_CPORT_DRV_INFO(sata_hba_inst,
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw sata_device->satadev_addr.cport);
c75976d12071ddd21443266260066ba036671682pawelw else /* port multiplier */
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw sdinfo = SATA_PMPORT_DRV_INFO(sata_hba_inst,
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw sata_device->satadev_addr.cport,
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw sata_device->satadev_addr.pmport);
c75976d12071ddd21443266260066ba036671682pawelw if (sdinfo == NULL) {
c75976d12071ddd21443266260066ba036671682pawelw mutex_exit(&SATA_CPORT_INFO(sata_hba_inst,
c75976d12071ddd21443266260066ba036671682pawelw sata_device->satadev_addr.cport)->cport_mutex);
c75976d12071ddd21443266260066ba036671682pawelw return (EINVAL);
c75976d12071ddd21443266260066ba036671682pawelw }
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw#ifdef _LITTLE_ENDIAN
c75976d12071ddd21443266260066ba036671682pawelw swab(sdinfo->satadrv_id.ai_model, ap_info, SATA_ID_MODEL_LEN);
c75976d12071ddd21443266260066ba036671682pawelw#else /* _LITTLE_ENDIAN */
c75976d12071ddd21443266260066ba036671682pawelw bcopy(sdinfo->satadrv_id.ai_model, ap_info, SATA_ID_MODEL_LEN);
c75976d12071ddd21443266260066ba036671682pawelw#endif /* _LITTLE_ENDIAN */
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw mutex_exit(&SATA_CPORT_INFO(sata_hba_inst,
c75976d12071ddd21443266260066ba036671682pawelw sata_device->satadev_addr.cport)->cport_mutex);
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw ap_info[SATA_ID_MODEL_LEN] = '\0';
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw info_len = strlen(ap_info) + 1;
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw if (ioc->get_size) {
c75976d12071ddd21443266260066ba036671682pawelw if (ddi_copyout((void *)&info_len, ioc->buf, ioc->bufsiz,
c75976d12071ddd21443266260066ba036671682pawelw mode) != 0)
c75976d12071ddd21443266260066ba036671682pawelw return (EFAULT);
c75976d12071ddd21443266260066ba036671682pawelw } else {
c75976d12071ddd21443266260066ba036671682pawelw if (ioc->bufsiz < info_len)
c75976d12071ddd21443266260066ba036671682pawelw return (EINVAL);
c75976d12071ddd21443266260066ba036671682pawelw if (ddi_copyout((void *)ap_info, ioc->buf, ioc->bufsiz,
c75976d12071ddd21443266260066ba036671682pawelw mode) != 0)
c75976d12071ddd21443266260066ba036671682pawelw return (EFAULT);
c75976d12071ddd21443266260066ba036671682pawelw }
c75976d12071ddd21443266260066ba036671682pawelw return (0);
c75976d12071ddd21443266260066ba036671682pawelw}
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw/*
c75976d12071ddd21443266260066ba036671682pawelw * Process ioctl get device firmware revision info request.
c75976d12071ddd21443266260066ba036671682pawelw * This operation should return to cfgadm the device firmware revision
c75976d12071ddd21443266260066ba036671682pawelw * information string
c75976d12071ddd21443266260066ba036671682pawelw *
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Port multiplier is supported.
c75976d12071ddd21443266260066ba036671682pawelw */
c75976d12071ddd21443266260066ba036671682pawelwstatic int
c75976d12071ddd21443266260066ba036671682pawelwsata_ioctl_get_revfirmware_info(sata_hba_inst_t *sata_hba_inst,
c75976d12071ddd21443266260066ba036671682pawelw sata_device_t *sata_device, sata_ioctl_data_t *ioc, int mode)
c75976d12071ddd21443266260066ba036671682pawelw{
c75976d12071ddd21443266260066ba036671682pawelw sata_drive_info_t *sdinfo;
c75976d12071ddd21443266260066ba036671682pawelw uint32_t info_len;
c75976d12071ddd21443266260066ba036671682pawelw char ap_info[SATA_ID_FW_LEN + 1];
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw mutex_enter(&SATA_CPORT_INFO(sata_hba_inst,
c75976d12071ddd21443266260066ba036671682pawelw sata_device->satadev_addr.cport)->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (sata_device->satadev_addr.qual == SATA_ADDR_DCPORT)
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw sdinfo = SATA_CPORT_DRV_INFO(sata_hba_inst,
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw sata_device->satadev_addr.cport);
c75976d12071ddd21443266260066ba036671682pawelw else /* port multiplier */
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw sdinfo = SATA_PMPORT_DRV_INFO(sata_hba_inst,
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw sata_device->satadev_addr.cport,
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw sata_device->satadev_addr.pmport);
c75976d12071ddd21443266260066ba036671682pawelw if (sdinfo == NULL) {
c75976d12071ddd21443266260066ba036671682pawelw mutex_exit(&SATA_CPORT_INFO(sata_hba_inst,
c75976d12071ddd21443266260066ba036671682pawelw sata_device->satadev_addr.cport)->cport_mutex);
c75976d12071ddd21443266260066ba036671682pawelw return (EINVAL);
c75976d12071ddd21443266260066ba036671682pawelw }
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw#ifdef _LITTLE_ENDIAN
c75976d12071ddd21443266260066ba036671682pawelw swab(sdinfo->satadrv_id.ai_fw, ap_info, SATA_ID_FW_LEN);
c75976d12071ddd21443266260066ba036671682pawelw#else /* _LITTLE_ENDIAN */
c75976d12071ddd21443266260066ba036671682pawelw bcopy(sdinfo->satadrv_id.ai_fw, ap_info, SATA_ID_FW_LEN);
c75976d12071ddd21443266260066ba036671682pawelw#endif /* _LITTLE_ENDIAN */
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw mutex_exit(&SATA_CPORT_INFO(sata_hba_inst,
c75976d12071ddd21443266260066ba036671682pawelw sata_device->satadev_addr.cport)->cport_mutex);
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw ap_info[SATA_ID_FW_LEN] = '\0';
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw info_len = strlen(ap_info) + 1;
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw if (ioc->get_size) {
c75976d12071ddd21443266260066ba036671682pawelw if (ddi_copyout((void *)&info_len, ioc->buf, ioc->bufsiz,
c75976d12071ddd21443266260066ba036671682pawelw mode) != 0)
c75976d12071ddd21443266260066ba036671682pawelw return (EFAULT);
c75976d12071ddd21443266260066ba036671682pawelw } else {
c75976d12071ddd21443266260066ba036671682pawelw if (ioc->bufsiz < info_len)
c75976d12071ddd21443266260066ba036671682pawelw return (EINVAL);
c75976d12071ddd21443266260066ba036671682pawelw if (ddi_copyout((void *)ap_info, ioc->buf, ioc->bufsiz,
c75976d12071ddd21443266260066ba036671682pawelw mode) != 0)
c75976d12071ddd21443266260066ba036671682pawelw return (EFAULT);
c75976d12071ddd21443266260066ba036671682pawelw }
c75976d12071ddd21443266260066ba036671682pawelw return (0);
c75976d12071ddd21443266260066ba036671682pawelw}
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw/*
c75976d12071ddd21443266260066ba036671682pawelw * Process ioctl get device serial number info request.
c75976d12071ddd21443266260066ba036671682pawelw * This operation should return to cfgadm the device serial number string.
c75976d12071ddd21443266260066ba036671682pawelw *
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * NOTE: Port multiplier is supported.
c75976d12071ddd21443266260066ba036671682pawelw */
c75976d12071ddd21443266260066ba036671682pawelwstatic int
c75976d12071ddd21443266260066ba036671682pawelwsata_ioctl_get_serialnumber_info(sata_hba_inst_t *sata_hba_inst,
c75976d12071ddd21443266260066ba036671682pawelw sata_device_t *sata_device, sata_ioctl_data_t *ioc, int mode)
c75976d12071ddd21443266260066ba036671682pawelw{
c75976d12071ddd21443266260066ba036671682pawelw sata_drive_info_t *sdinfo;
c75976d12071ddd21443266260066ba036671682pawelw uint32_t info_len;
c75976d12071ddd21443266260066ba036671682pawelw char ap_info[SATA_ID_SERIAL_LEN + 1];
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw mutex_enter(&SATA_CPORT_INFO(sata_hba_inst,
c75976d12071ddd21443266260066ba036671682pawelw sata_device->satadev_addr.cport)->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (sata_device->satadev_addr.qual == SATA_ADDR_DCPORT)
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw sdinfo = SATA_CPORT_DRV_INFO(sata_hba_inst,
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw sata_device->satadev_addr.cport);
c75976d12071ddd21443266260066ba036671682pawelw else /* port multiplier */
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw sdinfo = SATA_PMPORT_DRV_INFO(sata_hba_inst,
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw sata_device->satadev_addr.cport,
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw sata_device->satadev_addr.pmport);
c75976d12071ddd21443266260066ba036671682pawelw if (sdinfo == NULL) {
c75976d12071ddd21443266260066ba036671682pawelw mutex_exit(&SATA_CPORT_INFO(sata_hba_inst,
c75976d12071ddd21443266260066ba036671682pawelw sata_device->satadev_addr.cport)->cport_mutex);
c75976d12071ddd21443266260066ba036671682pawelw return (EINVAL);
c75976d12071ddd21443266260066ba036671682pawelw }
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw#ifdef _LITTLE_ENDIAN
c75976d12071ddd21443266260066ba036671682pawelw swab(sdinfo->satadrv_id.ai_drvser, ap_info, SATA_ID_SERIAL_LEN);
c75976d12071ddd21443266260066ba036671682pawelw#else /* _LITTLE_ENDIAN */
c75976d12071ddd21443266260066ba036671682pawelw bcopy(sdinfo->satadrv_id.ai_drvser, ap_info, SATA_ID_SERIAL_LEN);
c75976d12071ddd21443266260066ba036671682pawelw#endif /* _LITTLE_ENDIAN */
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw mutex_exit(&SATA_CPORT_INFO(sata_hba_inst,
c75976d12071ddd21443266260066ba036671682pawelw sata_device->satadev_addr.cport)->cport_mutex);
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw ap_info[SATA_ID_SERIAL_LEN] = '\0';
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw info_len = strlen(ap_info) + 1;
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw if (ioc->get_size) {
c75976d12071ddd21443266260066ba036671682pawelw if (ddi_copyout((void *)&info_len, ioc->buf, ioc->bufsiz,
c75976d12071ddd21443266260066ba036671682pawelw mode) != 0)
c75976d12071ddd21443266260066ba036671682pawelw return (EFAULT);
c75976d12071ddd21443266260066ba036671682pawelw } else {
c75976d12071ddd21443266260066ba036671682pawelw if (ioc->bufsiz < info_len)
c75976d12071ddd21443266260066ba036671682pawelw return (EINVAL);
c75976d12071ddd21443266260066ba036671682pawelw if (ddi_copyout((void *)ap_info, ioc->buf, ioc->bufsiz,
c75976d12071ddd21443266260066ba036671682pawelw mode) != 0)
c75976d12071ddd21443266260066ba036671682pawelw return (EFAULT);
c75976d12071ddd21443266260066ba036671682pawelw }
c75976d12071ddd21443266260066ba036671682pawelw return (0);
c75976d12071ddd21443266260066ba036671682pawelw}
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Preset scsi extended sense data (to NO SENSE)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * First 18 bytes of the sense data are preset to current valid sense
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * with a key NO SENSE data.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown *
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Returns void
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void
2038334ab26baaa43c9083f35def041511c3cc1fUnknownsata_fixed_sense_data_preset(struct scsi_extended_sense *sense)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sense->es_valid = 1; /* Valid sense */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sense->es_class = CLASS_EXTENDED_SENSE; /* 0x70 - current err */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sense->es_key = KEY_NO_SENSE;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sense->es_info_1 = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sense->es_info_2 = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sense->es_info_3 = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sense->es_info_4 = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sense->es_add_len = 10; /* Additional length - replace with a def */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sense->es_cmd_info[0] = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sense->es_cmd_info[1] = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sense->es_cmd_info[2] = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sense->es_cmd_info[3] = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sense->es_add_code = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sense->es_qual_code = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
8d483882aa3390058094b043f3d62187b5d1de03mlf/*
8d483882aa3390058094b043f3d62187b5d1de03mlf * Register a legacy cmdk-style devid for the target (disk) device.
8d483882aa3390058094b043f3d62187b5d1de03mlf *
8d483882aa3390058094b043f3d62187b5d1de03mlf * Note: This function is called only when the HBA devinfo node has the
8d483882aa3390058094b043f3d62187b5d1de03mlf * property "use-cmdk-devid-format" set. This property indicates that
8d483882aa3390058094b043f3d62187b5d1de03mlf * devid compatible with old cmdk (target) driver is to be generated
8d483882aa3390058094b043f3d62187b5d1de03mlf * for any target device attached to this controller. This will take
8d483882aa3390058094b043f3d62187b5d1de03mlf * precedence over the devid generated by sd (target) driver.
8d483882aa3390058094b043f3d62187b5d1de03mlf * This function is derived from cmdk_devid_setup() function in cmdk.c.
8d483882aa3390058094b043f3d62187b5d1de03mlf */
8d483882aa3390058094b043f3d62187b5d1de03mlfstatic void
8d483882aa3390058094b043f3d62187b5d1de03mlfsata_target_devid_register(dev_info_t *dip, sata_drive_info_t *sdinfo)
8d483882aa3390058094b043f3d62187b5d1de03mlf{
8d483882aa3390058094b043f3d62187b5d1de03mlf char *hwid;
8d483882aa3390058094b043f3d62187b5d1de03mlf int modlen;
8d483882aa3390058094b043f3d62187b5d1de03mlf int serlen;
8d483882aa3390058094b043f3d62187b5d1de03mlf int rval;
8d483882aa3390058094b043f3d62187b5d1de03mlf ddi_devid_t devid;
8d483882aa3390058094b043f3d62187b5d1de03mlf
8d483882aa3390058094b043f3d62187b5d1de03mlf /*
8d483882aa3390058094b043f3d62187b5d1de03mlf * device ID is a concatanation of model number, "=", serial number.
8d483882aa3390058094b043f3d62187b5d1de03mlf */
8d483882aa3390058094b043f3d62187b5d1de03mlf hwid = kmem_zalloc(LEGACY_HWID_LEN, KM_SLEEP);
8d483882aa3390058094b043f3d62187b5d1de03mlf bcopy(&sdinfo->satadrv_id.ai_model, hwid,
8d483882aa3390058094b043f3d62187b5d1de03mlf sizeof (sdinfo->satadrv_id.ai_model));
8d483882aa3390058094b043f3d62187b5d1de03mlf swab(hwid, hwid, sizeof (sdinfo->satadrv_id.ai_model));
8d483882aa3390058094b043f3d62187b5d1de03mlf modlen = sata_check_modser(hwid, sizeof (sdinfo->satadrv_id.ai_model));
8d483882aa3390058094b043f3d62187b5d1de03mlf if (modlen == 0)
8d483882aa3390058094b043f3d62187b5d1de03mlf goto err;
8d483882aa3390058094b043f3d62187b5d1de03mlf hwid[modlen++] = '=';
8d483882aa3390058094b043f3d62187b5d1de03mlf bcopy(&sdinfo->satadrv_id.ai_drvser, &hwid[modlen],
8d483882aa3390058094b043f3d62187b5d1de03mlf sizeof (sdinfo->satadrv_id.ai_drvser));
8d483882aa3390058094b043f3d62187b5d1de03mlf swab(&hwid[modlen], &hwid[modlen],
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw sizeof (sdinfo->satadrv_id.ai_drvser));
8d483882aa3390058094b043f3d62187b5d1de03mlf serlen = sata_check_modser(&hwid[modlen],
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw sizeof (sdinfo->satadrv_id.ai_drvser));
8d483882aa3390058094b043f3d62187b5d1de03mlf if (serlen == 0)
8d483882aa3390058094b043f3d62187b5d1de03mlf goto err;
8d483882aa3390058094b043f3d62187b5d1de03mlf hwid[modlen + serlen] = 0; /* terminate the hwid string */
8d483882aa3390058094b043f3d62187b5d1de03mlf
8d483882aa3390058094b043f3d62187b5d1de03mlf /* initialize/register devid */
8d483882aa3390058094b043f3d62187b5d1de03mlf if ((rval = ddi_devid_init(dip, DEVID_ATA_SERIAL,
8315c5be243dbb5d2daa15cc2475e22de71d16d9Prasad Singamsetty (ushort_t)(modlen + serlen), hwid, &devid)) == DDI_SUCCESS) {
8d483882aa3390058094b043f3d62187b5d1de03mlf rval = ddi_devid_register(dip, devid);
8315c5be243dbb5d2daa15cc2475e22de71d16d9Prasad Singamsetty /*
8315c5be243dbb5d2daa15cc2475e22de71d16d9Prasad Singamsetty * Free up the allocated devid buffer.
8315c5be243dbb5d2daa15cc2475e22de71d16d9Prasad Singamsetty * NOTE: This doesn't mean unregistering devid.
8315c5be243dbb5d2daa15cc2475e22de71d16d9Prasad Singamsetty */
8315c5be243dbb5d2daa15cc2475e22de71d16d9Prasad Singamsetty ddi_devid_free(devid);
8315c5be243dbb5d2daa15cc2475e22de71d16d9Prasad Singamsetty }
8d483882aa3390058094b043f3d62187b5d1de03mlf
8d483882aa3390058094b043f3d62187b5d1de03mlf if (rval != DDI_SUCCESS)
8d483882aa3390058094b043f3d62187b5d1de03mlf cmn_err(CE_WARN, "sata: failed to create devid for the disk"
6f9b9bf43c10fb1741a40302efe9db1a139745c8pawelw " on port %d", sdinfo->satadrv_addr.cport);
8d483882aa3390058094b043f3d62187b5d1de03mlferr:
8d483882aa3390058094b043f3d62187b5d1de03mlf kmem_free(hwid, LEGACY_HWID_LEN);
8d483882aa3390058094b043f3d62187b5d1de03mlf}
8d483882aa3390058094b043f3d62187b5d1de03mlf
8d483882aa3390058094b043f3d62187b5d1de03mlf/*
8d483882aa3390058094b043f3d62187b5d1de03mlf * valid model/serial string must contain a non-zero non-space characters.
8d483882aa3390058094b043f3d62187b5d1de03mlf * trim trailing spaces/NULLs.
8d483882aa3390058094b043f3d62187b5d1de03mlf */
8d483882aa3390058094b043f3d62187b5d1de03mlfstatic int
8d483882aa3390058094b043f3d62187b5d1de03mlfsata_check_modser(char *buf, int buf_len)
8d483882aa3390058094b043f3d62187b5d1de03mlf{
8d483882aa3390058094b043f3d62187b5d1de03mlf boolean_t ret;
8d483882aa3390058094b043f3d62187b5d1de03mlf char *s;
8d483882aa3390058094b043f3d62187b5d1de03mlf int i;
8d483882aa3390058094b043f3d62187b5d1de03mlf int tb;
8d483882aa3390058094b043f3d62187b5d1de03mlf char ch;
8d483882aa3390058094b043f3d62187b5d1de03mlf
8d483882aa3390058094b043f3d62187b5d1de03mlf ret = B_FALSE;
8d483882aa3390058094b043f3d62187b5d1de03mlf s = buf;
8d483882aa3390058094b043f3d62187b5d1de03mlf for (i = 0; i < buf_len; i++) {
8d483882aa3390058094b043f3d62187b5d1de03mlf ch = *s++;
8d483882aa3390058094b043f3d62187b5d1de03mlf if (ch != ' ' && ch != '\0')
8d483882aa3390058094b043f3d62187b5d1de03mlf tb = i + 1;
8d483882aa3390058094b043f3d62187b5d1de03mlf if (ch != ' ' && ch != '\0' && ch != '0')
8d483882aa3390058094b043f3d62187b5d1de03mlf ret = B_TRUE;
8d483882aa3390058094b043f3d62187b5d1de03mlf }
8d483882aa3390058094b043f3d62187b5d1de03mlf
8d483882aa3390058094b043f3d62187b5d1de03mlf if (ret == B_FALSE)
8d483882aa3390058094b043f3d62187b5d1de03mlf return (0); /* invalid string */
8d483882aa3390058094b043f3d62187b5d1de03mlf
8d483882aa3390058094b043f3d62187b5d1de03mlf return (tb); /* return length */
8d483882aa3390058094b043f3d62187b5d1de03mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown/*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * sata_set_drive_features function compares current device features setting
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * with the saved device features settings and, if there is a difference,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * it restores device features setting to the previously saved state.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * It also arbitrarily tries to select the highest supported DMA mode.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Device Identify or Identify Packet Device data has to be current.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * At the moment read ahead and write cache are considered for all devices.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * For atapi devices, Removable Media Status Notification is set in addition
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * to common features.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown *
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * This function cannot be called in the interrupt context (it may sleep).
2038334ab26baaa43c9083f35def041511c3cc1fUnknown *
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * The input argument sdinfo should point to the drive info structure
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * to be updated after features are set. Note, that only
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * device (packet) identify data is updated, not the flags indicating the
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * supported features.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown *
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik * Returns SATA_SUCCESS if successful or there was nothing to do.
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik * Device Identify data in the drive info structure pointed to by the sdinfo
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik * arguments is updated even when no features were set or changed.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown *
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik * Returns SATA_FAILURE if device features could not be set or DMA mode
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik * for a disk cannot be set and device identify data cannot be fetched.
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik *
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik * Returns SATA_RETRY if device features could not be set (other than disk
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik * DMA mode) but the device identify data was fetched successfully.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown *
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Note: This function may fail the port, making it inaccessible.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * In such case the explicit port disconnect/connect or physical device
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * detach/attach is required to re-evaluate port state again.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic int
2038334ab26baaa43c9083f35def041511c3cc1fUnknownsata_set_drive_features(sata_hba_inst_t *sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_drive_info_t *sdinfo, int restore)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown{
2038334ab26baaa43c9083f35def041511c3cc1fUnknown int rval = SATA_SUCCESS;
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik int rval_set;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_drive_info_t new_sdinfo;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown char *finfo = "sata_set_drive_features: cannot";
2038334ab26baaa43c9083f35def041511c3cc1fUnknown char *finfox;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown int cache_op;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown bzero(&new_sdinfo, sizeof (sata_drive_info_t));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown new_sdinfo.satadrv_addr = sdinfo->satadrv_addr;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown new_sdinfo.satadrv_type = sdinfo->satadrv_type;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sata_fetch_device_identify_data(sata_hba_inst, &new_sdinfo) != 0) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik * Cannot get device identification - caller may retry later
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw SATADBG1(SATA_DBG_DEV_SETTINGS, sata_hba_inst,
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw "%s fetch device identify data\n", finfo);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (SATA_FAILURE);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown finfox = (restore != 0) ? " restore device features" :
2038334ab26baaa43c9083f35def041511c3cc1fUnknown " initialize device features\n";
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China switch (sdinfo->satadrv_type) {
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China case SATA_DTYPE_ATADISK:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Arbitrarily set UDMA mode */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sata_set_dma_mode(sata_hba_inst, &new_sdinfo) !=
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_SUCCESS) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_LOG_D((sata_hba_inst, CE_WARN,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "%s set UDMA mode\n", finfo));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (SATA_FAILURE);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China break;
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China case SATA_DTYPE_ATAPICD:
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China case SATA_DTYPE_ATAPITAPE:
f8a673ad9145b262edb65a98fb3fb92027d23a05ying tian - Beijing China case SATA_DTYPE_ATAPIDISK:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Set Removable Media Status Notification, if necessary */
7095af1983f107c8b16839f70101fdf710c4e620ying tian - Beijing China if (SATA_RM_NOTIFIC_SUPPORTED(new_sdinfo.satadrv_id) &&
7095af1983f107c8b16839f70101fdf710c4e620ying tian - Beijing China restore != 0) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (((sdinfo->satadrv_settings & SATA_DEV_RMSN) &&
7095af1983f107c8b16839f70101fdf710c4e620ying tian - Beijing China (!SATA_RM_NOTIFIC_ENABLED(new_sdinfo.satadrv_id)))||
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ((!(sdinfo->satadrv_settings & SATA_DEV_RMSN)) &&
7095af1983f107c8b16839f70101fdf710c4e620ying tian - Beijing China SATA_RM_NOTIFIC_ENABLED(new_sdinfo.satadrv_id))) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Current setting does not match saved one */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sata_set_rmsn(sata_hba_inst, sdinfo,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_settings &
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_DEV_RMSN) != SATA_SUCCESS)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rval = SATA_FAILURE;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * We have to set Multiword DMA or UDMA, if it is supported, as
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * we want to use DMA transfer mode whenever possible.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Some devices require explicit setting of the DMA mode.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (new_sdinfo.satadrv_id.ai_cap & SATA_DMA_SUPPORT) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Set highest supported DMA mode */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sata_set_dma_mode(sata_hba_inst, &new_sdinfo) !=
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_SUCCESS) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_LOG_D((sata_hba_inst, CE_WARN,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "%s set UDMA mode\n", finfo));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rval = SATA_FAILURE;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
7095af1983f107c8b16839f70101fdf710c4e620ying tian - Beijing China if (!SATA_READ_AHEAD_SUPPORTED(new_sdinfo.satadrv_id) &&
7095af1983f107c8b16839f70101fdf710c4e620ying tian - Beijing China !SATA_WRITE_CACHE_SUPPORTED(new_sdinfo.satadrv_id)) {
7095af1983f107c8b16839f70101fdf710c4e620ying tian - Beijing China /*
7095af1983f107c8b16839f70101fdf710c4e620ying tian - Beijing China * neither READ AHEAD nor WRITE CACHE is supported
7095af1983f107c8b16839f70101fdf710c4e620ying tian - Beijing China * - do nothing
7095af1983f107c8b16839f70101fdf710c4e620ying tian - Beijing China */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATADBG1(SATA_DBG_DEV_SETTINGS, sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "settable features not supported\n", NULL);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown goto update_sdinfo;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
7095af1983f107c8b16839f70101fdf710c4e620ying tian - Beijing China if ((SATA_READ_AHEAD_ENABLED(new_sdinfo.satadrv_id) &&
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (sdinfo->satadrv_settings & SATA_DEV_READ_AHEAD)) &&
7095af1983f107c8b16839f70101fdf710c4e620ying tian - Beijing China (SATA_WRITE_CACHE_ENABLED(new_sdinfo.satadrv_id) &&
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (sdinfo->satadrv_settings & SATA_DEV_WRITE_CACHE))) {
7095af1983f107c8b16839f70101fdf710c4e620ying tian - Beijing China /*
7095af1983f107c8b16839f70101fdf710c4e620ying tian - Beijing China * both READ AHEAD and WRITE CACHE are enabled
7095af1983f107c8b16839f70101fdf710c4e620ying tian - Beijing China * - Nothing to do
7095af1983f107c8b16839f70101fdf710c4e620ying tian - Beijing China */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATADBG1(SATA_DBG_DEV_SETTINGS, sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "no device features to set\n", NULL);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown goto update_sdinfo;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
7095af1983f107c8b16839f70101fdf710c4e620ying tian - Beijing China cache_op = 0;
7095af1983f107c8b16839f70101fdf710c4e620ying tian - Beijing China
7095af1983f107c8b16839f70101fdf710c4e620ying tian - Beijing China if (SATA_READ_AHEAD_SUPPORTED(new_sdinfo.satadrv_id)) {
7095af1983f107c8b16839f70101fdf710c4e620ying tian - Beijing China if ((sdinfo->satadrv_settings & SATA_DEV_READ_AHEAD) &&
7095af1983f107c8b16839f70101fdf710c4e620ying tian - Beijing China !SATA_READ_AHEAD_ENABLED(new_sdinfo.satadrv_id)) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Enable read ahead / read cache */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cache_op = SATAC_SF_ENABLE_READ_AHEAD;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATADBG1(SATA_DBG_DEV_SETTINGS, sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "enabling read cache\n", NULL);
7095af1983f107c8b16839f70101fdf710c4e620ying tian - Beijing China } else if (!(sdinfo->satadrv_settings & SATA_DEV_READ_AHEAD) &&
7095af1983f107c8b16839f70101fdf710c4e620ying tian - Beijing China SATA_READ_AHEAD_ENABLED(new_sdinfo.satadrv_id)) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Disable read ahead / read cache */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cache_op = SATAC_SF_DISABLE_READ_AHEAD;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATADBG1(SATA_DBG_DEV_SETTINGS, sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "disabling read cache\n", NULL);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
7095af1983f107c8b16839f70101fdf710c4e620ying tian - Beijing China if (cache_op != 0) {
7095af1983f107c8b16839f70101fdf710c4e620ying tian - Beijing China /* Try to set read cache mode */
7095af1983f107c8b16839f70101fdf710c4e620ying tian - Beijing China rval_set = sata_set_cache_mode(sata_hba_inst,
7095af1983f107c8b16839f70101fdf710c4e620ying tian - Beijing China &new_sdinfo, cache_op);
7095af1983f107c8b16839f70101fdf710c4e620ying tian - Beijing China if (rval != SATA_FAILURE && rval_set != SATA_SUCCESS)
7095af1983f107c8b16839f70101fdf710c4e620ying tian - Beijing China rval = rval_set;
7095af1983f107c8b16839f70101fdf710c4e620ying tian - Beijing China }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
7095af1983f107c8b16839f70101fdf710c4e620ying tian - Beijing China cache_op = 0;
7095af1983f107c8b16839f70101fdf710c4e620ying tian - Beijing China
7095af1983f107c8b16839f70101fdf710c4e620ying tian - Beijing China if (SATA_WRITE_CACHE_SUPPORTED(new_sdinfo.satadrv_id)) {
7095af1983f107c8b16839f70101fdf710c4e620ying tian - Beijing China if ((sdinfo->satadrv_settings & SATA_DEV_WRITE_CACHE) &&
7095af1983f107c8b16839f70101fdf710c4e620ying tian - Beijing China !SATA_WRITE_CACHE_ENABLED(new_sdinfo.satadrv_id)) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Enable write cache */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cache_op = SATAC_SF_ENABLE_WRITE_CACHE;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATADBG1(SATA_DBG_DEV_SETTINGS, sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "enabling write cache\n", NULL);
7095af1983f107c8b16839f70101fdf710c4e620ying tian - Beijing China } else if (!(sdinfo->satadrv_settings & SATA_DEV_WRITE_CACHE) &&
7095af1983f107c8b16839f70101fdf710c4e620ying tian - Beijing China SATA_WRITE_CACHE_ENABLED(new_sdinfo.satadrv_id)) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Disable write cache */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cache_op = SATAC_SF_DISABLE_WRITE_CACHE;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATADBG1(SATA_DBG_DEV_SETTINGS, sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "disabling write cache\n", NULL);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
7095af1983f107c8b16839f70101fdf710c4e620ying tian - Beijing China
7095af1983f107c8b16839f70101fdf710c4e620ying tian - Beijing China if (cache_op != 0) {
7095af1983f107c8b16839f70101fdf710c4e620ying tian - Beijing China /* Try to set write cache mode */
7095af1983f107c8b16839f70101fdf710c4e620ying tian - Beijing China rval_set = sata_set_cache_mode(sata_hba_inst,
7095af1983f107c8b16839f70101fdf710c4e620ying tian - Beijing China &new_sdinfo, cache_op);
7095af1983f107c8b16839f70101fdf710c4e620ying tian - Beijing China if (rval != SATA_FAILURE && rval_set != SATA_SUCCESS)
7095af1983f107c8b16839f70101fdf710c4e620ying tian - Beijing China rval = rval_set;
7095af1983f107c8b16839f70101fdf710c4e620ying tian - Beijing China }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik if (rval != SATA_SUCCESS)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_LOG_D((sata_hba_inst, CE_WARN,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "%s %s", finfo, finfox));
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik
2038334ab26baaa43c9083f35def041511c3cc1fUnknownupdate_sdinfo:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * We need to fetch Device Identify data again
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sata_fetch_device_identify_data(sata_hba_inst, &new_sdinfo) != 0) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Cannot get device identification - retry later
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_LOG_D((sata_hba_inst, CE_WARN,
ae8faf9c0cd738ab78a672de5bf7e7f7d004ebb2ls "%s re-fetch device identify data\n", finfo));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rval = SATA_FAILURE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Copy device sata info. */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_id = new_sdinfo.satadrv_id;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (rval);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Returns 1 if threshold exceeded, 0 if threshold not exceeded, -1 if
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * unable to determine.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Cannot be called in an interrupt context.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Called by sata_build_lsense_page_2f()
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic int
2038334ab26baaa43c9083f35def041511c3cc1fUnknownsata_fetch_smart_return_status(sata_hba_inst_t *sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_drive_info_t *sdinfo)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_pkt_t *spkt;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_cmd_t *scmd;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_pkt_txlate_t *spx;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int rval;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx = kmem_zalloc(sizeof (sata_pkt_txlate_t), KM_SLEEP);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_sata_hba_inst = sata_hba_inst;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_scsi_pkt = NULL; /* No scsi pkt involved */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt = sata_pkt_alloc(spx, SLEEP_FUNC);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (spkt == NULL) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown kmem_free(spx, sizeof (sata_pkt_txlate_t));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (-1);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* address is needed now */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_device.satadev_addr = sdinfo->satadrv_addr;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Fill sata_pkt */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_device.satadev_addr = sdinfo->satadrv_addr;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_op_mode = SATA_OPMODE_SYNCH | SATA_OPMODE_INTERRUPTS;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Synchronous mode, no callback */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_comp = NULL;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Timeout 30s */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_time = sata_default_pkt_time;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd = &spkt->satapkt_cmd;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_flags.sata_special_regs = B_TRUE;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_flags.sata_data_direction = SATA_DIR_NODATA_XFER;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Set up which registers need to be returned */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_flags.sata_copy_out_lba_mid_lsb = B_TRUE;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_flags.sata_copy_out_lba_high_lsb = B_TRUE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Build SMART_RETURN_STATUS cmd in the sata_pkt */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_addr_type = 0; /* N/A */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_sec_count_lsb = 0; /* N/A */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_lba_low_lsb = 0; /* N/A */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_lba_mid_lsb = SMART_MAGIC_VAL_1;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_lba_high_lsb = SMART_MAGIC_VAL_2;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_features_reg = SATA_SMART_RETURN_STATUS;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_device_reg = 0; /* Always device 0 */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_cmd_reg = SATAC_SMART;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_addr.cport)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Send pkt to SATA HBA driver */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if ((*SATA_START_FUNC(sata_hba_inst))(SATA_DIP(sata_hba_inst), spkt) !=
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_TRAN_ACCEPTED ||
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_reason != SATA_PKT_COMPLETED) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_enter(&(SATA_CPORT_MUTEX(sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_addr.cport)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Whoops, no SMART RETURN STATUS
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rval = -1;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown } else {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_enter(&(SATA_CPORT_MUTEX(sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_addr.cport)));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (scmd->satacmd_error_reg & SATA_ERROR_ABORT) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rval = -1;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown goto fail;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (scmd->satacmd_status_reg & SATA_STATUS_ERR) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rval = -1;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown goto fail;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if ((scmd->satacmd_lba_mid_lsb == SMART_MAGIC_VAL_1) &&
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (scmd->satacmd_lba_high_lsb == SMART_MAGIC_VAL_2))
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rval = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown else if ((scmd->satacmd_lba_mid_lsb == SMART_MAGIC_VAL_3) &&
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (scmd->satacmd_lba_high_lsb == SMART_MAGIC_VAL_4))
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rval = 1;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown else {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rval = -1;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown goto fail;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
2038334ab26baaa43c9083f35def041511c3cc1fUnknownfail:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Free allocated resources */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_pkt_free(spx);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown kmem_free(spx, sizeof (sata_pkt_txlate_t));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (rval);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Returns 0 if succeeded, -1 otherwise
2038334ab26baaa43c9083f35def041511c3cc1fUnknown *
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Cannot be called in an interrupt context.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic int
2038334ab26baaa43c9083f35def041511c3cc1fUnknownsata_fetch_smart_data(
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_hba_inst_t *sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_drive_info_t *sdinfo,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown struct smart_data *smart_data)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_pkt_t *spkt;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_cmd_t *scmd;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_pkt_txlate_t *spx;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int rval;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown#if ! defined(lint)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ASSERT(sizeof (struct smart_data) == 512);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown#endif
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx = kmem_zalloc(sizeof (sata_pkt_txlate_t), KM_SLEEP);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_sata_hba_inst = sata_hba_inst;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_scsi_pkt = NULL; /* No scsi pkt involved */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt = sata_pkt_alloc(spx, SLEEP_FUNC);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (spkt == NULL) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown kmem_free(spx, sizeof (sata_pkt_txlate_t));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (-1);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* address is needed now */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_device.satadev_addr = sdinfo->satadrv_addr;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Fill sata_pkt */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_device.satadev_addr = sdinfo->satadrv_addr;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_op_mode = SATA_OPMODE_SYNCH | SATA_OPMODE_INTERRUPTS;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Synchronous mode, no callback */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_comp = NULL;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Timeout 30s */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_time = sata_default_pkt_time;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd = &spkt->satapkt_cmd;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_flags.sata_data_direction = SATA_DIR_READ;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Allocate buffer for SMART data
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_bp = sata_alloc_local_buffer(spx,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sizeof (struct smart_data));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (scmd->satacmd_bp == NULL) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_pkt_free(spx);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown kmem_free(spx, sizeof (sata_pkt_txlate_t));
4360436b3c604bc28d37be269ad152b4c38157c3pawelw SATA_LOG_D((sata_hba_inst, CE_WARN,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "sata_fetch_smart_data: "
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "cannot allocate buffer"));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (-1);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Build SMART_READ_DATA cmd in the sata_pkt */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_addr_type = 0; /* N/A */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_sec_count_lsb = 0; /* N/A */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_lba_low_lsb = 0; /* N/A */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_lba_mid_lsb = SMART_MAGIC_VAL_1;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_lba_high_lsb = SMART_MAGIC_VAL_2;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_features_reg = SATA_SMART_READ_DATA;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_device_reg = 0; /* Always device 0 */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_cmd_reg = SATAC_SMART;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_addr.cport)));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Send pkt to SATA HBA driver */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if ((*SATA_START_FUNC(sata_hba_inst))(SATA_DIP(sata_hba_inst), spkt) !=
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_TRAN_ACCEPTED ||
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_reason != SATA_PKT_COMPLETED) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_enter(&(SATA_CPORT_MUTEX(sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_addr.cport)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Whoops, no SMART DATA available
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rval = -1;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown goto fail;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown } else {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_enter(&(SATA_CPORT_MUTEX(sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_addr.cport)));
b5fc475bca6525d8da80728128eefb7100aaf66bap if (spx->txlt_buf_dma_handle != NULL) {
b5fc475bca6525d8da80728128eefb7100aaf66bap rval = ddi_dma_sync(spx->txlt_buf_dma_handle, 0, 0,
b5fc475bca6525d8da80728128eefb7100aaf66bap DDI_DMA_SYNC_FORKERNEL);
b5fc475bca6525d8da80728128eefb7100aaf66bap ASSERT(rval == DDI_SUCCESS);
b5fc475bca6525d8da80728128eefb7100aaf66bap }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown bcopy(scmd->satacmd_bp->b_un.b_addr, (uint8_t *)smart_data,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sizeof (struct smart_data));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknownfail:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Free allocated resources */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_free_local_buffer(spx);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_pkt_free(spx);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown kmem_free(spx, sizeof (sata_pkt_txlate_t));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (rval);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Used by LOG SENSE page 0x10
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik * Reads (in synchronous mode) the self test log data using Read Log Ext cmd.
3852f6739b148db36d43cd6e758a0855fd49f24cPawel Wojcik * Note: cannot be called in the interrupt context.
6ed1276fb5fe78fb1cce38682748a830ef8bd157pawelw *
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * return 0 for success, -1 otherwise
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic int
2038334ab26baaa43c9083f35def041511c3cc1fUnknownsata_ext_smart_selftest_read_log(
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_hba_inst_t *sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_drive_info_t *sdinfo,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown struct smart_ext_selftest_log *ext_selftest_log,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown uint16_t block_num)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_pkt_txlate_t *spx;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_pkt_t *spkt;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_cmd_t *scmd;
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw int rval;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown#if ! defined(lint)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ASSERT(sizeof (struct smart_ext_selftest_log) == 512);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown#endif
4360436b3c604bc28d37be269ad152b4c38157c3pawelw
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx = kmem_zalloc(sizeof (sata_pkt_txlate_t), KM_SLEEP);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_sata_hba_inst = sata_hba_inst;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_scsi_pkt = NULL; /* No scsi pkt involved */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt = sata_pkt_alloc(spx, SLEEP_FUNC);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (spkt == NULL) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown kmem_free(spx, sizeof (sata_pkt_txlate_t));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (-1);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* address is needed now */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_device.satadev_addr = sdinfo->satadrv_addr;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Fill sata_pkt */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_device.satadev_addr = sdinfo->satadrv_addr;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_op_mode = SATA_OPMODE_SYNCH | SATA_OPMODE_INTERRUPTS;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Synchronous mode, no callback */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_comp = NULL;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Timeout 30s */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_time = sata_default_pkt_time;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd = &spkt->satapkt_cmd;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_flags.sata_data_direction = SATA_DIR_READ;
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Allocate buffer for SMART extended self-test log
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_bp = sata_alloc_local_buffer(spx,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sizeof (struct smart_ext_selftest_log));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (scmd->satacmd_bp == NULL) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_pkt_free(spx);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown kmem_free(spx, sizeof (sata_pkt_txlate_t));
4360436b3c604bc28d37be269ad152b4c38157c3pawelw SATA_LOG_D((sata_hba_inst, CE_WARN,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "sata_ext_smart_selftest_log: "
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "cannot allocate buffer"));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (-1);
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw }
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Build READ LOG EXT w/ extended self-test log cmd in the sata_pkt */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_addr_type = ATA_ADDR_LBA48;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_sec_count_lsb = 1; /* One sector of selftest log */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_sec_count_msb = 0; /* One sector of selftest log */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_lba_low_lsb = EXT_SMART_SELFTEST_LOG_PAGE;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_lba_low_msb = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_lba_mid_lsb = block_num & 0xff;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_lba_mid_msb = block_num >> 8;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_device_reg = 0; /* Always device 0 */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_cmd_reg = SATAC_READ_LOG_EXT;
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_addr.cport)));
6ed1276fb5fe78fb1cce38682748a830ef8bd157pawelw
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Send pkt to SATA HBA driver */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if ((*SATA_START_FUNC(sata_hba_inst))(SATA_DIP(sata_hba_inst), spkt) !=
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_TRAN_ACCEPTED ||
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_reason != SATA_PKT_COMPLETED) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_enter(&(SATA_CPORT_MUTEX(sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_addr.cport)));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Whoops, no SMART selftest log info available
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rval = -1;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown goto fail;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown } else {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_enter(&(SATA_CPORT_MUTEX(sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_addr.cport)));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
b5fc475bca6525d8da80728128eefb7100aaf66bap if (spx->txlt_buf_dma_handle != NULL) {
b5fc475bca6525d8da80728128eefb7100aaf66bap rval = ddi_dma_sync(spx->txlt_buf_dma_handle, 0, 0,
b5fc475bca6525d8da80728128eefb7100aaf66bap DDI_DMA_SYNC_FORKERNEL);
b5fc475bca6525d8da80728128eefb7100aaf66bap ASSERT(rval == DDI_SUCCESS);
b5fc475bca6525d8da80728128eefb7100aaf66bap }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown bcopy(scmd->satacmd_bp->b_un.b_addr,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (uint8_t *)ext_selftest_log,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sizeof (struct smart_ext_selftest_log));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rval = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknownfail:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Free allocated resources */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_free_local_buffer(spx);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_pkt_free(spx);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown kmem_free(spx, sizeof (sata_pkt_txlate_t));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (rval);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown}
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown/*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Returns 0 for success, -1 otherwise
2038334ab26baaa43c9083f35def041511c3cc1fUnknown *
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * SMART self-test log data is returned in buffer pointed to by selftest_log
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic int
2038334ab26baaa43c9083f35def041511c3cc1fUnknownsata_smart_selftest_log(
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_hba_inst_t *sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_drive_info_t *sdinfo,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown struct smart_selftest_log *selftest_log)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown{
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_pkt_t *spkt;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_cmd_t *scmd;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_pkt_txlate_t *spx;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown int rval;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown#if ! defined(lint)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ASSERT(sizeof (struct smart_selftest_log) == 512);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown#endif
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx = kmem_zalloc(sizeof (sata_pkt_txlate_t), KM_SLEEP);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_sata_hba_inst = sata_hba_inst;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_scsi_pkt = NULL; /* No scsi pkt involved */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt = sata_pkt_alloc(spx, SLEEP_FUNC);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (spkt == NULL) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown kmem_free(spx, sizeof (sata_pkt_txlate_t));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (-1);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* address is needed now */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_device.satadev_addr = sdinfo->satadrv_addr;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Fill sata_pkt */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_device.satadev_addr = sdinfo->satadrv_addr;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_op_mode = SATA_OPMODE_SYNCH | SATA_OPMODE_INTERRUPTS;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Synchronous mode, no callback */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_comp = NULL;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Timeout 30s */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_time = sata_default_pkt_time;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd = &spkt->satapkt_cmd;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_flags.sata_data_direction = SATA_DIR_READ;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Allocate buffer for SMART SELFTEST LOG
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_bp = sata_alloc_local_buffer(spx,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sizeof (struct smart_selftest_log));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (scmd->satacmd_bp == NULL) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_pkt_free(spx);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown kmem_free(spx, sizeof (sata_pkt_txlate_t));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_LOG_D((sata_hba_inst, CE_WARN,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "sata_smart_selftest_log: "
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "cannot allocate buffer"));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (-1);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Build SMART_READ_LOG cmd in the sata_pkt */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_addr_type = 0; /* N/A */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_sec_count_lsb = 1; /* One sector of SMART log */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_lba_low_lsb = SMART_SELFTEST_LOG_PAGE;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_lba_mid_lsb = SMART_MAGIC_VAL_1;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_lba_high_lsb = SMART_MAGIC_VAL_2;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_features_reg = SATA_SMART_READ_LOG;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_device_reg = 0; /* Always device 0 */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_cmd_reg = SATAC_SMART;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_addr.cport)));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Send pkt to SATA HBA driver */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if ((*SATA_START_FUNC(sata_hba_inst))(SATA_DIP(sata_hba_inst), spkt) !=
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_TRAN_ACCEPTED ||
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_reason != SATA_PKT_COMPLETED) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_enter(&(SATA_CPORT_MUTEX(sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_addr.cport)));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Whoops, no SMART DATA available
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rval = -1;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown goto fail;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown } else {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_enter(&(SATA_CPORT_MUTEX(sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_addr.cport)));
b5fc475bca6525d8da80728128eefb7100aaf66bap if (spx->txlt_buf_dma_handle != NULL) {
b5fc475bca6525d8da80728128eefb7100aaf66bap rval = ddi_dma_sync(spx->txlt_buf_dma_handle, 0, 0,
b5fc475bca6525d8da80728128eefb7100aaf66bap DDI_DMA_SYNC_FORKERNEL);
b5fc475bca6525d8da80728128eefb7100aaf66bap ASSERT(rval == DDI_SUCCESS);
b5fc475bca6525d8da80728128eefb7100aaf66bap }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown bcopy(scmd->satacmd_bp->b_un.b_addr, (uint8_t *)selftest_log,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sizeof (struct smart_selftest_log));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rval = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknownfail:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Free allocated resources */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_free_local_buffer(spx);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_pkt_free(spx);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown kmem_free(spx, sizeof (sata_pkt_txlate_t));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (rval);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown}
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown/*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Returns 0 for success, -1 otherwise
2038334ab26baaa43c9083f35def041511c3cc1fUnknown *
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * SMART READ LOG data is returned in buffer pointed to by smart_log
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic int
2038334ab26baaa43c9083f35def041511c3cc1fUnknownsata_smart_read_log(
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_hba_inst_t *sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_drive_info_t *sdinfo,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown uint8_t *smart_log, /* where the data should be returned */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown uint8_t which_log, /* which log should be returned */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown uint8_t log_size) /* # of 512 bytes in log */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown{
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_pkt_t *spkt;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_cmd_t *scmd;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_pkt_txlate_t *spx;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown int rval;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx = kmem_zalloc(sizeof (sata_pkt_txlate_t), KM_SLEEP);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_sata_hba_inst = sata_hba_inst;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_scsi_pkt = NULL; /* No scsi pkt involved */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt = sata_pkt_alloc(spx, SLEEP_FUNC);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (spkt == NULL) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown kmem_free(spx, sizeof (sata_pkt_txlate_t));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (-1);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* address is needed now */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_device.satadev_addr = sdinfo->satadrv_addr;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Fill sata_pkt */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_device.satadev_addr = sdinfo->satadrv_addr;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_op_mode = SATA_OPMODE_SYNCH | SATA_OPMODE_INTERRUPTS;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Synchronous mode, no callback */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_comp = NULL;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Timeout 30s */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_time = sata_default_pkt_time;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd = &spkt->satapkt_cmd;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_flags.sata_data_direction = SATA_DIR_READ;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Allocate buffer for SMART READ LOG
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_bp = sata_alloc_local_buffer(spx, log_size * 512);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (scmd->satacmd_bp == NULL) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_pkt_free(spx);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown kmem_free(spx, sizeof (sata_pkt_txlate_t));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_LOG_D((sata_hba_inst, CE_WARN,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "sata_smart_read_log: " "cannot allocate buffer"));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (-1);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Build SMART_READ_LOG cmd in the sata_pkt */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_addr_type = 0; /* N/A */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_sec_count_lsb = log_size; /* what the caller asked for */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_lba_low_lsb = which_log; /* which log page */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_lba_mid_lsb = SMART_MAGIC_VAL_1;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_lba_high_lsb = SMART_MAGIC_VAL_2;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_features_reg = SATA_SMART_READ_LOG;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_device_reg = 0; /* Always device 0 */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_cmd_reg = SATAC_SMART;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_addr.cport)));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Send pkt to SATA HBA driver */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if ((*SATA_START_FUNC(sata_hba_inst))(SATA_DIP(sata_hba_inst), spkt) !=
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_TRAN_ACCEPTED ||
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_reason != SATA_PKT_COMPLETED) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_enter(&(SATA_CPORT_MUTEX(sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_addr.cport)));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Whoops, no SMART DATA available
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rval = -1;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown goto fail;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown } else {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_enter(&(SATA_CPORT_MUTEX(sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_addr.cport)));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
b5fc475bca6525d8da80728128eefb7100aaf66bap if (spx->txlt_buf_dma_handle != NULL) {
b5fc475bca6525d8da80728128eefb7100aaf66bap rval = ddi_dma_sync(spx->txlt_buf_dma_handle, 0, 0,
b5fc475bca6525d8da80728128eefb7100aaf66bap DDI_DMA_SYNC_FORKERNEL);
b5fc475bca6525d8da80728128eefb7100aaf66bap ASSERT(rval == DDI_SUCCESS);
b5fc475bca6525d8da80728128eefb7100aaf66bap }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown bcopy(scmd->satacmd_bp->b_un.b_addr, smart_log, log_size * 512);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rval = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknownfail:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Free allocated resources */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_free_local_buffer(spx);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_pkt_free(spx);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown kmem_free(spx, sizeof (sata_pkt_txlate_t));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (rval);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown}
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown/*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Used by LOG SENSE page 0x10
2038334ab26baaa43c9083f35def041511c3cc1fUnknown *
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * return 0 for success, -1 otherwise
2038334ab26baaa43c9083f35def041511c3cc1fUnknown *
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic int
2038334ab26baaa43c9083f35def041511c3cc1fUnknownsata_read_log_ext_directory(
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_hba_inst_t *sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_drive_info_t *sdinfo,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown struct read_log_ext_directory *logdir)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown{
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_pkt_txlate_t *spx;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_pkt_t *spkt;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_cmd_t *scmd;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown int rval;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown#if ! defined(lint)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ASSERT(sizeof (struct read_log_ext_directory) == 512);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown#endif
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx = kmem_zalloc(sizeof (sata_pkt_txlate_t), KM_SLEEP);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_sata_hba_inst = sata_hba_inst;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spx->txlt_scsi_pkt = NULL; /* No scsi pkt involved */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt = sata_pkt_alloc(spx, SLEEP_FUNC);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (spkt == NULL) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown kmem_free(spx, sizeof (sata_pkt_txlate_t));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (-1);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Fill sata_pkt */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_device.satadev_addr = sdinfo->satadrv_addr;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_op_mode = SATA_OPMODE_SYNCH | SATA_OPMODE_INTERRUPTS;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Synchronous mode, no callback */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_comp = NULL;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Timeout 30s */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_time = sata_default_pkt_time;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd = &spkt->satapkt_cmd;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_flags.sata_data_direction = SATA_DIR_READ;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Allocate buffer for SMART READ LOG EXTENDED command
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_bp = sata_alloc_local_buffer(spx,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sizeof (struct read_log_ext_directory));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (scmd->satacmd_bp == NULL) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_pkt_free(spx);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown kmem_free(spx, sizeof (sata_pkt_txlate_t));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_LOG_D((sata_hba_inst, CE_WARN,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "sata_read_log_ext_directory: "
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "cannot allocate buffer"));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (-1);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Build READ LOG EXT w/ log directory cmd in the sata_pkt */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_addr_type = ATA_ADDR_LBA48;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_sec_count_lsb = 1; /* One sector of directory */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_sec_count_msb = 0; /* One sector of directory */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_lba_low_lsb = READ_LOG_EXT_LOG_DIRECTORY;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_lba_low_msb = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_lba_mid_lsb = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_lba_mid_msb = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_device_reg = 0; /* Always device 0 */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scmd->satacmd_cmd_reg = SATAC_READ_LOG_EXT;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_addr.cport)));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Send pkt to SATA HBA driver */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if ((*SATA_START_FUNC(sata_hba_inst))(SATA_DIP(sata_hba_inst), spkt) !=
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_TRAN_ACCEPTED ||
2038334ab26baaa43c9083f35def041511c3cc1fUnknown spkt->satapkt_reason != SATA_PKT_COMPLETED) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_enter(&(SATA_CPORT_MUTEX(sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_addr.cport)));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Whoops, no SMART selftest log info available
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rval = -1;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown goto fail;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown } else {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_enter(&(SATA_CPORT_MUTEX(sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_addr.cport)));
b5fc475bca6525d8da80728128eefb7100aaf66bap if (spx->txlt_buf_dma_handle != NULL) {
b5fc475bca6525d8da80728128eefb7100aaf66bap rval = ddi_dma_sync(spx->txlt_buf_dma_handle, 0, 0,
b5fc475bca6525d8da80728128eefb7100aaf66bap DDI_DMA_SYNC_FORKERNEL);
b5fc475bca6525d8da80728128eefb7100aaf66bap ASSERT(rval == DDI_SUCCESS);
b5fc475bca6525d8da80728128eefb7100aaf66bap }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown bcopy(scmd->satacmd_bp->b_un.b_addr, (uint8_t *)logdir,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sizeof (struct read_log_ext_directory));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rval = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknownfail:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Free allocated resources */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_free_local_buffer(spx);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_pkt_free(spx);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown kmem_free(spx, sizeof (sata_pkt_txlate_t));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return (rval);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown}
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
82263d52a84b4a969aa53f8ededddff841646ad9yt/*
82263d52a84b4a969aa53f8ededddff841646ad9yt * Set up error retrieval sata command for NCQ command error data
82263d52a84b4a969aa53f8ededddff841646ad9yt * recovery.
82263d52a84b4a969aa53f8ededddff841646ad9yt *
82263d52a84b4a969aa53f8ededddff841646ad9yt * Returns SATA_SUCCESS when data buffer is allocated and packet set-up,
82263d52a84b4a969aa53f8ededddff841646ad9yt * returns SATA_FAILURE otherwise.
82263d52a84b4a969aa53f8ededddff841646ad9yt */
82263d52a84b4a969aa53f8ededddff841646ad9ytstatic int
82263d52a84b4a969aa53f8ededddff841646ad9ytsata_ncq_err_ret_cmd_setup(sata_pkt_txlate_t *spx, sata_drive_info_t *sdinfo)
82263d52a84b4a969aa53f8ededddff841646ad9yt{
82263d52a84b4a969aa53f8ededddff841646ad9yt#ifndef __lock_lint
82263d52a84b4a969aa53f8ededddff841646ad9yt _NOTE(ARGUNUSED(sdinfo))
82263d52a84b4a969aa53f8ededddff841646ad9yt#endif
82263d52a84b4a969aa53f8ededddff841646ad9yt
82263d52a84b4a969aa53f8ededddff841646ad9yt sata_pkt_t *spkt = spx->txlt_sata_pkt;
82263d52a84b4a969aa53f8ededddff841646ad9yt sata_cmd_t *scmd;
82263d52a84b4a969aa53f8ededddff841646ad9yt struct buf *bp;
82263d52a84b4a969aa53f8ededddff841646ad9yt
82263d52a84b4a969aa53f8ededddff841646ad9yt /* Operation modes are up to the caller */
82263d52a84b4a969aa53f8ededddff841646ad9yt spkt->satapkt_op_mode = SATA_OPMODE_SYNCH | SATA_OPMODE_INTERRUPTS;
82263d52a84b4a969aa53f8ededddff841646ad9yt
82263d52a84b4a969aa53f8ededddff841646ad9yt /* Synchronous mode, no callback - may be changed by the caller */
82263d52a84b4a969aa53f8ededddff841646ad9yt spkt->satapkt_comp = NULL;
82263d52a84b4a969aa53f8ededddff841646ad9yt spkt->satapkt_time = sata_default_pkt_time;
82263d52a84b4a969aa53f8ededddff841646ad9yt
82263d52a84b4a969aa53f8ededddff841646ad9yt scmd = &spkt->satapkt_cmd;
82263d52a84b4a969aa53f8ededddff841646ad9yt bcopy(&sata_rle_cmd, scmd, sizeof (sata_cmd_t));
82263d52a84b4a969aa53f8ededddff841646ad9yt scmd->satacmd_flags.sata_ignore_dev_reset = B_TRUE;
82263d52a84b4a969aa53f8ededddff841646ad9yt
82263d52a84b4a969aa53f8ededddff841646ad9yt /*
82263d52a84b4a969aa53f8ededddff841646ad9yt * Allocate dma_able buffer error data.
82263d52a84b4a969aa53f8ededddff841646ad9yt * Buffer allocation will take care of buffer alignment and other DMA
82263d52a84b4a969aa53f8ededddff841646ad9yt * attributes.
82263d52a84b4a969aa53f8ededddff841646ad9yt */
82263d52a84b4a969aa53f8ededddff841646ad9yt bp = sata_alloc_local_buffer(spx,
82263d52a84b4a969aa53f8ededddff841646ad9yt sizeof (struct sata_ncq_error_recovery_page));
82263d52a84b4a969aa53f8ededddff841646ad9yt if (bp == NULL)
82263d52a84b4a969aa53f8ededddff841646ad9yt return (SATA_FAILURE);
82263d52a84b4a969aa53f8ededddff841646ad9yt
82263d52a84b4a969aa53f8ededddff841646ad9yt bp_mapin(bp); /* make data buffer accessible */
82263d52a84b4a969aa53f8ededddff841646ad9yt scmd->satacmd_bp = bp;
82263d52a84b4a969aa53f8ededddff841646ad9yt
82263d52a84b4a969aa53f8ededddff841646ad9yt /*
82263d52a84b4a969aa53f8ededddff841646ad9yt * Set-up pointer to the buffer handle, so HBA can sync buffer
82263d52a84b4a969aa53f8ededddff841646ad9yt * before accessing it. Handle is in usual place in translate struct.
82263d52a84b4a969aa53f8ededddff841646ad9yt */
82263d52a84b4a969aa53f8ededddff841646ad9yt scmd->satacmd_err_ret_buf_handle = &spx->txlt_buf_dma_handle;
82263d52a84b4a969aa53f8ededddff841646ad9yt
82263d52a84b4a969aa53f8ededddff841646ad9yt ASSERT(scmd->satacmd_num_dma_cookies != 0);
82263d52a84b4a969aa53f8ededddff841646ad9yt ASSERT(scmd->satacmd_dma_cookie_list != NULL);
82263d52a84b4a969aa53f8ededddff841646ad9yt
82263d52a84b4a969aa53f8ededddff841646ad9yt return (SATA_SUCCESS);
82263d52a84b4a969aa53f8ededddff841646ad9yt}
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown/*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * sata_xlate_errors() is used to translate (S)ATA error
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * information to SCSI information returned in the SCSI
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * packet.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic void
2038334ab26baaa43c9083f35def041511c3cc1fUnknownsata_xlate_errors(sata_pkt_txlate_t *spx)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown{
2038334ab26baaa43c9083f35def041511c3cc1fUnknown struct scsi_pkt *scsipkt = spx->txlt_scsi_pkt;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown struct scsi_extended_sense *sense;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scsipkt->pkt_reason = CMD_INCOMPLETE;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown *scsipkt->pkt_scbp = STATUS_CHECK;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sense = sata_arq_sense(spx);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown switch (spx->txlt_sata_pkt->satapkt_reason) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown case SATA_PKT_PORT_ERROR:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * We have no device data. Assume no data transfered.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sense->es_key = KEY_HARDWARE_ERROR;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown break;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown case SATA_PKT_DEV_ERROR:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (spx->txlt_sata_pkt->satapkt_cmd.satacmd_status_reg &
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_STATUS_ERR) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * determine dev error reason from error
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * reg content
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_decode_device_error(spx, sense);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown break;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* No extended sense key - no info available */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown break;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown case SATA_PKT_TIMEOUT:
ae8faf9c0cd738ab78a672de5bf7e7f7d004ebb2ls scsipkt->pkt_reason = CMD_TIMEOUT;
ae8faf9c0cd738ab78a672de5bf7e7f7d004ebb2ls scsipkt->pkt_statistics |= STAT_TIMEOUT | STAT_DEV_RESET;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* No extended sense key */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown break;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown case SATA_PKT_ABORTED:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scsipkt->pkt_reason = CMD_ABORTED;
ae8faf9c0cd738ab78a672de5bf7e7f7d004ebb2ls scsipkt->pkt_statistics |= STAT_ABORTED;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* No extended sense key */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown break;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown case SATA_PKT_RESET:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * pkt aborted either by an explicit reset request from
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * a host, or due to error recovery
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scsipkt->pkt_reason = CMD_RESET;
ae8faf9c0cd738ab78a672de5bf7e7f7d004ebb2ls scsipkt->pkt_statistics |= STAT_DEV_RESET;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown break;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown default:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown scsipkt->pkt_reason = CMD_TRAN_ERR;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown break;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown}
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown/*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Log sata message
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * dev pathname msg line preceeds the logged message.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic void
2038334ab26baaa43c9083f35def041511c3cc1fUnknownsata_log(sata_hba_inst_t *sata_hba_inst, uint_t level, char *fmt, ...)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown{
2038334ab26baaa43c9083f35def041511c3cc1fUnknown char pathname[128];
f5f2d263454d943a366844932bdb677530ba733bFred Herard dev_info_t *dip = NULL;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown va_list ap;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_enter(&sata_log_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown va_start(ap, fmt);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (void) vsprintf(sata_log_buf, fmt, ap);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown va_end(ap);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sata_hba_inst != NULL) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown dip = SATA_DIP(sata_hba_inst);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (void) ddi_pathname(dip, pathname);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown } else {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown pathname[0] = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (level == CE_CONT) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sata_debug_flags == 0)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cmn_err(level, "?%s:\n %s\n", pathname, sata_log_buf);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown else
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cmn_err(level, "%s:\n %s\n", pathname, sata_log_buf);
ae8faf9c0cd738ab78a672de5bf7e7f7d004ebb2ls } else {
ae8faf9c0cd738ab78a672de5bf7e7f7d004ebb2ls if (level != CE_NOTE) {
ae8faf9c0cd738ab78a672de5bf7e7f7d004ebb2ls cmn_err(level, "%s:\n %s", pathname, sata_log_buf);
ae8faf9c0cd738ab78a672de5bf7e7f7d004ebb2ls } else if (sata_msg) {
ae8faf9c0cd738ab78a672de5bf7e7f7d004ebb2ls cmn_err(level, "%s:\n %s", pathname,
ae8faf9c0cd738ab78a672de5bf7e7f7d004ebb2ls sata_log_buf);
ae8faf9c0cd738ab78a672de5bf7e7f7d004ebb2ls }
ae8faf9c0cd738ab78a672de5bf7e7f7d004ebb2ls }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
f5f2d263454d943a366844932bdb677530ba733bFred Herard /* sata trace debug */
f5f2d263454d943a366844932bdb677530ba733bFred Herard sata_trace_debug(dip, sata_log_buf);
f5f2d263454d943a366844932bdb677530ba733bFred Herard
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&sata_log_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown}
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown/* ******** Asynchronous HBA events handling & hotplugging support ******** */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown/*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Start or terminate the thread, depending on flag arg and current state
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic void
2038334ab26baaa43c9083f35def041511c3cc1fUnknownsata_event_thread_control(int startstop)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown{
2038334ab26baaa43c9083f35def041511c3cc1fUnknown static int sata_event_thread_terminating = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown static int sata_event_thread_starting = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown int i;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_enter(&sata_event_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (startstop == 0 && (sata_event_thread_starting == 1 ||
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_event_thread_terminating == 1)) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&sata_event_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (startstop == 1 && sata_event_thread_starting == 1) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&sata_event_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (startstop == 1 && sata_event_thread_terminating == 1) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_event_thread_starting = 1;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* wait til terminate operation completes */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown i = SATA_EVNT_DAEMON_TERM_WAIT/SATA_EVNT_DAEMON_TERM_TIMEOUT;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown while (sata_event_thread_terminating == 1) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (i-- <= 0) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_event_thread_starting = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&sata_event_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown#ifdef SATA_DEBUG
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cmn_err(CE_WARN, "sata_event_thread_control: "
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "timeout waiting for thread to terminate");
2038334ab26baaa43c9083f35def041511c3cc1fUnknown#endif
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&sata_event_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown delay(drv_usectohz(SATA_EVNT_DAEMON_TERM_TIMEOUT));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_enter(&sata_event_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (startstop == 1) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sata_event_thread == NULL) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_event_thread = thread_create(NULL, 0,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (void (*)())sata_event_daemon,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown &sata_hba_list, 0, &p0, TS_RUN, minclsyspri);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_event_thread_starting = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&sata_event_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * If we got here, thread may need to be terminated
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sata_event_thread != NULL) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown int i;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Signal event thread to go away */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_event_thread_terminating = 1;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_event_thread_terminate = 1;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cv_signal(&sata_event_cv);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Wait til daemon terminates.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown i = SATA_EVNT_DAEMON_TERM_WAIT/SATA_EVNT_DAEMON_TERM_TIMEOUT;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown while (sata_event_thread_terminate == 1) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&sata_event_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (i-- <= 0) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Daemon did not go away !!! */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown#ifdef SATA_DEBUG
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cmn_err(CE_WARN, "sata_event_thread_control: "
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "cannot terminate event daemon thread");
2038334ab26baaa43c9083f35def041511c3cc1fUnknown#endif
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_enter(&sata_event_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown break;
6ed1276fb5fe78fb1cce38682748a830ef8bd157pawelw }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown delay(drv_usectohz(SATA_EVNT_DAEMON_TERM_TIMEOUT));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_enter(&sata_event_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_event_thread_terminating = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ASSERT(sata_event_thread_terminating == 0);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ASSERT(sata_event_thread_starting == 0);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&sata_event_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown}
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown/*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * SATA HBA event notification function.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Events reported by SATA HBA drivers per HBA instance relate to a change in
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * a port and/or device state or a controller itself.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Events for different addresses/addr types cannot be combined.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * A warning message is generated for each event type.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Events are not processed by this function, so only the
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * event flag(s)is set for an affected entity and the event thread is
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * waken up. Event daemon thread processes all events.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown *
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * NOTE: Since more than one event may be reported at the same time, one
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * cannot determine a sequence of events when opposite event are reported, eg.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * LINK_LOST and LINK_ESTABLISHED. Actual port status during event processing
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * is taking precedence over reported events, i.e. may cause ignoring some
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * events.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown#define SATA_EVENT_MAX_MSG_LENGTH 79
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknownvoid
2038334ab26baaa43c9083f35def041511c3cc1fUnknownsata_hba_event_notify(dev_info_t *dip, sata_device_t *sata_device, int event)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown{
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_hba_inst_t *sata_hba_inst = NULL;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_address_t *saddr;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_pmult_info_t *pmultinfo;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_drive_info_t *sdinfo;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_port_stats_t *pstats;
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik sata_cport_info_t *cportinfo;
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik sata_pmport_info_t *pmportinfo;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown int cport, pmport;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown char buf1[SATA_EVENT_MAX_MSG_LENGTH + 1];
2038334ab26baaa43c9083f35def041511c3cc1fUnknown char buf2[SATA_EVENT_MAX_MSG_LENGTH + 1];
2038334ab26baaa43c9083f35def041511c3cc1fUnknown char *lcp;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown static char *err_msg_evnt_1 =
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "sata_hba_event_notify: invalid port event 0x%x ";
2038334ab26baaa43c9083f35def041511c3cc1fUnknown static char *err_msg_evnt_2 =
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "sata_hba_event_notify: invalid device event 0x%x ";
2038334ab26baaa43c9083f35def041511c3cc1fUnknown int linkevent;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * There is a possibility that an event will be generated on HBA
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik * that has not completed attachment or is detaching. We still want
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik * to process events until HBA is detached.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_enter(&sata_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown for (sata_hba_inst = sata_hba_list; sata_hba_inst != NULL;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_hba_inst = sata_hba_inst->satahba_next) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (SATA_DIP(sata_hba_inst) == dip)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sata_hba_inst->satahba_attached == 1)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown break;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&sata_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sata_hba_inst == NULL)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* HBA not attached */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ASSERT(sata_device != NULL);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Validate address before - do not proceed with invalid address.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown saddr = &sata_device->satadev_addr;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (saddr->cport >= SATA_NUM_CPORTS(sata_hba_inst))
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cport = saddr->cport;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown pmport = saddr->pmport;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown buf1[0] = buf2[0] = '\0';
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik /*
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik * If event relates to port or device, check port state.
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik * Port has to be initialized, or we cannot accept an event.
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik */
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik if ((saddr->qual & (SATA_ADDR_CPORT | SATA_ADDR_PMPORT |
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_ADDR_DCPORT | SATA_ADDR_DPMPORT | SATA_ADDR_PMULT)) != 0) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&sata_hba_inst->satahba_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cportinfo = SATA_CPORT_INFO(sata_hba_inst, cport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&sata_hba_inst->satahba_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (cportinfo == NULL || cportinfo->cport_state == 0)
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang return;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if ((saddr->qual & (SATA_ADDR_PMULT | SATA_ADDR_PMPORT |
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_ADDR_DPMPORT)) != 0) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (cportinfo->cport_dev_type != SATA_DTYPE_PMULT) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_LOG_D((sata_hba_inst, CE_WARN,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "sata_hba_event_notify: Non-pmult device (0x%x)"
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "is attached to port %d, ignore pmult/pmport "
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "event 0x%x", cportinfo->cport_dev_type,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cport, event));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang return;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&cportinfo->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmultinfo = SATA_PMULT_INFO(sata_hba_inst, cport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&cportinfo->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * The daemon might be processing attachment of port
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * multiplier, in that case we should ignore events on its
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * sub-devices.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang *
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * NOTE: Only pmult_state is checked in sata_hba_event_notify.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * The pmport_state is checked by sata daemon.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (pmultinfo == NULL ||
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmultinfo->pmult_state == SATA_STATE_UNKNOWN) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_LOG_D((sata_hba_inst, CE_WARN,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "sata_hba_event_notify: pmult is not"
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "available at port %d:%d, ignore event 0x%x",
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cport, pmport, event));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang return;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if ((saddr->qual &
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (SATA_ADDR_PMPORT | SATA_ADDR_DPMPORT)) != 0) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&cportinfo->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (pmport > SATA_NUM_PMPORTS(sata_hba_inst, cport)) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_LOG_D((sata_hba_inst, CE_WARN,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "sata_hba_event_notify: invalid/"
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "un-implemented port %d:%d (%d ports), "
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "ignore event 0x%x", cport, pmport,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_NUM_PMPORTS(sata_hba_inst, cport), event));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&cportinfo->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang return;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&cportinfo->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&sata_hba_inst->satahba_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo = SATA_PMPORT_INFO(sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cport, pmport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&sata_hba_inst->satahba_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* pmport is implemented/valid? */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (pmportinfo == NULL) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_LOG_D((sata_hba_inst, CE_WARN,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "sata_hba_event_notify: invalid/"
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "un-implemented port %d:%d, ignore "
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "event 0x%x", cport, pmport, event));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang return;
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik }
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik }
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Events refer to devices, ports and controllers - each has
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * unique address. Events for different addresses cannot be combined.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (saddr->qual & (SATA_ADDR_CPORT | SATA_ADDR_PMPORT)) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_enter(&(SATA_CPORT_MUTEX(sata_hba_inst, cport)));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* qualify this event(s) */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if ((event & SATA_EVNT_PORT_EVENTS) == 0) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Invalid event for the device port */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (void) sprintf(buf2, err_msg_evnt_1,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown event & SATA_EVNT_PORT_EVENTS);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst, cport)));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown goto event_info;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (saddr->qual == SATA_ADDR_CPORT) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Controller's device port event */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (SATA_CPORT_INFO(sata_hba_inst, cport))->
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cport_event_flags |=
2038334ab26baaa43c9083f35def041511c3cc1fUnknown event & SATA_EVNT_PORT_EVENTS;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown pstats =
2038334ab26baaa43c9083f35def041511c3cc1fUnknown &(SATA_CPORT_INFO(sata_hba_inst, cport))->
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cport_stats;
6ed1276fb5fe78fb1cce38682748a830ef8bd157pawelw } else {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst, cport)));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&pmportinfo->pmport_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Port multiplier's device port event */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (SATA_PMPORT_INFO(sata_hba_inst, cport, pmport))->
2038334ab26baaa43c9083f35def041511c3cc1fUnknown pmport_event_flags |=
2038334ab26baaa43c9083f35def041511c3cc1fUnknown event & SATA_EVNT_PORT_EVENTS;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown pstats =
2038334ab26baaa43c9083f35def041511c3cc1fUnknown &(SATA_PMPORT_INFO(sata_hba_inst, cport, pmport))->
2038334ab26baaa43c9083f35def041511c3cc1fUnknown pmport_stats;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&(SATA_CPORT_MUTEX(sata_hba_inst, cport)));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Add to statistics and log the message. We have to do it
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * here rather than in the event daemon, because there may be
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * multiple events occuring before they are processed.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown linkevent = event &
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (SATA_EVNT_LINK_LOST | SATA_EVNT_LINK_ESTABLISHED);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (linkevent) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (linkevent == (SATA_EVNT_LINK_LOST |
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_EVNT_LINK_ESTABLISHED)) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* This is likely event combination */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (void) strlcat(buf1, "link lost/established, ",
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_EVENT_MAX_MSG_LENGTH);
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (pstats->link_lost < 0xffffffffffffffffULL)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown pstats->link_lost++;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (pstats->link_established <
2038334ab26baaa43c9083f35def041511c3cc1fUnknown 0xffffffffffffffffULL)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown pstats->link_established++;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown linkevent = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown } else if (linkevent & SATA_EVNT_LINK_LOST) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (void) strlcat(buf1, "link lost, ",
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_EVENT_MAX_MSG_LENGTH);
4360436b3c604bc28d37be269ad152b4c38157c3pawelw
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (pstats->link_lost < 0xffffffffffffffffULL)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown pstats->link_lost++;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown } else {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (void) strlcat(buf1, "link established, ",
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_EVENT_MAX_MSG_LENGTH);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (pstats->link_established <
2038334ab26baaa43c9083f35def041511c3cc1fUnknown 0xffffffffffffffffULL)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown pstats->link_established++;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (event & SATA_EVNT_DEVICE_ATTACHED) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (void) strlcat(buf1, "device attached, ",
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_EVENT_MAX_MSG_LENGTH);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (pstats->device_attached < 0xffffffffffffffffULL)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown pstats->device_attached++;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (event & SATA_EVNT_DEVICE_DETACHED) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (void) strlcat(buf1, "device detached, ",
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_EVENT_MAX_MSG_LENGTH);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (pstats->device_detached < 0xffffffffffffffffULL)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown pstats->device_detached++;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (event & SATA_EVNT_PWR_LEVEL_CHANGED) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATADBG1(SATA_DBG_EVENTS, sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "port %d power level changed", cport);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (pstats->port_pwr_changed < 0xffffffffffffffffULL)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown pstats->port_pwr_changed++;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
4360436b3c604bc28d37be269ad152b4c38157c3pawelw
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if ((event & ~SATA_EVNT_PORT_EVENTS) != 0) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* There should be no other events for this address */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (void) sprintf(buf2, err_msg_evnt_1,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown event & ~SATA_EVNT_PORT_EVENTS);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst, cport)));
4360436b3c604bc28d37be269ad152b4c38157c3pawelw
2038334ab26baaa43c9083f35def041511c3cc1fUnknown } else if (saddr->qual & (SATA_ADDR_DCPORT | SATA_ADDR_DPMPORT)) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_enter(&(SATA_CPORT_MUTEX(sata_hba_inst, cport)));
4360436b3c604bc28d37be269ad152b4c38157c3pawelw
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* qualify this event */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if ((event & SATA_EVNT_DEVICE_RESET) == 0) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Invalid event for a device */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (void) sprintf(buf2, err_msg_evnt_2,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown event & SATA_EVNT_DEVICE_RESET);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst, cport)));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown goto event_info;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* drive event */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo = sata_get_device_info(sata_hba_inst, sata_device);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sdinfo != NULL) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (event & SATA_EVNT_DEVICE_RESET) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (void) strlcat(buf1, "device reset, ",
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_EVENT_MAX_MSG_LENGTH);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sdinfo->satadrv_stats.drive_reset <
2038334ab26baaa43c9083f35def041511c3cc1fUnknown 0xffffffffffffffffULL)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_stats.drive_reset++;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_event_flags |=
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_EVNT_DEVICE_RESET;
4360436b3c604bc28d37be269ad152b4c38157c3pawelw }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if ((event & ~SATA_EVNT_DEVICE_RESET) != 0) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Invalid event for a device */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (void) sprintf(buf2, err_msg_evnt_2,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown event & ~SATA_EVNT_DRIVE_EVENTS);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst, cport)));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang } else if (saddr->qual == SATA_ADDR_PMULT) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&(SATA_CPORT_MUTEX(sata_hba_inst, cport)));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* qualify this event */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if ((event & (SATA_EVNT_DEVICE_RESET |
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_EVNT_PMULT_LINK_CHANGED)) == 0) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Invalid event for a port multiplier */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (void) sprintf(buf2, err_msg_evnt_2,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang event & SATA_EVNT_DEVICE_RESET);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst, cport)));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang goto event_info;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmultinfo = SATA_PMULT_INFO(sata_hba_inst, cport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (event & SATA_EVNT_DEVICE_RESET) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATADBG1(SATA_DBG_PMULT, sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "[Reset] port-mult on cport %d", cport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmultinfo->pmult_event_flags |=
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_EVNT_DEVICE_RESET;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (void) strlcat(buf1, "pmult reset, ",
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_EVENT_MAX_MSG_LENGTH);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (event & SATA_EVNT_PMULT_LINK_CHANGED) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATADBG1(SATA_DBG_PMULT, sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "pmult link changed on cport %d", cport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmultinfo->pmult_event_flags |=
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_EVNT_PMULT_LINK_CHANGED;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (void) strlcat(buf1, "pmult link changed, ",
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_EVENT_MAX_MSG_LENGTH);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst, cport)));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
2038334ab26baaa43c9083f35def041511c3cc1fUnknown } else {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (saddr->qual != SATA_ADDR_NULL) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Wrong address qualifier */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_LOG_D((sata_hba_inst, CE_WARN,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "sata_hba_event_notify: invalid address 0x%x",
2038334ab26baaa43c9083f35def041511c3cc1fUnknown *(uint32_t *)saddr));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if ((event & SATA_EVNT_CONTROLLER_EVENTS) == 0 ||
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (event & ~SATA_EVNT_CONTROLLER_EVENTS) != 0) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Invalid event for the controller */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_LOG_D((sata_hba_inst, CE_WARN,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "sata_hba_event_notify: invalid event 0x%x for "
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "controller",
2038334ab26baaa43c9083f35def041511c3cc1fUnknown event & SATA_EVNT_CONTROLLER_EVENTS));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown buf1[0] = '\0';
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* This may be a frequent and not interesting event */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATADBG1(SATA_DBG_EVENTS, sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "controller power level changed\n", NULL);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_enter(&sata_hba_inst->satahba_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sata_hba_inst->satahba_stats.ctrl_pwr_change <
2038334ab26baaa43c9083f35def041511c3cc1fUnknown 0xffffffffffffffffULL)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_hba_inst->satahba_stats.ctrl_pwr_change++;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_hba_inst->satahba_event_flags |=
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_EVNT_PWR_LEVEL_CHANGED;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&sata_hba_inst->satahba_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * If we got here, there is something to do with this HBA
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * instance.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_enter(&sata_hba_inst->satahba_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_hba_inst->satahba_event_flags |= SATA_EVNT_MAIN;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&sata_hba_inst->satahba_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_enter(&sata_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_event_pending |= SATA_EVNT_MAIN; /* global event indicator */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&sata_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Tickle event thread */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_enter(&sata_event_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sata_event_thread_active == 0)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cv_signal(&sata_event_cv);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&sata_event_mutex);
4360436b3c604bc28d37be269ad152b4c38157c3pawelw
2038334ab26baaa43c9083f35def041511c3cc1fUnknownevent_info:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (buf1[0] != '\0') {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown lcp = strrchr(buf1, ',');
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (lcp != NULL)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown *lcp = '\0';
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (saddr->qual == SATA_ADDR_CPORT ||
2038334ab26baaa43c9083f35def041511c3cc1fUnknown saddr->qual == SATA_ADDR_DCPORT) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (buf1[0] != '\0') {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_log(sata_hba_inst, CE_NOTE, "port %d: %s\n",
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cport, buf1);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (buf2[0] != '\0') {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_log(sata_hba_inst, CE_NOTE, "port %d: %s\n",
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cport, buf2);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown } else if (saddr->qual == SATA_ADDR_PMPORT ||
2038334ab26baaa43c9083f35def041511c3cc1fUnknown saddr->qual == SATA_ADDR_DPMPORT) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (buf1[0] != '\0') {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_log(sata_hba_inst, CE_NOTE,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "port %d pmport %d: %s\n", cport, pmport, buf1);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (buf2[0] != '\0') {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_log(sata_hba_inst, CE_NOTE,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "port %d pmport %d: %s\n", cport, pmport, buf2);
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw }
6ed1276fb5fe78fb1cce38682748a830ef8bd157pawelw }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
4360436b3c604bc28d37be269ad152b4c38157c3pawelw/*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Event processing thread.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Arg is a pointer to the sata_hba_list pointer.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * It is not really needed, because sata_hba_list is global and static
4360436b3c604bc28d37be269ad152b4c38157c3pawelw */
4360436b3c604bc28d37be269ad152b4c38157c3pawelwstatic void
2038334ab26baaa43c9083f35def041511c3cc1fUnknownsata_event_daemon(void *arg)
4360436b3c604bc28d37be269ad152b4c38157c3pawelw{
2038334ab26baaa43c9083f35def041511c3cc1fUnknown#ifndef __lock_lint
2038334ab26baaa43c9083f35def041511c3cc1fUnknown _NOTE(ARGUNUSED(arg))
2038334ab26baaa43c9083f35def041511c3cc1fUnknown#endif
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_hba_inst_t *sata_hba_inst;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown clock_t lbolt;
4360436b3c604bc28d37be269ad152b4c38157c3pawelw
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATADBG1(SATA_DBG_EVENTS_DAEMON, NULL,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "SATA event daemon started\n", NULL);
2038334ab26baaa43c9083f35def041511c3cc1fUnknownloop:
4360436b3c604bc28d37be269ad152b4c38157c3pawelw /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Process events here. Walk through all registered HBAs
4360436b3c604bc28d37be269ad152b4c38157c3pawelw */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_enter(&sata_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown for (sata_hba_inst = sata_hba_list; sata_hba_inst != NULL;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_hba_inst = sata_hba_inst->satahba_next) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ASSERT(sata_hba_inst != NULL);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_enter(&sata_hba_inst->satahba_mutex);
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik if (sata_hba_inst->satahba_attached == 0 ||
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (sata_hba_inst->satahba_event_flags &
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_EVNT_SKIP) != 0) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&sata_hba_inst->satahba_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown continue;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sata_hba_inst->satahba_event_flags & SATA_EVNT_MAIN) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_hba_inst->satahba_event_flags |= SATA_EVNT_SKIP;
4360436b3c604bc28d37be269ad152b4c38157c3pawelw mutex_exit(&sata_hba_inst->satahba_mutex);
4360436b3c604bc28d37be269ad152b4c38157c3pawelw mutex_exit(&sata_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Got the controller with pending event */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_process_controller_events(sata_hba_inst);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Since global mutex was released, there is a
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * possibility that HBA list has changed, so start
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * over from the top. Just processed controller
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * will be passed-over because of the SKIP flag.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown goto loop;
4360436b3c604bc28d37be269ad152b4c38157c3pawelw }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&sata_hba_inst->satahba_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Clear SKIP flag in all controllers */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown for (sata_hba_inst = sata_hba_list; sata_hba_inst != NULL;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_hba_inst = sata_hba_inst->satahba_next) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_enter(&sata_hba_inst->satahba_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_hba_inst->satahba_event_flags &= ~SATA_EVNT_SKIP;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&sata_hba_inst->satahba_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&sata_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATADBG1(SATA_DBG_EVENTS_DAEMON, NULL,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "SATA EVENT DAEMON suspending itself", NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown#ifdef SATA_DEBUG
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if ((sata_func_enable & SATA_ENABLE_PROCESS_EVENTS) == 0) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_log(sata_hba_inst, CE_WARN,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "SATA EVENTS PROCESSING DISABLED\n");
2038334ab26baaa43c9083f35def041511c3cc1fUnknown thread_exit(); /* Daemon will not run again */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown#endif
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_enter(&sata_event_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_event_thread_active = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&sata_event_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Go to sleep/suspend itself and wake up either because new event or
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * wait timeout. Exit if there is a termination request (driver
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * unload).
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown do {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown lbolt = ddi_get_lbolt();
2038334ab26baaa43c9083f35def041511c3cc1fUnknown lbolt += drv_usectohz(SATA_EVNT_DAEMON_SLEEP_TIME);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_enter(&sata_event_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (void) cv_timedwait(&sata_event_cv, &sata_event_mutex, lbolt);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sata_event_thread_active != 0) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&sata_event_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown continue;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Check if it is time to go away */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sata_event_thread_terminate == 1) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * It is up to the thread setting above flag to make
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * sure that this thread is not killed prematurely.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_event_thread_terminate = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_event_thread = NULL;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&sata_event_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATADBG1(SATA_DBG_EVENTS_DAEMON, NULL,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "SATA_EVENT_DAEMON_TERMINATING", NULL);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown thread_exit(); { _NOTE(NOT_REACHED) }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&sata_event_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown } while (!(sata_event_pending & SATA_EVNT_MAIN));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_enter(&sata_event_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_event_thread_active = 1;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&sata_event_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_enter(&sata_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_event_pending &= ~SATA_EVNT_MAIN;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&sata_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATADBG1(SATA_DBG_EVENTS_DAEMON, NULL,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "SATA EVENT DAEMON READY TO PROCESS EVENT", NULL);
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw
2038334ab26baaa43c9083f35def041511c3cc1fUnknown goto loop;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown}
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw
c03acfcad7780db4ddf763511a82026680b3b2c1ls/*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Specific HBA instance event processing.
c03acfcad7780db4ddf763511a82026680b3b2c1ls *
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * NOTE: At the moment, device event processing is limited to hard disks
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * only.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Port multiplier is supported now.
c03acfcad7780db4ddf763511a82026680b3b2c1ls */
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic void
2038334ab26baaa43c9083f35def041511c3cc1fUnknownsata_process_controller_events(sata_hba_inst_t *sata_hba_inst)
c03acfcad7780db4ddf763511a82026680b3b2c1ls{
2038334ab26baaa43c9083f35def041511c3cc1fUnknown int ncport;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown uint32_t event_flags;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_address_t *saddr;
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik sata_cport_info_t *cportinfo;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_pmult_info_t *pmultinfo;
c03acfcad7780db4ddf763511a82026680b3b2c1ls
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATADBG1(SATA_DBG_EVENTS_CNTRL, sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "Processing controller %d event(s)",
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ddi_get_instance(SATA_DIP(sata_hba_inst)));
c03acfcad7780db4ddf763511a82026680b3b2c1ls
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_enter(&sata_hba_inst->satahba_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_hba_inst->satahba_event_flags &= ~SATA_EVNT_MAIN;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown event_flags = sata_hba_inst->satahba_event_flags;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&sata_hba_inst->satahba_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Process controller power change first
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * HERE
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (event_flags & SATA_EVNT_PWR_LEVEL_CHANGED)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_process_cntrl_pwr_level_change(sata_hba_inst);
c03acfcad7780db4ddf763511a82026680b3b2c1ls
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Search through ports/devices to identify affected port/device.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * We may have to process events for more than one port/device.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown for (ncport = 0; ncport < SATA_NUM_CPORTS(sata_hba_inst); ncport++) {
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik /*
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik * Not all ports may be processed in attach by the time we
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik * get an event. Check if port info is initialized.
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik */
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik mutex_enter(&sata_hba_inst->satahba_mutex);
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik cportinfo = SATA_CPORT_INFO(sata_hba_inst, ncport);
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik mutex_exit(&sata_hba_inst->satahba_mutex);
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik if (cportinfo == NULL || cportinfo->cport_state == NULL)
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik continue;
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik /* We have initialized controller port info */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_enter(&(SATA_CPORT_MUTEX(sata_hba_inst, ncport)));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown event_flags = (SATA_CPORT_INFO(sata_hba_inst, ncport))->
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cport_event_flags;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Check if port was locked by IOCTL processing */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (event_flags & SATA_APCTL_LOCK_PORT_BUSY) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * We ignore port events because port is busy
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * with AP control processing. Set again
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * controller and main event flag, so that
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * events may be processed by the next daemon
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * run.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst, ncport)));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_enter(&sata_hba_inst->satahba_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_hba_inst->satahba_event_flags |= SATA_EVNT_MAIN;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&sata_hba_inst->satahba_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_enter(&sata_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_event_pending |= SATA_EVNT_MAIN;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&sata_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATADBG1(SATA_DBG_EVENTS_PROCPST, sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "Event processing postponed until "
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "AP control processing completes",
2038334ab26baaa43c9083f35def041511c3cc1fUnknown NULL);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Check other ports */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown continue;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown } else {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Set BSY flag so that AP control would not
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * interfere with events processing for
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * this port.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (SATA_CPORT_INFO(sata_hba_inst, ncport))->
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cport_event_flags |= SATA_EVNT_LOCK_PORT_BUSY;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst, ncport)));
c03acfcad7780db4ddf763511a82026680b3b2c1ls
2038334ab26baaa43c9083f35def041511c3cc1fUnknown saddr = &(SATA_CPORT_INFO(sata_hba_inst, ncport))->cport_addr;
c03acfcad7780db4ddf763511a82026680b3b2c1ls
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if ((event_flags &
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (SATA_EVNT_PORT_EVENTS | SATA_EVNT_DRIVE_EVENTS)) != 0) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Got port event.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * We need some hierarchy of event processing as they
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * are affecting each other:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * 1. port failed
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * 2. device detached/attached
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * 3. link events - link events may trigger device
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * detached or device attached events in some
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * circumstances.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * 4. port power level changed
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (event_flags & SATA_EVNT_PORT_FAILED) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_process_port_failed_event(sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown saddr);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (event_flags & SATA_EVNT_DEVICE_DETACHED) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_process_device_detached(sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown saddr);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (event_flags & SATA_EVNT_DEVICE_ATTACHED) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_process_device_attached(sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown saddr);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (event_flags &
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (SATA_EVNT_LINK_ESTABLISHED |
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_EVNT_LINK_LOST)) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_process_port_link_events(sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown saddr);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (event_flags & SATA_EVNT_PWR_LEVEL_CHANGED) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_process_port_pwr_change(sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown saddr);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (event_flags & SATA_EVNT_TARGET_NODE_CLEANUP) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_process_target_node_cleanup(
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_hba_inst, saddr);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (event_flags & SATA_EVNT_AUTOONLINE_DEVICE) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_process_device_autoonline(
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_hba_inst, saddr);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Scan port multiplier and all its sub-ports event flags.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * The events are marked by
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * (1) sata_pmult_info.pmult_event_flags
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * (2) sata_pmport_info.pmport_event_flags
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&(SATA_CPORT_MUTEX(sata_hba_inst, ncport)));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (cportinfo->cport_dev_type == SATA_DTYPE_PMULT) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * There should be another extra check: this
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * port multiplier still exists?
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmultinfo = SATA_PMULT_INFO(sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang ncport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (pmultinfo != NULL) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&(SATA_CPORT_MUTEX(
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_hba_inst, ncport)));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_process_pmult_events(
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_hba_inst, ncport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&(SATA_CPORT_MUTEX(
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_hba_inst, ncport)));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang } else {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATADBG1(SATA_DBG_PMULT, sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "Port-multiplier is gone. "
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "Ignore all sub-device events "
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "at port %d.", ncport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if ((SATA_CPORT_DEV_TYPE(sata_hba_inst, ncport) !=
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_DTYPE_NONE) &&
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (SATA_CPORT_DRV_INFO(sata_hba_inst, ncport) != NULL)) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (SATA_CPORT_DRV_INFO(sata_hba_inst, ncport)->
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang satadrv_event_flags &
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (SATA_EVNT_DEVICE_RESET |
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_EVNT_INPROC_DEVICE_RESET)) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Have device event */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_process_device_reset(sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang saddr);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Release PORT_BUSY flag */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (SATA_CPORT_INFO(sata_hba_inst, ncport))->
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cport_event_flags &= ~SATA_EVNT_LOCK_PORT_BUSY;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst, ncport)));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang } /* End of loop through the controller SATA ports */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang}
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang/*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Specific port multiplier instance event processing. At the moment, device
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * event processing is limited to link/attach event only.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang *
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * NOTE: power management event is not supported yet.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhangstatic void
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhangsata_process_pmult_events(sata_hba_inst_t *sata_hba_inst, uint8_t cport)
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang{
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_cport_info_t *cportinfo = SATA_CPORT_INFO(sata_hba_inst, cport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_pmult_info_t *pmultinfo;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_pmport_info_t *pmportinfo;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_address_t *saddr;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device_t sata_device;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang uint32_t event_flags;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang int npmport;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang int rval;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATADBG2(SATA_DBG_EVENTS_CNTRL|SATA_DBG_PMULT, sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "Processing pmult event(s) on cport %d of controller %d",
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cport, ddi_get_instance(SATA_DIP(sata_hba_inst)));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* First process events on port multiplier */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&cportinfo->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmultinfo = SATA_PMULT_INFO(sata_hba_inst, cport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang event_flags = pmultinfo->pmult_event_flags;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Reset event (of port multiplier) has higher priority because the
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * port multiplier itself might be failed or removed after reset.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (event_flags & SATA_EVNT_DEVICE_RESET) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * The status of the sub-links are uncertain,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * so mark all sub-ports as RESET
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang for (npmport = 0; npmport < SATA_NUM_PMPORTS(
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_hba_inst, cport); npmport ++) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo = SATA_PMPORT_INFO(sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cport, npmport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (pmportinfo == NULL) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* That's weird. */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_LOG_D((sata_hba_inst, CE_WARN,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "sata_hba_event_notify: "
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "invalid/un-implemented "
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "port %d:%d (%d ports), ",
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cport, npmport, SATA_NUM_PMPORTS(
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_hba_inst, cport)));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang continue;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Mark all pmport to unknow state. */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo->pmport_state = SATA_STATE_UNKNOWN;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Mark all pmports with link events. */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo->pmport_event_flags =
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (SATA_EVNT_LINK_ESTABLISHED|SATA_EVNT_LINK_LOST);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang } else if (event_flags & SATA_EVNT_PMULT_LINK_CHANGED) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * We need probe the port multiplier to know what has
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * happened.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang bzero(&sata_device, sizeof (sata_device_t));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device.satadev_rev = SATA_DEVICE_REV;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device.satadev_addr.cport = cport;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device.satadev_addr.pmport = SATA_PMULT_HOSTPORT;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device.satadev_addr.qual = SATA_ADDR_PMULT;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&cportinfo->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang rval = (*SATA_PROBE_PORT_FUNC(sata_hba_inst))
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (SATA_DIP(sata_hba_inst), &sata_device);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&cportinfo->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (rval != SATA_SUCCESS) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Something went wrong? Fail the port */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cportinfo->cport_state = SATA_PSTATE_FAILED;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&cportinfo->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_LOG_D((sata_hba_inst, CE_WARN,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "SATA port %d probing failed", cport));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* PMult structure must be released. */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_free_pmult(sata_hba_inst, &sata_device);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang return;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_update_port_info(sata_hba_inst, &sata_device);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Sanity check - Port is active? Is the link active?
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * The device is still a port multiplier?
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if ((cportinfo->cport_state &
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (SATA_PSTATE_SHUTDOWN | SATA_PSTATE_FAILED)) ||
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang ((cportinfo->cport_scr.sstatus &
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_PORT_DEVLINK_UP_MASK) != SATA_PORT_DEVLINK_UP) ||
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (cportinfo->cport_dev_type != SATA_DTYPE_PMULT)) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&cportinfo->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* PMult structure must be released. */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_free_pmult(sata_hba_inst, &sata_device);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang return;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Probed succeed, set port ready. */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cportinfo->cport_state |=
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_STATE_PROBED | SATA_STATE_READY;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Release port multiplier event flags. */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmultinfo->pmult_event_flags &=
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang ~(SATA_EVNT_DEVICE_RESET|SATA_EVNT_PMULT_LINK_CHANGED);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&cportinfo->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Check all sub-links.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang for (npmport = 0; npmport < SATA_NUM_PMPORTS(sata_hba_inst, cport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang npmport ++) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo = SATA_PMPORT_INFO(sata_hba_inst, cport, npmport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang event_flags = pmportinfo->pmport_event_flags;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang saddr = &pmportinfo->pmport_addr;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if ((event_flags &
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (SATA_EVNT_PORT_EVENTS | SATA_EVNT_DRIVE_EVENTS)) != 0) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Got port multiplier port event.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * We need some hierarchy of event processing as they
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * are affecting each other:
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * 1. device detached/attached
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * 2. link events - link events may trigger device
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * detached or device attached events in some
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * circumstances.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (event_flags & SATA_EVNT_DEVICE_DETACHED) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_process_pmdevice_detached(sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang saddr);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (event_flags & SATA_EVNT_DEVICE_ATTACHED) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_process_pmdevice_attached(sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang saddr);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (event_flags & SATA_EVNT_LINK_ESTABLISHED ||
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang event_flags & SATA_EVNT_LINK_LOST) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_process_pmport_link_events(sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang saddr);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (event_flags & SATA_EVNT_TARGET_NODE_CLEANUP) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_process_target_node_cleanup(
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_hba_inst, saddr);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Checking drive event(s). */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (pmportinfo->pmport_dev_type != SATA_DTYPE_NONE &&
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo->pmport_sata_drive != NULL) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang event_flags = pmportinfo->pmport_sata_drive->
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang satadrv_event_flags;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (event_flags & (SATA_EVNT_DEVICE_RESET |
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw SATA_EVNT_INPROC_DEVICE_RESET)) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw /* Have device event */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_process_pmdevice_reset(sata_hba_inst,
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw saddr);
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw }
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Release PORT_BUSY flag */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&cportinfo->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cportinfo->cport_event_flags &= ~SATA_EVNT_LOCK_PORT_BUSY;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&cportinfo->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
c03acfcad7780db4ddf763511a82026680b3b2c1ls
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATADBG2(SATA_DBG_EVENTS_CNTRL|SATA_DBG_PMULT, sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "[DONE] pmult event(s) on cport %d of controller %d",
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cport, ddi_get_instance(SATA_DIP(sata_hba_inst)));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown}
489f952b4388bd1ea1feff97164a4416e0c621eals
2038334ab26baaa43c9083f35def041511c3cc1fUnknown/*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Process HBA power level change reported by HBA driver.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Not implemented at this time - event is ignored.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic void
2038334ab26baaa43c9083f35def041511c3cc1fUnknownsata_process_cntrl_pwr_level_change(sata_hba_inst_t *sata_hba_inst)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown{
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATADBG1(SATA_DBG_EVENTS_PROC, sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "Processing controller power level change", NULL);
c03acfcad7780db4ddf763511a82026680b3b2c1ls
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Ignoring it for now */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_enter(&sata_hba_inst->satahba_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_hba_inst->satahba_event_flags &= ~SATA_EVNT_PWR_LEVEL_CHANGED;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&sata_hba_inst->satahba_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown}
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown/*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Process port power level change reported by HBA driver.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Not implemented at this time - event is ignored.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic void
2038334ab26baaa43c9083f35def041511c3cc1fUnknownsata_process_port_pwr_change(sata_hba_inst_t *sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_address_t *saddr)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown{
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_cport_info_t *cportinfo;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATADBG1(SATA_DBG_EVENTS_PROC, sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "Processing port power level change", NULL);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cportinfo = SATA_CPORT_INFO(sata_hba_inst, saddr->cport);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_enter(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->cport_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Reset event flag */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cportinfo->cport_event_flags &= ~SATA_EVNT_PWR_LEVEL_CHANGED;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->cport_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown}
c03acfcad7780db4ddf763511a82026680b3b2c1ls
2038334ab26baaa43c9083f35def041511c3cc1fUnknown/*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Process port failure reported by HBA driver.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * cports support only - no pmports.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic void
2038334ab26baaa43c9083f35def041511c3cc1fUnknownsata_process_port_failed_event(sata_hba_inst_t *sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_address_t *saddr)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown{
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_cport_info_t *cportinfo;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cportinfo = SATA_CPORT_INFO(sata_hba_inst, saddr->cport);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_enter(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->cport_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Reset event flag first */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cportinfo->cport_event_flags &= ~SATA_EVNT_PORT_FAILED;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* If the port is in SHUTDOWN or FAILED state, ignore this event. */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if ((cportinfo->cport_state &
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (SATA_PSTATE_SHUTDOWN | SATA_PSTATE_FAILED)) == 0) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cport_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Fail the port */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cportinfo->cport_state = SATA_PSTATE_FAILED;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->cport_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_log(sata_hba_inst, CE_WARN, "SATA port %d failed", saddr->cport);
c03acfcad7780db4ddf763511a82026680b3b2c1ls}
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls/*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Device Reset Event processing.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * The seqeunce is managed by 3 stage flags:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * - reset event reported,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * - reset event being processed,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * - request to clear device reset state.
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw *
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw * NOTE: This function has to be entered with cport mutex held. It exits with
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw * mutex held as well, but can release mutex during the processing.
c03acfcad7780db4ddf763511a82026680b3b2c1ls */
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic void
2038334ab26baaa43c9083f35def041511c3cc1fUnknownsata_process_device_reset(sata_hba_inst_t *sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_address_t *saddr)
c03acfcad7780db4ddf763511a82026680b3b2c1ls{
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_drive_info_t old_sdinfo; /* local copy of the drive info */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_drive_info_t *sdinfo;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_cport_info_t *cportinfo;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_device_t sata_device;
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik int rval_probe, rval_set;
c03acfcad7780db4ddf763511a82026680b3b2c1ls
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* We only care about host sata cport for now */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cportinfo = SATA_CPORT_INFO(sata_hba_inst, saddr->cport);
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw sdinfo = SATA_CPORT_DRV_INFO(sata_hba_inst, saddr->cport);
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw /*
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw * If the port is in SHUTDOWN or FAILED state, or device is in FAILED
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw * state, ignore reset event.
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw */
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw if (((cportinfo->cport_state &
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw (SATA_PSTATE_SHUTDOWN | SATA_PSTATE_FAILED)) != 0) ||
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw (sdinfo->satadrv_state & SATA_DSTATE_FAILED) != 0) {
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw sdinfo->satadrv_event_flags &=
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw ~(SATA_EVNT_DEVICE_RESET | SATA_EVNT_INPROC_DEVICE_RESET);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return;
c03acfcad7780db4ddf763511a82026680b3b2c1ls }
c03acfcad7780db4ddf763511a82026680b3b2c1ls
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if ((SATA_CPORT_DEV_TYPE(sata_hba_inst, saddr->cport) ==
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_DTYPE_PMULT)) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Should not happened: this is already handled in
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * sata_hba_event_notify()
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&cportinfo->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang goto done;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if ((SATA_CPORT_DEV_TYPE(sata_hba_inst, saddr->cport) &
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_VALID_DEV_TYPE) == 0) {
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw /*
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw * This should not happen - coding error.
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw * But we can recover, so do not panic, just clean up
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw * and if in debug mode, log the message.
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw */
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw#ifdef SATA_DEBUG
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw sata_log(sata_hba_inst, CE_WARN,
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw "sata_process_device_reset: "
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw "Invalid device type with sdinfo!", NULL);
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw#endif
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw sdinfo->satadrv_event_flags = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
c03acfcad7780db4ddf763511a82026680b3b2c1ls
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw#ifdef SATA_DEBUG
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if ((sdinfo->satadrv_event_flags &
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (SATA_EVNT_DEVICE_RESET | SATA_EVNT_INPROC_DEVICE_RESET)) == 0) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Nothing to do */
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw /* Something is weird - why we are processing dev reset? */
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw SATADBG1(SATA_DBG_EVENTS_PROC, sata_hba_inst,
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw "No device reset event!!!!", NULL);
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if ((sdinfo->satadrv_event_flags &
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (SATA_EVNT_DEVICE_RESET | SATA_EVNT_INPROC_DEVICE_RESET)) ==
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (SATA_EVNT_DEVICE_RESET | SATA_EVNT_INPROC_DEVICE_RESET)) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Something is weird - new device reset event */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATADBG1(SATA_DBG_EVENTS_PROC, sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "Overlapping device reset events!", NULL);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown#endif
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATADBG1(SATA_DBG_EVENTS_PROC, sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "Processing port %d device reset", saddr->cport);
c03acfcad7780db4ddf763511a82026680b3b2c1ls
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Clear event flag */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_event_flags &= ~SATA_EVNT_DEVICE_RESET;
c03acfcad7780db4ddf763511a82026680b3b2c1ls
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* It seems that we always need to check the port state first */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_device.satadev_rev = SATA_DEVICE_REV;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_device.satadev_addr = *saddr;
c03acfcad7780db4ddf763511a82026680b3b2c1ls /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * We have to exit mutex, because the HBA probe port function may
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * block on its own mutex.
c03acfcad7780db4ddf763511a82026680b3b2c1ls */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->cport_mutex);
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik rval_probe = (*SATA_PROBE_PORT_FUNC(sata_hba_inst))
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (SATA_DIP(sata_hba_inst), &sata_device);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_enter(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->cport_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_update_port_info(sata_hba_inst, &sata_device);
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik if (rval_probe != SATA_SUCCESS) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Something went wrong? Fail the port */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cportinfo->cport_state = SATA_PSTATE_FAILED;
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw sdinfo = SATA_CPORT_DRV_INFO(sata_hba_inst, saddr->cport);
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw if (sdinfo != NULL)
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw sdinfo->satadrv_event_flags = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cport_mutex);
c03acfcad7780db4ddf763511a82026680b3b2c1ls SATA_LOG_D((sata_hba_inst, CE_WARN,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "SATA port %d probing failed",
2038334ab26baaa43c9083f35def041511c3cc1fUnknown saddr->cport));
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw mutex_enter(&SATA_CPORT_INFO(sata_hba_inst,
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw saddr->cport)->cport_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if ((sata_device.satadev_scr.sstatus &
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_PORT_DEVLINK_UP_MASK) !=
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_PORT_DEVLINK_UP ||
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_device.satadev_type == SATA_DTYPE_NONE) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * No device to process, anymore. Some other event processing
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * would or have already performed port info cleanup.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * To be safe (HBA may need it), request clearing device
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * reset condition.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sdinfo = SATA_CPORT_DRV_INFO(sata_hba_inst, saddr->cport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (sdinfo != NULL) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sdinfo->satadrv_event_flags &=
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang ~SATA_EVNT_INPROC_DEVICE_RESET;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sdinfo->satadrv_event_flags |=
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_EVNT_CLEAR_DEVICE_RESET;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang return;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sdinfo = SATA_CPORT_DRV_INFO(sata_hba_inst, saddr->cport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (sdinfo == NULL) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang return;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if ((sdinfo->satadrv_event_flags &
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_EVNT_INPROC_DEVICE_RESET) == 0) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Start tracking time for device feature restoration and
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * identification. Save current time (lbolt value).
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sdinfo->satadrv_reset_time = ddi_get_lbolt();
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Mark device reset processing as active */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sdinfo->satadrv_event_flags |= SATA_EVNT_INPROC_DEVICE_RESET;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang old_sdinfo = *sdinfo; /* local copy of the drive info */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang rval_set = sata_set_drive_features(sata_hba_inst, &old_sdinfo, 1);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (rval_set != SATA_SUCCESS) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Restoring drive setting failed.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Probe the port first, to check if the port state has changed
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device.satadev_rev = SATA_DEVICE_REV;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device.satadev_addr = *saddr;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device.satadev_addr.qual = SATA_ADDR_CPORT;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* probe port */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang rval_probe = (*SATA_PROBE_PORT_FUNC(sata_hba_inst))
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (SATA_DIP(sata_hba_inst), &sata_device);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (rval_probe == SATA_SUCCESS &&
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (sata_device.satadev_state &
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (SATA_PSTATE_SHUTDOWN | SATA_PSTATE_FAILED)) == 0 &&
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (sata_device.satadev_scr.sstatus &
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_PORT_DEVLINK_UP_MASK) == SATA_PORT_DEVLINK_UP &&
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device.satadev_type != SATA_DTYPE_NONE) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * We may retry this a bit later - in-process reset
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * condition should be already set.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Track retry time for device identification.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if ((cportinfo->cport_dev_type &
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_VALID_DEV_TYPE) != 0 &&
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_CPORTINFO_DRV_INFO(cportinfo) != NULL &&
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sdinfo->satadrv_reset_time != 0) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang clock_t cur_time = ddi_get_lbolt();
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * If the retry time limit was not
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * exceeded, retry.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if ((cur_time - sdinfo->satadrv_reset_time) <
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang drv_usectohz(SATA_DEV_REPROBE_TIMEOUT)) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang &sata_hba_inst->satahba_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_hba_inst->satahba_event_flags |=
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_EVNT_MAIN;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang &sata_hba_inst->satahba_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&sata_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_event_pending |= SATA_EVNT_MAIN;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&sata_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang return;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (rval_set == SATA_RETRY) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Setting drive features failed, but
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * the drive is still accessible,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * so emit a warning message before
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * return.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&SATA_CPORT_INFO(
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang saddr->cport)->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang goto done;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Fail the drive */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sdinfo->satadrv_state = SATA_DSTATE_FAILED;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_log(sata_hba_inst, CE_WARN,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "SATA device at port %d - device failed",
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang saddr->cport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * No point of retrying - device failed or some other event
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * processing or already did or will do port info cleanup.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * To be safe (HBA may need it),
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * request clearing device reset condition.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sdinfo->satadrv_event_flags |= SATA_EVNT_CLEAR_DEVICE_RESET;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sdinfo->satadrv_event_flags &= ~SATA_EVNT_INPROC_DEVICE_RESET;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sdinfo->satadrv_reset_time = 0;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang return;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhangdone:
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * If setting of drive features failed, but the drive is still
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * accessible, emit a warning message.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (rval_set == SATA_RETRY) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_log(sata_hba_inst, CE_WARN,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "SATA device at port %d - desired setting could not be "
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "restored after reset. Device may not operate as expected.",
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang saddr->cport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Raise the flag indicating that the next sata command could
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * be sent with SATA_CLEAR_DEV_RESET_STATE flag, if no new device
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * reset is reported.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (SATA_CPORTINFO_DRV_INFO(cportinfo) != NULL) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sdinfo->satadrv_reset_time = 0;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if ((cportinfo->cport_dev_type & SATA_VALID_DEV_TYPE) != 0) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sdinfo = SATA_CPORTINFO_DRV_INFO(cportinfo);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sdinfo->satadrv_event_flags &=
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang ~SATA_EVNT_INPROC_DEVICE_RESET;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sdinfo->satadrv_event_flags |=
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_EVNT_CLEAR_DEVICE_RESET;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang}
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang/*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Port Multiplier Port Device Reset Event processing.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang *
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * NOTE: This function has to be entered with pmport mutex held. It exits with
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * mutex held as well, but can release mutex during the processing.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhangstatic void
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhangsata_process_pmdevice_reset(sata_hba_inst_t *sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_address_t *saddr)
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang{
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_drive_info_t old_sdinfo; /* local copy of the drive info */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_drive_info_t *sdinfo = NULL;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_cport_info_t *cportinfo = NULL;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_pmport_info_t *pmportinfo = NULL;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_pmult_info_t *pminfo = NULL;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device_t sata_device;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang uint8_t cport = saddr->cport;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang uint8_t pmport = saddr->pmport;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang int rval;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATADBG2(SATA_DBG_EVENTS_PROC, sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "Processing drive reset at port %d:%d", cport, pmport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cportinfo = SATA_CPORT_INFO(sata_hba_inst, cport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo = SATA_PMPORT_INFO(sata_hba_inst, cport, pmport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sdinfo = SATA_PMPORT_DRV_INFO(sata_hba_inst, cport, pmport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * If the port is in SHUTDOWN or FAILED state, or device is in FAILED
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * state, ignore reset event.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (((cportinfo->cport_state &
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (SATA_PSTATE_SHUTDOWN | SATA_PSTATE_FAILED)) != 0) ||
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (sdinfo->satadrv_state & SATA_DSTATE_FAILED) != 0) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sdinfo->satadrv_event_flags &=
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang ~(SATA_EVNT_DEVICE_RESET | SATA_EVNT_INPROC_DEVICE_RESET);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang return;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if ((pmportinfo->pmport_dev_type & SATA_VALID_DEV_TYPE) == 0) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * This should not happen - coding error.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * But we can recover, so do not panic, just clean up
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * and if in debug mode, log the message.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang#ifdef SATA_DEBUG
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_log(sata_hba_inst, CE_WARN,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "sata_process_pmdevice_reset: "
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "Invalid device type with sdinfo!", NULL);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang#endif
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sdinfo->satadrv_event_flags = 0;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang return;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang#ifdef SATA_DEBUG
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if ((sdinfo->satadrv_event_flags &
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (SATA_EVNT_DEVICE_RESET | SATA_EVNT_INPROC_DEVICE_RESET)) == 0) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Nothing to do */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Something is weird - why we are processing dev reset? */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATADBG1(SATA_DBG_EVENTS_PROC, sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "No device reset event!!!!", NULL);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang return;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if ((sdinfo->satadrv_event_flags &
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (SATA_EVNT_DEVICE_RESET | SATA_EVNT_INPROC_DEVICE_RESET)) ==
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (SATA_EVNT_DEVICE_RESET | SATA_EVNT_INPROC_DEVICE_RESET)) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Something is weird - new device reset event */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATADBG1(SATA_DBG_EVENTS_PROC, sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "Overlapping device reset events!", NULL);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang#endif
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATADBG2(SATA_DBG_EVENTS_PROC, sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "Processing port %d:%d device reset", cport, pmport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Clear event flag */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sdinfo->satadrv_event_flags &= ~SATA_EVNT_DEVICE_RESET;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* It seems that we always need to check the port state first */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device.satadev_rev = SATA_DEVICE_REV;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device.satadev_addr = *saddr;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * We have to exit mutex, because the HBA probe port function may
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * block on its own mutex.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang rval = (*SATA_PROBE_PORT_FUNC(sata_hba_inst))
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (SATA_DIP(sata_hba_inst), &sata_device);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_update_pmport_info(sata_hba_inst, &sata_device);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (rval != SATA_SUCCESS) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Something went wrong? Fail the port */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo->pmport_state = SATA_PSTATE_FAILED;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sdinfo = SATA_PMPORT_DRV_INFO(sata_hba_inst, saddr->cport,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang saddr->pmport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (sdinfo != NULL)
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sdinfo->satadrv_event_flags = 0;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_LOG_D((sata_hba_inst, CE_WARN,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "SATA port %d:%d probing failed",
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang saddr->cport, saddr->pmport));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang return;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if ((sata_device.satadev_scr.sstatus &
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_PORT_DEVLINK_UP_MASK) !=
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_PORT_DEVLINK_UP ||
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device.satadev_type == SATA_DTYPE_NONE) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * No device to process, anymore. Some other event processing
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * would or have already performed port info cleanup.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * To be safe (HBA may need it), request clearing device
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * reset condition.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sdinfo = SATA_PMPORT_DRV_INFO(sata_hba_inst, saddr->cport,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang saddr->pmport);
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw if (sdinfo != NULL) {
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw sdinfo->satadrv_event_flags &=
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw ~SATA_EVNT_INPROC_DEVICE_RESET;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* must clear flags on cport */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pminfo = SATA_PMULT_INFO(sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang saddr->cport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pminfo->pmult_event_flags |=
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw SATA_EVNT_CLEAR_DEVICE_RESET;
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return;
c03acfcad7780db4ddf763511a82026680b3b2c1ls }
c03acfcad7780db4ddf763511a82026680b3b2c1ls
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sdinfo = SATA_PMPORT_DRV_INFO(sata_hba_inst, saddr->cport,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang saddr->pmport);
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw if (sdinfo == NULL) {
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw return;
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw }
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw if ((sdinfo->satadrv_event_flags &
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw SATA_EVNT_INPROC_DEVICE_RESET) == 0) {
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw /*
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw * Start tracking time for device feature restoration and
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw * identification. Save current time (lbolt value).
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw */
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw sdinfo->satadrv_reset_time = ddi_get_lbolt();
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Mark device reset processing as active */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdinfo->satadrv_event_flags |= SATA_EVNT_INPROC_DEVICE_RESET;
c03acfcad7780db4ddf763511a82026680b3b2c1ls
2038334ab26baaa43c9083f35def041511c3cc1fUnknown old_sdinfo = *sdinfo; /* local copy of the drive info */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&pmportinfo->pmport_mutex);
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (sata_set_drive_features(sata_hba_inst, &old_sdinfo, 1) ==
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_FAILURE) {
c03acfcad7780db4ddf763511a82026680b3b2c1ls /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Restoring drive setting failed.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Probe the port first, to check if the port state has changed
c03acfcad7780db4ddf763511a82026680b3b2c1ls */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_device.satadev_rev = SATA_DEVICE_REV;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_device.satadev_addr = *saddr;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device.satadev_addr.qual = SATA_ADDR_PMPORT;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* probe port */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang rval = (*SATA_PROBE_PORT_FUNC(sata_hba_inst))
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (SATA_DIP(sata_hba_inst), &sata_device);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (rval == SATA_SUCCESS &&
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (sata_device.satadev_state &
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (SATA_PSTATE_SHUTDOWN | SATA_PSTATE_FAILED)) == 0 &&
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (sata_device.satadev_scr.sstatus &
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_PORT_DEVLINK_UP_MASK) == SATA_PORT_DEVLINK_UP &&
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_device.satadev_type != SATA_DTYPE_NONE) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * We may retry this a bit later - in-process reset
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * condition should be already set.
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw * Track retry time for device identification.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if ((pmportinfo->pmport_dev_type &
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_VALID_DEV_TYPE) != 0 &&
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_PMPORTINFO_DRV_INFO(pmportinfo) != NULL &&
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw sdinfo->satadrv_reset_time != 0) {
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw clock_t cur_time = ddi_get_lbolt();
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw /*
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw * If the retry time limit was not
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw * exceeded, retry.
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw */
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw if ((cur_time - sdinfo->satadrv_reset_time) <
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw drv_usectohz(SATA_DEV_REPROBE_TIMEOUT)) {
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw mutex_enter(
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw &sata_hba_inst->satahba_mutex);
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw sata_hba_inst->satahba_event_flags |=
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw SATA_EVNT_MAIN;
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw mutex_exit(
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw &sata_hba_inst->satahba_mutex);
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw mutex_enter(&sata_mutex);
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw sata_event_pending |= SATA_EVNT_MAIN;
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw mutex_exit(&sata_mutex);
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw return;
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw /* Fail the drive */
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw sdinfo->satadrv_state = SATA_DSTATE_FAILED;
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw sata_log(sata_hba_inst, CE_WARN,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "SATA device at port %d:%d - device failed",
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang saddr->cport, saddr->pmport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang } else {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * No point of retrying - some other event processing
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * would or already did port info cleanup.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * To be safe (HBA may need it),
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * request clearing device reset condition.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sdinfo->satadrv_event_flags |=
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_EVNT_CLEAR_DEVICE_RESET;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sdinfo->satadrv_event_flags &= ~SATA_EVNT_INPROC_DEVICE_RESET;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sdinfo->satadrv_reset_time = 0;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang return;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Raise the flag indicating that the next sata command could
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * be sent with SATA_CLEAR_DEV_RESET_STATE flag, if no new device
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * reset is reported.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (SATA_PMPORTINFO_DRV_INFO(pmportinfo) != NULL) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sdinfo->satadrv_reset_time = 0;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (pmportinfo->pmport_dev_type & SATA_VALID_DEV_TYPE) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sdinfo = SATA_PMPORTINFO_DRV_INFO(pmportinfo);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sdinfo->satadrv_event_flags &=
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang ~SATA_EVNT_INPROC_DEVICE_RESET;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* must clear flags on cport */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pminfo = SATA_PMULT_INFO(sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang saddr->cport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pminfo->pmult_event_flags |=
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_EVNT_CLEAR_DEVICE_RESET;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang}
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang/*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Port Link Events processing.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Every link established event may involve device reset (due to
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * COMRESET signal, equivalent of the hard reset) so arbitrarily
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * set device reset event for an attached device (if any).
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * If the port is in SHUTDOWN or FAILED state, ignore link events.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang *
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * The link established event processing varies, depending on the state
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * of the target node, HBA hotplugging capabilities, state of the port.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * If the link is not active, the link established event is ignored.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * If HBA cannot detect device attachment and there is no target node,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * the link established event triggers device attach event processing.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Else, link established event triggers device reset event processing.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang *
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * The link lost event processing varies, depending on a HBA hotplugging
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * capability and the state of the port (link active or not active).
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * If the link is active, the lost link event is ignored.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * If HBA cannot detect device removal, the lost link event triggers
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * device detached event processing after link lost timeout.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Else, the event is ignored.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang *
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * NOTE: Port multiplier ports events are handled by
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * sata_process_pmport_link_events();
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhangstatic void
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhangsata_process_port_link_events(sata_hba_inst_t *sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_address_t *saddr)
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang{
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device_t sata_device;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_cport_info_t *cportinfo;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_drive_info_t *sdinfo;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang uint32_t event_flags;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang int rval;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATADBG1(SATA_DBG_EVENTS_PROC, sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "Processing port %d link event(s)", saddr->cport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cportinfo = SATA_CPORT_INFO(sata_hba_inst, saddr->cport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang event_flags = cportinfo->cport_event_flags;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Reset event flags first */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cportinfo->cport_event_flags &=
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang ~(SATA_EVNT_LINK_ESTABLISHED | SATA_EVNT_LINK_LOST);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* If the port is in SHUTDOWN or FAILED state, ignore link events. */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if ((cportinfo->cport_state &
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (SATA_PSTATE_SHUTDOWN | SATA_PSTATE_FAILED)) != 0) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang return;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * For the sanity sake get current port state.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Set device address only. Other sata_device fields should be
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * set by HBA driver.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device.satadev_rev = SATA_DEVICE_REV;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device.satadev_addr = *saddr;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * We have to exit mutex, because the HBA probe port function may
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * block on its own mutex.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang rval = (*SATA_PROBE_PORT_FUNC(sata_hba_inst))
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (SATA_DIP(sata_hba_inst), &sata_device);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_update_port_info(sata_hba_inst, &sata_device);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (rval != SATA_SUCCESS) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Something went wrong? Fail the port */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cportinfo->cport_state = SATA_PSTATE_FAILED;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_LOG_D((sata_hba_inst, CE_WARN,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "SATA port %d probing failed",
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang saddr->cport));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * We may want to release device info structure, but
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * it is not necessary.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang return;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang } else {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* port probed successfully */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cportinfo->cport_state |= SATA_STATE_PROBED | SATA_STATE_READY;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (event_flags & SATA_EVNT_LINK_ESTABLISHED) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if ((sata_device.satadev_scr.sstatus &
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_PORT_DEVLINK_UP_MASK) != SATA_PORT_DEVLINK_UP) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Ignore event */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATADBG1(SATA_DBG_EVENTS_PROC, sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "Ignoring port %d link established event - "
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "link down",
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang saddr->cport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang goto linklost;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATADBG1(SATA_DBG_EVENTS_PROC, sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "Processing port %d link established event",
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang saddr->cport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * For the sanity sake check if a device is attached - check
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * return state of a port probing.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (sata_device.satadev_type != SATA_DTYPE_NONE) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * HBA port probe indicated that there is a device
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * attached. Check if the framework had device info
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * structure attached for this device.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (cportinfo->cport_dev_type != SATA_DTYPE_NONE) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang ASSERT(SATA_CPORTINFO_DRV_INFO(cportinfo) !=
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang NULL);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sdinfo = SATA_CPORTINFO_DRV_INFO(cportinfo);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if ((sdinfo->satadrv_type &
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_VALID_DEV_TYPE) != 0) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Dev info structure is present.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * If dev_type is set to known type in
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * the framework's drive info struct
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * then the device existed before and
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * the link was probably lost
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * momentarily - in such case
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * we may want to check device
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * identity.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Identity check is not supported now.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang *
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Link established event
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * triggers device reset event.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (SATA_CPORTINFO_DRV_INFO(cportinfo))->
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang satadrv_event_flags |=
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_EVNT_DEVICE_RESET;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang } else if (cportinfo->cport_dev_type ==
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_DTYPE_NONE) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * We got new device attached! If HBA does not
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * generate device attached events, trigger it
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * here.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (!(SATA_FEATURES(sata_hba_inst) &
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_CTLF_HOTPLUG)) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cportinfo->cport_event_flags |=
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_EVNT_DEVICE_ATTACHED;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Reset link lost timeout */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cportinfo->cport_link_lost_time = 0;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhanglinklost:
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (event_flags & SATA_EVNT_LINK_LOST) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if ((sata_device.satadev_scr.sstatus &
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_PORT_DEVLINK_UP_MASK) == SATA_PORT_DEVLINK_UP) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Ignore event */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATADBG1(SATA_DBG_EVENTS_PROC, sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "Ignoring port %d link lost event - link is up",
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang saddr->cport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang goto done;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang#ifdef SATA_DEBUG
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (cportinfo->cport_link_lost_time == 0) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATADBG1(SATA_DBG_EVENTS_PROC, sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "Processing port %d link lost event",
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw saddr->cport);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang#endif
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * When HBA cannot generate device attached/detached events,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * we need to track link lost time and eventually generate
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * device detach event.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (!(SATA_FEATURES(sata_hba_inst) & SATA_CTLF_HOTPLUG)) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* We are tracking link lost time */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (cportinfo->cport_link_lost_time == 0) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* save current time (lbolt value) */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cportinfo->cport_link_lost_time =
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang ddi_get_lbolt();
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* just keep link lost event */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cportinfo->cport_event_flags |=
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_EVNT_LINK_LOST;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang } else {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang clock_t cur_time = ddi_get_lbolt();
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if ((cur_time -
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cportinfo->cport_link_lost_time) >=
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang drv_usectohz(
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_EVNT_LINK_LOST_TIMEOUT)) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* trigger device detach event */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cportinfo->cport_event_flags |=
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_EVNT_DEVICE_DETACHED;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cportinfo->cport_link_lost_time = 0;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATADBG1(SATA_DBG_EVENTS,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "Triggering port %d "
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "device detached event",
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang saddr->cport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang } else {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* keep link lost event */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cportinfo->cport_event_flags |=
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_EVNT_LINK_LOST;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * We could change port state to disable/delay access to
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * the attached device until the link is recovered.
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcikdone:
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang event_flags = cportinfo->cport_event_flags;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (event_flags != 0) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&sata_hba_inst->satahba_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_hba_inst->satahba_event_flags |= SATA_EVNT_MAIN;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&sata_hba_inst->satahba_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&sata_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_event_pending |= SATA_EVNT_MAIN;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&sata_mutex);
c03acfcad7780db4ddf763511a82026680b3b2c1ls }
c03acfcad7780db4ddf763511a82026680b3b2c1ls}
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls/*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Port Multiplier Port Link Events processing.
c03acfcad7780db4ddf763511a82026680b3b2c1ls */
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic void
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhangsata_process_pmport_link_events(sata_hba_inst_t *sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_address_t *saddr)
c03acfcad7780db4ddf763511a82026680b3b2c1ls{
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_device_t sata_device;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_pmport_info_t *pmportinfo = NULL;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_drive_info_t *sdinfo = NULL;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown uint32_t event_flags;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang uint8_t cport = saddr->cport;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang uint8_t pmport = saddr->pmport;
c03acfcad7780db4ddf763511a82026680b3b2c1ls int rval;
c03acfcad7780db4ddf763511a82026680b3b2c1ls
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATADBG2(SATA_DBG_EVENTS_PROC, sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "Processing port %d:%d link event(s)",
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cport, pmport);
c03acfcad7780db4ddf763511a82026680b3b2c1ls
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo = SATA_PMPORT_INFO(sata_hba_inst, cport, pmport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang event_flags = pmportinfo->pmport_event_flags;
c03acfcad7780db4ddf763511a82026680b3b2c1ls
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Reset event flags first */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo->pmport_event_flags &=
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ~(SATA_EVNT_LINK_ESTABLISHED | SATA_EVNT_LINK_LOST);
c03acfcad7780db4ddf763511a82026680b3b2c1ls
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* If the port is in SHUTDOWN or FAILED state, ignore link events. */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if ((pmportinfo->pmport_state &
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (SATA_PSTATE_SHUTDOWN | SATA_PSTATE_FAILED)) != 0) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&pmportinfo->pmport_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * For the sanity sake get current port state.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Set device address only. Other sata_device fields should be
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * set by HBA driver.
c03acfcad7780db4ddf763511a82026680b3b2c1ls */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_device.satadev_rev = SATA_DEVICE_REV;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_device.satadev_addr = *saddr;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * We have to exit mutex, because the HBA probe port function may
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * block on its own mutex.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&SATA_PMPORT_MUTEX(sata_hba_inst, saddr->cport,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang saddr->pmport));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rval = (*SATA_PROBE_PORT_FUNC(sata_hba_inst))
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (SATA_DIP(sata_hba_inst), &sata_device);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&SATA_PMPORT_MUTEX(sata_hba_inst, saddr->cport,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang saddr->pmport));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_update_pmport_info(sata_hba_inst, &sata_device);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (rval != SATA_SUCCESS) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Something went wrong? Fail the port */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo->pmport_state = SATA_PSTATE_FAILED;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&SATA_PMPORT_MUTEX(sata_hba_inst, saddr->cport,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang saddr->pmport));
c03acfcad7780db4ddf763511a82026680b3b2c1ls SATA_LOG_D((sata_hba_inst, CE_WARN,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "SATA port %d:%d probing failed",
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang saddr->cport, saddr->pmport));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * We may want to release device info structure, but
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * it is not necessary.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown } else {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* port probed successfully */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo->pmport_state |=
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_STATE_PROBED | SATA_STATE_READY;
c03acfcad7780db4ddf763511a82026680b3b2c1ls }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&SATA_PMPORT_MUTEX(sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang saddr->cport, saddr->pmport));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&SATA_PMPORT_MUTEX(sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang saddr->cport, saddr->pmport));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (event_flags & SATA_EVNT_LINK_ESTABLISHED) {
c03acfcad7780db4ddf763511a82026680b3b2c1ls
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if ((sata_device.satadev_scr.sstatus &
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_PORT_DEVLINK_UP_MASK) != SATA_PORT_DEVLINK_UP) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Ignore event */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATADBG2(SATA_DBG_EVENTS_PROC, sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "Ignoring port %d:%d link established event - "
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "link down",
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang saddr->cport, saddr->pmport);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown goto linklost;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
c03acfcad7780db4ddf763511a82026680b3b2c1ls
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATADBG2(SATA_DBG_EVENTS_PROC, sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "Processing port %d:%d link established event",
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cport, pmport);
489f952b4388bd1ea1feff97164a4416e0c621eals
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * For the sanity sake check if a device is attached - check
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * return state of a port probing.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sata_device.satadev_type != SATA_DTYPE_NONE &&
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_device.satadev_type != SATA_DTYPE_PMULT) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * HBA port probe indicated that there is a device
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * attached. Check if the framework had device info
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * structure attached for this device.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (pmportinfo->pmport_dev_type != SATA_DTYPE_NONE) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang ASSERT(SATA_PMPORTINFO_DRV_INFO(pmportinfo) !=
2038334ab26baaa43c9083f35def041511c3cc1fUnknown NULL);
489f952b4388bd1ea1feff97164a4416e0c621eals
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sdinfo = SATA_PMPORTINFO_DRV_INFO(pmportinfo);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if ((sdinfo->satadrv_type &
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_VALID_DEV_TYPE) != 0) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Dev info structure is present.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * If dev_type is set to known type in
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * the framework's drive info struct
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * then the device existed before and
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * the link was probably lost
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * momentarily - in such case
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * we may want to check device
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * identity.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Identity check is not supported now.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown *
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Link established event
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * triggers device reset event.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (SATA_PMPORTINFO_DRV_INFO(pmportinfo))->
2038334ab26baaa43c9083f35def041511c3cc1fUnknown satadrv_event_flags |=
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_EVNT_DEVICE_RESET;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang } else if (pmportinfo->pmport_dev_type ==
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_DTYPE_NONE) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * We got new device attached! If HBA does not
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * generate device attached events, trigger it
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * here.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (!(SATA_FEATURES(sata_hba_inst) &
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_CTLF_HOTPLUG)) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo->pmport_event_flags |=
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_EVNT_DEVICE_ATTACHED;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Reset link lost timeout */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo->pmport_link_lost_time = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknownlinklost:
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (event_flags & SATA_EVNT_LINK_LOST) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang#ifdef SATA_DEBUG
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (pmportinfo->pmport_link_lost_time == 0) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATADBG2(SATA_DBG_EVENTS_PROC, sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "Processing port %d:%d link lost event",
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang saddr->cport, saddr->pmport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang#endif
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if ((sata_device.satadev_scr.sstatus &
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_PORT_DEVLINK_UP_MASK) == SATA_PORT_DEVLINK_UP) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Ignore event */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATADBG2(SATA_DBG_EVENTS_PROC, sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "Ignoring port %d:%d link lost event - link is up",
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang saddr->cport, saddr->pmport);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown goto done;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * When HBA cannot generate device attached/detached events,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * we need to track link lost time and eventually generate
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * device detach event.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (!(SATA_FEATURES(sata_hba_inst) & SATA_CTLF_HOTPLUG)) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* We are tracking link lost time */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (pmportinfo->pmport_link_lost_time == 0) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* save current time (lbolt value) */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo->pmport_link_lost_time =
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ddi_get_lbolt();
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* just keep link lost event */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo->pmport_event_flags |=
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_EVNT_LINK_LOST;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown } else {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown clock_t cur_time = ddi_get_lbolt();
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if ((cur_time -
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo->pmport_link_lost_time) >=
2038334ab26baaa43c9083f35def041511c3cc1fUnknown drv_usectohz(
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_EVNT_LINK_LOST_TIMEOUT)) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* trigger device detach event */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo->pmport_event_flags |=
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_EVNT_DEVICE_DETACHED;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo->pmport_link_lost_time = 0;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATADBG2(SATA_DBG_EVENTS,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "Triggering port %d:%d "
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "device detached event",
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang saddr->cport, saddr->pmport);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown } else {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* keep link lost event */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo->pmport_event_flags |=
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_EVNT_LINK_LOST;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
c03acfcad7780db4ddf763511a82026680b3b2c1ls /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * We could change port state to disable/delay access to
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * the attached device until the link is recovered.
c03acfcad7780db4ddf763511a82026680b3b2c1ls */
c03acfcad7780db4ddf763511a82026680b3b2c1ls }
2038334ab26baaa43c9083f35def041511c3cc1fUnknowndone:
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang event_flags = pmportinfo->pmport_event_flags;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&SATA_PMPORT_MUTEX(sata_hba_inst, saddr->cport,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang saddr->pmport));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (event_flags != 0) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_enter(&sata_hba_inst->satahba_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_hba_inst->satahba_event_flags |= SATA_EVNT_MAIN;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&sata_hba_inst->satahba_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_enter(&sata_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_event_pending |= SATA_EVNT_MAIN;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&sata_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
c03acfcad7780db4ddf763511a82026680b3b2c1ls}
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls/*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Device Detached Event processing.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Port is probed to find if a device is really gone. If so,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * the device info structure is detached from the SATA port info structure
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * and released.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Port status is updated.
c03acfcad7780db4ddf763511a82026680b3b2c1ls *
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * NOTE: Port multiplier ports events are handled by
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * sata_process_pmdevice_detached()
c03acfcad7780db4ddf763511a82026680b3b2c1ls */
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic void
2038334ab26baaa43c9083f35def041511c3cc1fUnknownsata_process_device_detached(sata_hba_inst_t *sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_address_t *saddr)
c03acfcad7780db4ddf763511a82026680b3b2c1ls{
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_cport_info_t *cportinfo;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_pmport_info_t *pmportinfo;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_drive_info_t *sdevinfo;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_device_t sata_device;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_address_t pmport_addr;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang char name[16];
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang uint8_t cport = saddr->cport;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang int npmport;
c03acfcad7780db4ddf763511a82026680b3b2c1ls int rval;
c03acfcad7780db4ddf763511a82026680b3b2c1ls
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATADBG1(SATA_DBG_EVENTS_PROC, sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "Processing port %d device detached", saddr->cport);
c03acfcad7780db4ddf763511a82026680b3b2c1ls
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cportinfo = SATA_CPORT_INFO(sata_hba_inst, saddr->cport);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_enter(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->cport_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Clear event flag */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cportinfo->cport_event_flags &= ~SATA_EVNT_DEVICE_DETACHED;
c03acfcad7780db4ddf763511a82026680b3b2c1ls
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* If the port is in SHUTDOWN or FAILED state, ignore detach event. */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if ((cportinfo->cport_state &
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (SATA_PSTATE_SHUTDOWN | SATA_PSTATE_FAILED)) != 0) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cport_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* For sanity, re-probe the port */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_device.satadev_rev = SATA_DEVICE_REV;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_device.satadev_addr = *saddr;
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * We have to exit mutex, because the HBA probe port function may
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * block on its own mutex.
c03acfcad7780db4ddf763511a82026680b3b2c1ls */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->cport_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rval = (*SATA_PROBE_PORT_FUNC(sata_hba_inst))
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (SATA_DIP(sata_hba_inst), &sata_device);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_enter(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->cport_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_update_port_info(sata_hba_inst, &sata_device);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (rval != SATA_SUCCESS) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Something went wrong? Fail the port */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cportinfo->cport_state = SATA_PSTATE_FAILED;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cport_mutex);
c03acfcad7780db4ddf763511a82026680b3b2c1ls SATA_LOG_D((sata_hba_inst, CE_WARN,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "SATA port %d probing failed",
2038334ab26baaa43c9083f35def041511c3cc1fUnknown saddr->cport));
c03acfcad7780db4ddf763511a82026680b3b2c1ls /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * We may want to release device info structure, but
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * it is not necessary.
c03acfcad7780db4ddf763511a82026680b3b2c1ls */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return;
c03acfcad7780db4ddf763511a82026680b3b2c1ls } else {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* port probed successfully */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cportinfo->cport_state |= SATA_STATE_PROBED | SATA_STATE_READY;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Check if a device is still attached. For sanity, check also
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * link status - if no link, there is no device.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if ((sata_device.satadev_scr.sstatus & SATA_PORT_DEVLINK_UP_MASK) ==
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_PORT_DEVLINK_UP && sata_device.satadev_type !=
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_DTYPE_NONE) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Device is still attached - ignore detach event.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cport_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATADBG1(SATA_DBG_EVENTS_PROC, sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "Ignoring detach - device still attached to port %d",
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_device.satadev_addr.cport);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * We need to detach and release device info structure here
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (cportinfo->cport_dev_type == SATA_DTYPE_PMULT) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * A port-multiplier is removed.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang *
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Calling sata_process_pmdevice_detached() does not work
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * here. The port multiplier is gone, so we cannot probe
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * sub-port any more and all pmult-related data structure must
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * be de-allocated immediately. Following structure of every
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * implemented sub-port behind the pmult are required to
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * released.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang *
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * - attachment point
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * - target node
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * - sata_drive_info
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * - sata_pmport_info
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang for (npmport = 0; npmport < SATA_NUM_PMPORTS(sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cport); npmport ++) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATADBG2(SATA_DBG_PMULT|SATA_DBG_EVENTS_PROC,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "Detaching target node at port %d:%d",
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cport, npmport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&SATA_CPORT_MUTEX(sata_hba_inst, cport));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Remove attachment point. */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang name[0] = '\0';
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (void) sprintf(name, "%d.%d", cport, npmport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang ddi_remove_minor_node(SATA_DIP(sata_hba_inst), name);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_log(sata_hba_inst, CE_NOTE,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "Remove attachment point of port %d:%d",
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cport, npmport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Remove target node */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmport_addr.cport = cport;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmport_addr.pmport = (uint8_t)npmport;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmport_addr.qual = SATA_ADDR_PMPORT;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_remove_target_node(sata_hba_inst, &pmport_addr);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&SATA_CPORT_MUTEX(sata_hba_inst, cport));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Release sata_pmport_info & sata_drive_info. */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo = SATA_PMPORT_INFO(sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cport, npmport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang ASSERT(pmportinfo != NULL);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sdevinfo = SATA_PMPORTINFO_DRV_INFO(pmportinfo);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (sdevinfo != NULL) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (void) kmem_free((void *) sdevinfo,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sizeof (sata_drive_info_t));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Release sata_pmport_info at last */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (void) kmem_free((void *) pmportinfo,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sizeof (sata_pmport_info_t));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Finally, release sata_pmult_info */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (void) kmem_free((void *)
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_CPORTINFO_PMULT_INFO(cportinfo),
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sizeof (sata_pmult_info_t));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_CPORTINFO_PMULT_INFO(cportinfo) = NULL;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_log(sata_hba_inst, CE_WARN,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "SATA port-multiplier detached at port %d", cport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cportinfo->cport_dev_type = SATA_DTYPE_NONE;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&SATA_CPORT_INFO(sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang saddr->cport)->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang } else {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (SATA_CPORTINFO_DRV_INFO(cportinfo) != NULL) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sdevinfo = SATA_CPORTINFO_DRV_INFO(cportinfo);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_CPORTINFO_DRV_INFO(cportinfo) = NULL;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (void) kmem_free((void *)sdevinfo,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sizeof (sata_drive_info_t));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_log(sata_hba_inst, CE_WARN,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "SATA device detached at port %d", cport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cportinfo->cport_dev_type = SATA_DTYPE_NONE;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&SATA_CPORT_INFO(sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang saddr->cport)->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Try to offline a device and remove target node
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * if it still exists
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_remove_target_node(sata_hba_inst, saddr);
c03acfcad7780db4ddf763511a82026680b3b2c1ls }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Generate sysevent - EC_DR / ESC_DR_AP_STATE_CHANGE
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * with the hint: SE_HINT_REMOVE
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_gen_sysevent(sata_hba_inst, saddr, SE_HINT_REMOVE);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang}
c03acfcad7780db4ddf763511a82026680b3b2c1ls
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang/*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Port Multiplier Port Device Deattached Event processing.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang *
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * NOTE: No Mutex should be hold.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhangstatic void
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhangsata_process_pmdevice_detached(sata_hba_inst_t *sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_address_t *saddr)
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang{
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_pmport_info_t *pmportinfo;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_drive_info_t *sdevinfo;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device_t sata_device;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang int rval;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang uint8_t cport, pmport;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cport = saddr->cport;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmport = saddr->pmport;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATADBG2(SATA_DBG_EVENTS_PROC, sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "Processing port %d:%d device detached",
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cport, pmport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo = SATA_PMPORT_INFO(sata_hba_inst, cport, pmport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&SATA_PMPORT_MUTEX(sata_hba_inst, cport, pmport));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Clear event flag */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo->pmport_event_flags &= ~SATA_EVNT_DEVICE_DETACHED;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* If the port is in SHUTDOWN or FAILED state, ignore detach event. */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if ((pmportinfo->pmport_state &
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (SATA_PSTATE_SHUTDOWN | SATA_PSTATE_FAILED)) != 0) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&SATA_PMPORT_MUTEX(sata_hba_inst, cport, pmport));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang return;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* For sanity, re-probe the port */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device.satadev_rev = SATA_DEVICE_REV;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device.satadev_addr = *saddr;
c03acfcad7780db4ddf763511a82026680b3b2c1ls
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * We have to exit mutex, because the HBA probe port function may
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * block on its own mutex.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&SATA_PMPORT_MUTEX(sata_hba_inst, cport, pmport));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang rval = (*SATA_PROBE_PORT_FUNC(sata_hba_inst))
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (SATA_DIP(sata_hba_inst), &sata_device);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&SATA_PMPORT_MUTEX(sata_hba_inst, cport, pmport));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_update_pmport_info(sata_hba_inst, &sata_device);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (rval != SATA_SUCCESS) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Something went wrong? Fail the port */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo->pmport_state = SATA_PSTATE_FAILED;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&SATA_PMPORT_MUTEX(sata_hba_inst, cport, pmport));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_LOG_D((sata_hba_inst, CE_WARN,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "SATA port %d:%d probing failed",
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang saddr->pmport));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * We may want to release device info structure, but
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * it is not necessary.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang return;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang } else {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* port probed successfully */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo->pmport_state |=
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_STATE_PROBED | SATA_STATE_READY;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Check if a device is still attached. For sanity, check also
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * link status - if no link, there is no device.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if ((sata_device.satadev_scr.sstatus & SATA_PORT_DEVLINK_UP_MASK) ==
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_PORT_DEVLINK_UP && sata_device.satadev_type !=
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_DTYPE_NONE) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Device is still attached - ignore detach event.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&SATA_PMPORT_MUTEX(sata_hba_inst, cport, pmport));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATADBG1(SATA_DBG_EVENTS_PROC, sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "Ignoring detach - device still attached to port %d",
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device.satadev_addr.pmport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang return;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * We need to detach and release device info structure here
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (SATA_PMPORTINFO_DRV_INFO(pmportinfo) != NULL) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sdevinfo = SATA_PMPORTINFO_DRV_INFO(pmportinfo);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_PMPORTINFO_DRV_INFO(pmportinfo) = NULL;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (void) kmem_free((void *)sdevinfo,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sizeof (sata_drive_info_t));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo->pmport_dev_type = SATA_DTYPE_NONE;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Device cannot be reached anymore, even if the target node may be
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * still present.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&SATA_PMPORT_MUTEX(sata_hba_inst, cport, pmport));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Try to offline a device and remove target node if it still exists
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_remove_target_node(sata_hba_inst, saddr);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Generate sysevent - EC_DR / ESC_DR_AP_STATE_CHANGE
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * with the hint: SE_HINT_REMOVE
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_gen_sysevent(sata_hba_inst, saddr, SE_HINT_REMOVE);
c03acfcad7780db4ddf763511a82026680b3b2c1ls}
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls/*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Device Attached Event processing.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Port state is checked to verify that a device is really attached. If so,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * the device info structure is created and attached to the SATA port info
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * structure.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown *
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * If attached device cannot be identified or set-up, the retry for the
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * attach processing is set-up. Subsequent daemon run would try again to
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * identify the device, until the time limit is reached
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * (SATA_DEV_IDENTIFY_TIMEOUT).
2038334ab26baaa43c9083f35def041511c3cc1fUnknown *
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * This function cannot be called in interrupt context (it may sleep).
c03acfcad7780db4ddf763511a82026680b3b2c1ls *
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * NOTE: Port multiplier ports events are handled by
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * sata_process_pmdevice_attached()
c03acfcad7780db4ddf763511a82026680b3b2c1ls */
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic void
2038334ab26baaa43c9083f35def041511c3cc1fUnknownsata_process_device_attached(sata_hba_inst_t *sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_address_t *saddr)
c03acfcad7780db4ddf763511a82026680b3b2c1ls{
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_cport_info_t *cportinfo = NULL;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_drive_info_t *sdevinfo = NULL;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_pmult_info_t *pmultinfo = NULL;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_pmport_info_t *pmportinfo = NULL;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_device_t sata_device;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown dev_info_t *tdip;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang uint32_t event_flags = 0, pmult_event_flags = 0;
c03acfcad7780db4ddf763511a82026680b3b2c1ls int rval;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang int npmport;
c03acfcad7780db4ddf763511a82026680b3b2c1ls
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATADBG1(SATA_DBG_EVENTS_PROC, sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "Processing port %d device attached", saddr->cport);
c03acfcad7780db4ddf763511a82026680b3b2c1ls
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cportinfo = SATA_CPORT_INFO(sata_hba_inst, saddr->cport);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_enter(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->cport_mutex);
c03acfcad7780db4ddf763511a82026680b3b2c1ls
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Clear attach event flag first */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cportinfo->cport_event_flags &= ~SATA_EVNT_DEVICE_ATTACHED;
c03acfcad7780db4ddf763511a82026680b3b2c1ls
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* If the port is in SHUTDOWN or FAILED state, ignore event. */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if ((cportinfo->cport_state &
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (SATA_PSTATE_SHUTDOWN | SATA_PSTATE_FAILED)) != 0) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cportinfo->cport_dev_attach_time = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cport_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * If the sata_drive_info structure is found attached to the port info,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * despite the fact the device was removed and now it is re-attached,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * the old drive info structure was not removed.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Arbitrarily release device info structure.
c03acfcad7780db4ddf763511a82026680b3b2c1ls */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (SATA_CPORTINFO_DRV_INFO(cportinfo) != NULL) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sdevinfo = SATA_CPORTINFO_DRV_INFO(cportinfo);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_CPORTINFO_DRV_INFO(cportinfo) = NULL;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (void) kmem_free((void *)sdevinfo,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sizeof (sata_drive_info_t));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATADBG1(SATA_DBG_EVENTS_PROC, sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "Arbitrarily detaching old device info.", NULL);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cportinfo->cport_dev_type = SATA_DTYPE_NONE;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* For sanity, re-probe the port */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_device.satadev_rev = SATA_DEVICE_REV;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_device.satadev_addr = *saddr;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * We have to exit mutex, because the HBA probe port function may
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * block on its own mutex.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->cport_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rval = (*SATA_PROBE_PORT_FUNC(sata_hba_inst))
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (SATA_DIP(sata_hba_inst), &sata_device);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_enter(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->cport_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_update_port_info(sata_hba_inst, &sata_device);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (rval != SATA_SUCCESS) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Something went wrong? Fail the port */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cportinfo->cport_state = SATA_PSTATE_FAILED;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cportinfo->cport_dev_attach_time = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cport_mutex);
c03acfcad7780db4ddf763511a82026680b3b2c1ls SATA_LOG_D((sata_hba_inst, CE_WARN,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "SATA port %d probing failed",
2038334ab26baaa43c9083f35def041511c3cc1fUnknown saddr->cport));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown } else {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* port probed successfully */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cportinfo->cport_state |= SATA_STATE_PROBED | SATA_STATE_READY;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Check if a device is still attached. For sanity, check also
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * link status - if no link, there is no device.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if ((sata_device.satadev_scr.sstatus & SATA_PORT_DEVLINK_UP_MASK) !=
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_PORT_DEVLINK_UP || sata_device.satadev_type ==
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_DTYPE_NONE) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * No device - ignore attach event.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cportinfo->cport_dev_attach_time = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cport_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATADBG1(SATA_DBG_EVENTS_PROC, sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "Ignoring attach - no device connected to port %d",
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_device.satadev_addr.cport);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return;
c03acfcad7780db4ddf763511a82026680b3b2c1ls }
c03acfcad7780db4ddf763511a82026680b3b2c1ls
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->cport_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Generate sysevent - EC_DR / ESC_DR_AP_STATE_CHANGE
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * with the hint: SE_HINT_INSERT
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_gen_sysevent(sata_hba_inst, saddr, SE_HINT_INSERT);
c03acfcad7780db4ddf763511a82026680b3b2c1ls
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Port reprobing will take care of the creation of the device
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * info structure and determination of the device type.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_device.satadev_addr = *saddr;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (void) sata_reprobe_port(sata_hba_inst, &sata_device,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_DEV_IDENTIFY_NORETRY);
489f952b4388bd1ea1feff97164a4416e0c621eals
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_enter(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cport_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if ((cportinfo->cport_state & SATA_STATE_READY) &&
2038334ab26baaa43c9083f35def041511c3cc1fUnknown (cportinfo->cport_dev_type != SATA_DTYPE_NONE)) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Some device is attached to the port */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (cportinfo->cport_dev_type == SATA_DTYPE_UNKNOWN) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * A device was not successfully attached.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Track retry time for device identification.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (cportinfo->cport_dev_attach_time != 0) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown clock_t cur_time = ddi_get_lbolt();
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * If the retry time limit was not exceeded,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * reinstate attach event.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if ((cur_time -
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cportinfo->cport_dev_attach_time) <
2038334ab26baaa43c9083f35def041511c3cc1fUnknown drv_usectohz(
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_DEV_IDENTIFY_TIMEOUT)) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* OK, restore attach event */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cportinfo->cport_event_flags |=
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_EVNT_DEVICE_ATTACHED;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown } else {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Timeout - cannot identify device */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cportinfo->cport_dev_attach_time = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_log(sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown CE_WARN,
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw "Could not identify SATA device "
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw "at port %d",
2038334ab26baaa43c9083f35def041511c3cc1fUnknown saddr->cport);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown } else {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Start tracking time for device
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * identification.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Save current time (lbolt value).
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cportinfo->cport_dev_attach_time =
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ddi_get_lbolt();
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Restore attach event */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cportinfo->cport_event_flags |=
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_EVNT_DEVICE_ATTACHED;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang } else if (cportinfo->cport_dev_type == SATA_DTYPE_PMULT) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cportinfo->cport_dev_attach_time = 0;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_log(sata_hba_inst, CE_NOTE,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "SATA port-multiplier detected at port %d",
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang saddr->cport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (SATA_CPORTINFO_PMULT_INFO(cportinfo) != NULL) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Log the info of new port multiplier */
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang mutex_exit(&SATA_CPORT_INFO(sata_hba_inst,
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang saddr->cport)->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_show_pmult_info(sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang &sata_device);
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang mutex_enter(&SATA_CPORT_INFO(sata_hba_inst,
918304a3bd962ac065ad520336a044d94b40ad16Xiao-Yu Zhang saddr->cport)->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang ASSERT(SATA_CPORTINFO_PMULT_INFO(cportinfo) != NULL);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmultinfo = SATA_CPORTINFO_PMULT_INFO(cportinfo);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang for (npmport = 0; npmport <
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmultinfo->pmult_num_dev_ports; npmport++) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo = SATA_PMPORT_INFO(sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang saddr->cport, npmport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang ASSERT(pmportinfo != NULL);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&SATA_CPORT_INFO(sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang saddr->cport)->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Marked all pmports with link events. */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo->pmport_event_flags =
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_EVNT_LINK_ESTABLISHED;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmult_event_flags |=
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo->pmport_event_flags;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&SATA_CPORT_INFO(sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang saddr->cport)->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Auto-online is not available for PMult now. */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
2038334ab26baaa43c9083f35def041511c3cc1fUnknown } else {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
c75976d12071ddd21443266260066ba036671682pawelw * If device was successfully attached, the subsequent
c75976d12071ddd21443266260066ba036671682pawelw * action depends on a state of the
c75976d12071ddd21443266260066ba036671682pawelw * sata_auto_online variable. If it is set to zero.
c75976d12071ddd21443266260066ba036671682pawelw * an explicit 'configure' command will be needed to
c75976d12071ddd21443266260066ba036671682pawelw * configure it. If its value is non-zero, we will
c75976d12071ddd21443266260066ba036671682pawelw * attempt to online (configure) the device.
c75976d12071ddd21443266260066ba036671682pawelw * First, log the message indicating that a device
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * was attached.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cportinfo->cport_dev_attach_time = 0;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_log(sata_hba_inst, CE_WARN,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "SATA device detected at port %d", saddr->cport);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (SATA_CPORTINFO_DRV_INFO(cportinfo) != NULL) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_drive_info_t new_sdinfo;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /* Log device info data */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown new_sdinfo = *(SATA_CPORTINFO_DRV_INFO(
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cportinfo));
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_show_drive_info(sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown &new_sdinfo);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&SATA_CPORT_INFO(sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown saddr->cport)->cport_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Make sure that there is no target node for that
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * device. If so, release it. It should not happen,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * unless we had problem removing the node when
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * device was detached.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown tdip = sata_get_target_dip(SATA_DIP(sata_hba_inst),
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang saddr->cport, saddr->pmport);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_enter(&SATA_CPORT_INFO(sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown saddr->cport)->cport_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (tdip != NULL) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown#ifdef SATA_DEBUG
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if ((cportinfo->cport_event_flags &
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_EVNT_TARGET_NODE_CLEANUP) == 0)
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_log(sata_hba_inst, CE_WARN,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "sata_process_device_attached: "
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "old device target node exists!");
2038334ab26baaa43c9083f35def041511c3cc1fUnknown#endif
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * target node exists - try to unconfigure
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * device and remove the node.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&SATA_CPORT_INFO(sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown saddr->cport)->cport_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown rval = ndi_devi_offline(tdip,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown NDI_DEVI_REMOVE);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_enter(&SATA_CPORT_INFO(sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown saddr->cport)->cport_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (rval == NDI_SUCCESS) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cportinfo->cport_event_flags &=
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ~SATA_EVNT_TARGET_NODE_CLEANUP;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cportinfo->cport_tgtnode_clean = B_TRUE;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown } else {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * PROBLEM - the target node remained
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * and it belongs to a previously
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * attached device.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * This happens when the file was open
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * or the node was waiting for
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * resources at the time the
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * associated device was removed.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Instruct event daemon to retry the
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * cleanup later.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_log(sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown CE_WARN,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "Application(s) accessing "
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "previously attached SATA "
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "device have to release "
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "it before newly inserted "
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "device can be made accessible.",
2038334ab26baaa43c9083f35def041511c3cc1fUnknown saddr->cport);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cportinfo->cport_event_flags |=
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATA_EVNT_TARGET_NODE_CLEANUP;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cportinfo->cport_tgtnode_clean =
2038334ab26baaa43c9083f35def041511c3cc1fUnknown B_FALSE;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
c75976d12071ddd21443266260066ba036671682pawelw if (sata_auto_online != 0) {
c75976d12071ddd21443266260066ba036671682pawelw cportinfo->cport_event_flags |=
c75976d12071ddd21443266260066ba036671682pawelw SATA_EVNT_AUTOONLINE_DEVICE;
c75976d12071ddd21443266260066ba036671682pawelw }
489f952b4388bd1ea1feff97164a4416e0c621eals
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
c03acfcad7780db4ddf763511a82026680b3b2c1ls } else {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cportinfo->cport_dev_attach_time = 0;
c03acfcad7780db4ddf763511a82026680b3b2c1ls }
c03acfcad7780db4ddf763511a82026680b3b2c1ls
2038334ab26baaa43c9083f35def041511c3cc1fUnknown event_flags = cportinfo->cport_event_flags;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (event_flags != 0 || pmult_event_flags != 0) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_enter(&sata_hba_inst->satahba_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_hba_inst->satahba_event_flags |= SATA_EVNT_MAIN;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&sata_hba_inst->satahba_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_enter(&sata_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_event_pending |= SATA_EVNT_MAIN;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&sata_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
c03acfcad7780db4ddf763511a82026680b3b2c1ls}
c03acfcad7780db4ddf763511a82026680b3b2c1ls
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang/*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Port Multiplier Port Device Attached Event processing.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang *
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * NOTE: No Mutex should be hold.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhangstatic void
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhangsata_process_pmdevice_attached(sata_hba_inst_t *sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_address_t *saddr)
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang{
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_pmport_info_t *pmportinfo;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_drive_info_t *sdinfo;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device_t sata_device;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang dev_info_t *tdip;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang uint32_t event_flags;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang uint8_t cport = saddr->cport;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang uint8_t pmport = saddr->pmport;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang int rval;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATADBG2(SATA_DBG_EVENTS_PROC, sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "Processing port %d:%d device attached", cport, pmport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo = SATA_PMPORT_INFO(sata_hba_inst, cport, pmport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Clear attach event flag first */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo->pmport_event_flags &= ~SATA_EVNT_DEVICE_ATTACHED;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* If the port is in SHUTDOWN or FAILED state, ignore event. */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if ((pmportinfo->pmport_state &
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (SATA_PSTATE_SHUTDOWN | SATA_PSTATE_FAILED)) != 0) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo->pmport_dev_attach_time = 0;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang return;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * If the sata_drive_info structure is found attached to the port info,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * despite the fact the device was removed and now it is re-attached,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * the old drive info structure was not removed.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Arbitrarily release device info structure.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (SATA_PMPORTINFO_DRV_INFO(pmportinfo) != NULL) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sdinfo = SATA_PMPORTINFO_DRV_INFO(pmportinfo);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_PMPORTINFO_DRV_INFO(pmportinfo) = NULL;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (void) kmem_free((void *)sdinfo,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sizeof (sata_drive_info_t));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATADBG1(SATA_DBG_EVENTS_PROC, sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "Arbitrarily detaching old device info.", NULL);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo->pmport_dev_type = SATA_DTYPE_NONE;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* For sanity, re-probe the port */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device.satadev_rev = SATA_DEVICE_REV;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device.satadev_addr = *saddr;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * We have to exit mutex, because the HBA probe port function may
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * block on its own mutex.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang rval = (*SATA_PROBE_PORT_FUNC(sata_hba_inst))
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (SATA_DIP(sata_hba_inst), &sata_device);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_update_pmport_info(sata_hba_inst, &sata_device);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (rval != SATA_SUCCESS) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Something went wrong? Fail the port */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo->pmport_state = SATA_PSTATE_FAILED;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo->pmport_dev_attach_time = 0;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_LOG_D((sata_hba_inst, CE_WARN,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "SATA port %d:%d probing failed", cport, pmport));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang return;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang } else {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* pmport probed successfully */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo->pmport_state |=
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_STATE_PROBED | SATA_STATE_READY;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Check if a device is still attached. For sanity, check also
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * link status - if no link, there is no device.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if ((sata_device.satadev_scr.sstatus & SATA_PORT_DEVLINK_UP_MASK) !=
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_PORT_DEVLINK_UP || sata_device.satadev_type ==
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_DTYPE_NONE) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * No device - ignore attach event.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo->pmport_dev_attach_time = 0;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATADBG2(SATA_DBG_EVENTS_PROC, sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "Ignoring attach - no device connected to port %d:%d",
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cport, pmport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang return;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Generate sysevent - EC_DR / ESC_DR_AP_STATE_CHANGE
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * with the hint: SE_HINT_INSERT
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_gen_sysevent(sata_hba_inst, saddr, SE_HINT_INSERT);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Port reprobing will take care of the creation of the device
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * info structure and determination of the device type.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_device.satadev_addr = *saddr;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (void) sata_reprobe_port(sata_hba_inst, &sata_device,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_DEV_IDENTIFY_NORETRY);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if ((pmportinfo->pmport_state & SATA_STATE_READY) &&
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (pmportinfo->pmport_dev_type != SATA_DTYPE_NONE)) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Some device is attached to the port */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (pmportinfo->pmport_dev_type == SATA_DTYPE_UNKNOWN) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * A device was not successfully attached.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Track retry time for device identification.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (pmportinfo->pmport_dev_attach_time != 0) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang clock_t cur_time = ddi_get_lbolt();
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * If the retry time limit was not exceeded,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * reinstate attach event.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if ((cur_time -
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo->pmport_dev_attach_time) <
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang drv_usectohz(
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_DEV_IDENTIFY_TIMEOUT)) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* OK, restore attach event */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo->pmport_event_flags |=
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_EVNT_DEVICE_ATTACHED;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang } else {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Timeout - cannot identify device */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo->pmport_dev_attach_time = 0;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_log(sata_hba_inst, CE_WARN,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "Could not identify SATA device "
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "at port %d:%d",
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cport, pmport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang } else {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Start tracking time for device
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * identification.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Save current time (lbolt value).
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo->pmport_dev_attach_time =
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang ddi_get_lbolt();
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Restore attach event */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo->pmport_event_flags |=
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_EVNT_DEVICE_ATTACHED;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang } else {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * If device was successfully attached, the subsequent
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * action depends on a state of the
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * sata_auto_online variable. If it is set to zero.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * an explicit 'configure' command will be needed to
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * configure it. If its value is non-zero, we will
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * attempt to online (configure) the device.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * First, log the message indicating that a device
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * was attached.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo->pmport_dev_attach_time = 0;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_log(sata_hba_inst, CE_WARN,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "SATA device detected at port %d:%d",
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cport, pmport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (SATA_PMPORTINFO_DRV_INFO(pmportinfo) != NULL) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_drive_info_t new_sdinfo;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Log device info data */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang new_sdinfo = *(SATA_PMPORTINFO_DRV_INFO(
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo));
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_show_drive_info(sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang &new_sdinfo);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Make sure that there is no target node for that
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * device. If so, release it. It should not happen,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * unless we had problem removing the node when
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * device was detached.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang tdip = sata_get_target_dip(SATA_DIP(sata_hba_inst),
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang saddr->cport, saddr->pmport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (tdip != NULL) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang#ifdef SATA_DEBUG
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if ((pmportinfo->pmport_event_flags &
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_EVNT_TARGET_NODE_CLEANUP) == 0)
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_log(sata_hba_inst, CE_WARN,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "sata_process_device_attached: "
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "old device target node exists!");
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang#endif
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * target node exists - try to unconfigure
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * device and remove the node.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang rval = ndi_devi_offline(tdip,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang NDI_DEVI_REMOVE);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (rval == NDI_SUCCESS) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo->pmport_event_flags &=
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang ~SATA_EVNT_TARGET_NODE_CLEANUP;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo->pmport_tgtnode_clean =
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang B_TRUE;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang } else {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /*
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * PROBLEM - the target node remained
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * and it belongs to a previously
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * attached device.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * This happens when the file was open
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * or the node was waiting for
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * resources at the time the
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * associated device was removed.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Instruct event daemon to retry the
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * cleanup later.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_log(sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang CE_WARN,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "Application(s) accessing "
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "previously attached SATA "
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "device have to release "
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "it before newly inserted "
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "device can be made accessible."
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "at port %d:%d",
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cport, pmport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo->pmport_event_flags |=
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_EVNT_TARGET_NODE_CLEANUP;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo->pmport_tgtnode_clean =
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang B_FALSE;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (sata_auto_online != 0) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo->pmport_event_flags |=
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_EVNT_AUTOONLINE_DEVICE;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang } else {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmportinfo->pmport_dev_attach_time = 0;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang event_flags = pmportinfo->pmport_event_flags;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&pmportinfo->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (event_flags != 0) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&sata_hba_inst->satahba_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_hba_inst->satahba_event_flags |= SATA_EVNT_MAIN;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&sata_hba_inst->satahba_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&sata_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_event_pending |= SATA_EVNT_MAIN;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&sata_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* clear the reset_in_progress events */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (SATA_PMPORTINFO_DRV_INFO(pmportinfo) != NULL) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (pmportinfo->pmport_dev_type & SATA_VALID_DEV_TYPE) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* must clear flags on cport */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sata_pmult_info_t *pminfo =
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_PMULT_INFO(sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang saddr->cport);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pminfo->pmult_event_flags |=
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_EVNT_CLEAR_DEVICE_RESET;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang}
2038334ab26baaa43c9083f35def041511c3cc1fUnknown
c03acfcad7780db4ddf763511a82026680b3b2c1ls/*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Device Target Node Cleanup Event processing.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * If the target node associated with a sata port device is in
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * DEVI_DEVICE_REMOVED state, an attempt is made to remove it.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * If the target node cannot be removed, the event flag is left intact,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * so that event daemon may re-run this function later.
c03acfcad7780db4ddf763511a82026680b3b2c1ls *
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * This function cannot be called in interrupt context (it may sleep).
c03acfcad7780db4ddf763511a82026680b3b2c1ls *
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * NOTE: Processes cport events only, not port multiplier ports.
c03acfcad7780db4ddf763511a82026680b3b2c1ls */
2038334ab26baaa43c9083f35def041511c3cc1fUnknownstatic void
2038334ab26baaa43c9083f35def041511c3cc1fUnknownsata_process_target_node_cleanup(sata_hba_inst_t *sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_address_t *saddr)
c03acfcad7780db4ddf763511a82026680b3b2c1ls{
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_cport_info_t *cportinfo;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown dev_info_t *tdip;
c03acfcad7780db4ddf763511a82026680b3b2c1ls
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATADBG1(SATA_DBG_EVENTS_PROC, sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "Processing port %d device target node cleanup", saddr->cport);
c03acfcad7780db4ddf763511a82026680b3b2c1ls
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cportinfo = SATA_CPORT_INFO(sata_hba_inst, saddr->cport);
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Check if there is target node for that device and it is in the
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * DEVI_DEVICE_REMOVED state. If so, release it.
c03acfcad7780db4ddf763511a82026680b3b2c1ls */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang tdip = sata_get_target_dip(SATA_DIP(sata_hba_inst), saddr->cport,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang saddr->pmport);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (tdip != NULL) {
c03acfcad7780db4ddf763511a82026680b3b2c1ls /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * target node exists - check if it is target node of
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * a removed device.
c03acfcad7780db4ddf763511a82026680b3b2c1ls */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (sata_check_device_removed(tdip) == B_TRUE) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown SATADBG1(SATA_DBG_EVENTS_PROC, sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "sata_process_target_node_cleanup: "
2038334ab26baaa43c9083f35def041511c3cc1fUnknown "old device target node exists!", NULL);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Unconfigure and remove the target node
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown if (ndi_devi_offline(tdip, NDI_DEVI_REMOVE) ==
2038334ab26baaa43c9083f35def041511c3cc1fUnknown NDI_SUCCESS) {
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_enter(&SATA_CPORT_INFO(sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown saddr->cport)->cport_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown cportinfo->cport_event_flags &=
2038334ab26baaa43c9083f35def041511c3cc1fUnknown ~SATA_EVNT_TARGET_NODE_CLEANUP;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&SATA_CPORT_INFO(sata_hba_inst,
2038334ab26baaa43c9083f35def041511c3cc1fUnknown saddr->cport)->cport_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown return;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
2038334ab26baaa43c9083f35def041511c3cc1fUnknown /*
2038334ab26baaa43c9083f35def041511c3cc1fUnknown * Event daemon will retry the cleanup later.
2038334ab26baaa43c9083f35def041511c3cc1fUnknown */
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_enter(&sata_hba_inst->satahba_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_hba_inst->satahba_event_flags |= SATA_EVNT_MAIN;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&sata_hba_inst->satahba_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_enter(&sata_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown sata_event_pending |= SATA_EVNT_MAIN;
2038334ab26baaa43c9083f35def041511c3cc1fUnknown mutex_exit(&sata_mutex);
2038334ab26baaa43c9083f35def041511c3cc1fUnknown }
c03acfcad7780db4ddf763511a82026680b3b2c1ls } else {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (saddr->qual == SATA_ADDR_CPORT ||
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang saddr->qual == SATA_ADDR_DCPORT) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&SATA_CPORT_INFO(sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang saddr->cport)->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cportinfo->cport_event_flags &=
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang ~SATA_EVNT_TARGET_NODE_CLEANUP;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&SATA_CPORT_INFO(sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang saddr->cport)->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang } else {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* sanity check */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (SATA_CPORT_DEV_TYPE(sata_hba_inst, saddr->cport) !=
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_DTYPE_PMULT || SATA_PMULT_INFO(sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang saddr->cport) == NULL)
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang return;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (SATA_PMPORT_INFO(sata_hba_inst, saddr->cport,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang saddr->pmport) == NULL)
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang return;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&SATA_PMPORT_INFO(sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang saddr->cport, saddr->pmport)->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_PMPORT_INFO(sata_hba_inst, saddr->cport,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang saddr->pmport)->pmport_event_flags &=
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang ~SATA_EVNT_TARGET_NODE_CLEANUP;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&SATA_PMPORT_INFO(sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang saddr->cport, saddr->pmport)->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
c03acfcad7780db4ddf763511a82026680b3b2c1ls }
c03acfcad7780db4ddf763511a82026680b3b2c1ls}
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c75976d12071ddd21443266260066ba036671682pawelw/*
c75976d12071ddd21443266260066ba036671682pawelw * Device AutoOnline Event processing.
c75976d12071ddd21443266260066ba036671682pawelw * If attached device is to be onlined, an attempt is made to online this
c75976d12071ddd21443266260066ba036671682pawelw * device, but only if there is no lingering (old) target node present.
c75976d12071ddd21443266260066ba036671682pawelw * If the device cannot be onlined, the event flag is left intact,
c75976d12071ddd21443266260066ba036671682pawelw * so that event daemon may re-run this function later.
c75976d12071ddd21443266260066ba036671682pawelw *
c75976d12071ddd21443266260066ba036671682pawelw * This function cannot be called in interrupt context (it may sleep).
c75976d12071ddd21443266260066ba036671682pawelw *
c75976d12071ddd21443266260066ba036671682pawelw * NOTE: Processes cport events only, not port multiplier ports.
c75976d12071ddd21443266260066ba036671682pawelw */
c75976d12071ddd21443266260066ba036671682pawelwstatic void
c75976d12071ddd21443266260066ba036671682pawelwsata_process_device_autoonline(sata_hba_inst_t *sata_hba_inst,
c75976d12071ddd21443266260066ba036671682pawelw sata_address_t *saddr)
c75976d12071ddd21443266260066ba036671682pawelw{
c75976d12071ddd21443266260066ba036671682pawelw sata_cport_info_t *cportinfo;
c75976d12071ddd21443266260066ba036671682pawelw sata_drive_info_t *sdinfo;
c75976d12071ddd21443266260066ba036671682pawelw sata_device_t sata_device;
c75976d12071ddd21443266260066ba036671682pawelw dev_info_t *tdip;
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw SATADBG1(SATA_DBG_EVENTS_PROC, sata_hba_inst,
c75976d12071ddd21443266260066ba036671682pawelw "Processing port %d attached device auto-onlining", saddr->cport);
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw cportinfo = SATA_CPORT_INFO(sata_hba_inst, saddr->cport);
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw /*
c75976d12071ddd21443266260066ba036671682pawelw * Check if device is present and recognized. If not, reset event.
c75976d12071ddd21443266260066ba036671682pawelw */
c75976d12071ddd21443266260066ba036671682pawelw mutex_enter(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->cport_mutex);
c75976d12071ddd21443266260066ba036671682pawelw if ((cportinfo->cport_dev_type & SATA_VALID_DEV_TYPE) == 0) {
c75976d12071ddd21443266260066ba036671682pawelw /* Nothing to online */
c75976d12071ddd21443266260066ba036671682pawelw cportinfo->cport_event_flags &= ~SATA_EVNT_AUTOONLINE_DEVICE;
c75976d12071ddd21443266260066ba036671682pawelw mutex_exit(&SATA_CPORT_INFO(sata_hba_inst,
c75976d12071ddd21443266260066ba036671682pawelw saddr->cport)->cport_mutex);
c75976d12071ddd21443266260066ba036671682pawelw return;
c75976d12071ddd21443266260066ba036671682pawelw }
c75976d12071ddd21443266260066ba036671682pawelw mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->cport_mutex);
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw /*
c75976d12071ddd21443266260066ba036671682pawelw * Check if there is target node for this device and if it is in the
c75976d12071ddd21443266260066ba036671682pawelw * DEVI_DEVICE_REMOVED state. If so, abort onlining but keep
c75976d12071ddd21443266260066ba036671682pawelw * the event for later processing.
c75976d12071ddd21443266260066ba036671682pawelw */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang tdip = sata_get_target_dip(SATA_DIP(sata_hba_inst), saddr->cport,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang saddr->pmport);
c75976d12071ddd21443266260066ba036671682pawelw if (tdip != NULL) {
c75976d12071ddd21443266260066ba036671682pawelw /*
c75976d12071ddd21443266260066ba036671682pawelw * target node exists - check if it is target node of
c75976d12071ddd21443266260066ba036671682pawelw * a removed device.
c75976d12071ddd21443266260066ba036671682pawelw */
c75976d12071ddd21443266260066ba036671682pawelw if (sata_check_device_removed(tdip) == B_TRUE) {
c75976d12071ddd21443266260066ba036671682pawelw SATADBG1(SATA_DBG_EVENTS_PROC, sata_hba_inst,
c75976d12071ddd21443266260066ba036671682pawelw "sata_process_device_autoonline: "
c75976d12071ddd21443266260066ba036671682pawelw "old device target node exists!", NULL);
c75976d12071ddd21443266260066ba036671682pawelw /*
c75976d12071ddd21443266260066ba036671682pawelw * Event daemon will retry device onlining later.
c75976d12071ddd21443266260066ba036671682pawelw */
c75976d12071ddd21443266260066ba036671682pawelw mutex_enter(&sata_hba_inst->satahba_mutex);
c75976d12071ddd21443266260066ba036671682pawelw sata_hba_inst->satahba_event_flags |= SATA_EVNT_MAIN;
c75976d12071ddd21443266260066ba036671682pawelw mutex_exit(&sata_hba_inst->satahba_mutex);
c75976d12071ddd21443266260066ba036671682pawelw mutex_enter(&sata_mutex);
c75976d12071ddd21443266260066ba036671682pawelw sata_event_pending |= SATA_EVNT_MAIN;
c75976d12071ddd21443266260066ba036671682pawelw mutex_exit(&sata_mutex);
c75976d12071ddd21443266260066ba036671682pawelw return;
c75976d12071ddd21443266260066ba036671682pawelw }
c75976d12071ddd21443266260066ba036671682pawelw /*
c75976d12071ddd21443266260066ba036671682pawelw * If the target node is not in the 'removed" state, assume
c75976d12071ddd21443266260066ba036671682pawelw * that it belongs to this device. There is nothing more to do,
c75976d12071ddd21443266260066ba036671682pawelw * but reset the event.
c75976d12071ddd21443266260066ba036671682pawelw */
c75976d12071ddd21443266260066ba036671682pawelw } else {
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw /*
c75976d12071ddd21443266260066ba036671682pawelw * Try to online the device
c75976d12071ddd21443266260066ba036671682pawelw * If there is any reset-related event, remove it. We are
c75976d12071ddd21443266260066ba036671682pawelw * configuring the device and no state restoring is needed.
c75976d12071ddd21443266260066ba036671682pawelw */
c75976d12071ddd21443266260066ba036671682pawelw mutex_enter(&SATA_CPORT_INFO(sata_hba_inst,
c75976d12071ddd21443266260066ba036671682pawelw saddr->cport)->cport_mutex);
c75976d12071ddd21443266260066ba036671682pawelw sata_device.satadev_addr = *saddr;
c75976d12071ddd21443266260066ba036671682pawelw if (saddr->qual == SATA_ADDR_CPORT)
c75976d12071ddd21443266260066ba036671682pawelw sata_device.satadev_addr.qual = SATA_ADDR_DCPORT;
c75976d12071ddd21443266260066ba036671682pawelw else
c75976d12071ddd21443266260066ba036671682pawelw sata_device.satadev_addr.qual = SATA_ADDR_DPMPORT;
c75976d12071ddd21443266260066ba036671682pawelw sdinfo = sata_get_device_info(sata_hba_inst, &sata_device);
c75976d12071ddd21443266260066ba036671682pawelw if (sdinfo != NULL) {
c75976d12071ddd21443266260066ba036671682pawelw if (sdinfo->satadrv_event_flags &
c75976d12071ddd21443266260066ba036671682pawelw (SATA_EVNT_DEVICE_RESET |
c75976d12071ddd21443266260066ba036671682pawelw SATA_EVNT_INPROC_DEVICE_RESET))
c75976d12071ddd21443266260066ba036671682pawelw sdinfo->satadrv_event_flags = 0;
c75976d12071ddd21443266260066ba036671682pawelw sdinfo->satadrv_event_flags |=
c75976d12071ddd21443266260066ba036671682pawelw SATA_EVNT_CLEAR_DEVICE_RESET;
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw /* Need to create a new target node. */
c75976d12071ddd21443266260066ba036671682pawelw cportinfo->cport_tgtnode_clean = B_TRUE;
c75976d12071ddd21443266260066ba036671682pawelw mutex_exit(&SATA_CPORT_INFO(sata_hba_inst,
c75976d12071ddd21443266260066ba036671682pawelw saddr->cport)->cport_mutex);
c75976d12071ddd21443266260066ba036671682pawelw tdip = sata_create_target_node(SATA_DIP(sata_hba_inst),
c75976d12071ddd21443266260066ba036671682pawelw sata_hba_inst, &sata_device.satadev_addr);
c75976d12071ddd21443266260066ba036671682pawelw if (tdip == NULL) {
c75976d12071ddd21443266260066ba036671682pawelw /*
c75976d12071ddd21443266260066ba036671682pawelw * Configure (onlining) failed.
c75976d12071ddd21443266260066ba036671682pawelw * We will NOT retry
c75976d12071ddd21443266260066ba036671682pawelw */
c75976d12071ddd21443266260066ba036671682pawelw SATA_LOG_D((sata_hba_inst, CE_WARN,
c75976d12071ddd21443266260066ba036671682pawelw "sata_process_device_autoonline: "
c75976d12071ddd21443266260066ba036671682pawelw "configuring SATA device at port %d failed",
c75976d12071ddd21443266260066ba036671682pawelw saddr->cport));
c75976d12071ddd21443266260066ba036671682pawelw }
c75976d12071ddd21443266260066ba036671682pawelw } else {
c75976d12071ddd21443266260066ba036671682pawelw mutex_exit(&SATA_CPORT_INFO(sata_hba_inst,
c75976d12071ddd21443266260066ba036671682pawelw saddr->cport)->cport_mutex);
c75976d12071ddd21443266260066ba036671682pawelw }
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw }
c75976d12071ddd21443266260066ba036671682pawelw mutex_enter(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->cport_mutex);
c75976d12071ddd21443266260066ba036671682pawelw cportinfo->cport_event_flags &= ~SATA_EVNT_AUTOONLINE_DEVICE;
c75976d12071ddd21443266260066ba036671682pawelw mutex_exit(&SATA_CPORT_INFO(sata_hba_inst,
c75976d12071ddd21443266260066ba036671682pawelw saddr->cport)->cport_mutex);
c75976d12071ddd21443266260066ba036671682pawelw}
c75976d12071ddd21443266260066ba036671682pawelw
c75976d12071ddd21443266260066ba036671682pawelw
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelwstatic void
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelwsata_gen_sysevent(sata_hba_inst_t *sata_hba_inst, sata_address_t *saddr,
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw int hint)
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw{
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw char ap[MAXPATHLEN];
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw nvlist_t *ev_attr_list = NULL;
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw int err;
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw /* Allocate and build sysevent attribute list */
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw err = nvlist_alloc(&ev_attr_list, NV_UNIQUE_NAME_TYPE, DDI_NOSLEEP);
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw if (err != 0) {
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw SATA_LOG_D((sata_hba_inst, CE_WARN,
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw "sata_gen_sysevent: "
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw "cannot allocate memory for sysevent attributes\n"));
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw return;
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw }
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw /* Add hint attribute */
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw err = nvlist_add_string(ev_attr_list, DR_HINT, SE_HINT2STR(hint));
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw if (err != 0) {
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw SATA_LOG_D((sata_hba_inst, CE_WARN,
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw "sata_gen_sysevent: "
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw "failed to add DR_HINT attr for sysevent"));
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw nvlist_free(ev_attr_list);
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw return;
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw }
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw /*
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw * Add AP attribute.
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw * Get controller pathname and convert it into AP pathname by adding
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw * a target number.
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw */
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw (void) snprintf(ap, MAXPATHLEN, "/devices");
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw (void) ddi_pathname(SATA_DIP(sata_hba_inst), ap + strlen(ap));
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw (void) snprintf(ap + strlen(ap), MAXPATHLEN - strlen(ap), ":%d",
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw SATA_MAKE_AP_NUMBER(saddr->cport, saddr->pmport, saddr->qual));
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw err = nvlist_add_string(ev_attr_list, DR_AP_ID, ap);
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw if (err != 0) {
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw SATA_LOG_D((sata_hba_inst, CE_WARN,
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw "sata_gen_sysevent: "
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw "failed to add DR_AP_ID attr for sysevent"));
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw nvlist_free(ev_attr_list);
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw return;
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw }
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw /* Generate/log sysevent */
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw err = ddi_log_sysevent(SATA_DIP(sata_hba_inst), DDI_VENDOR_SUNW, EC_DR,
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw ESC_DR_AP_STATE_CHANGE, ev_attr_list, NULL, DDI_NOSLEEP);
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw if (err != DDI_SUCCESS) {
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw SATA_LOG_D((sata_hba_inst, CE_WARN,
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw "sata_gen_sysevent: "
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw "cannot log sysevent, err code %x\n", err));
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw }
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw nvlist_free(ev_attr_list);
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw}
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls
4360436b3c604bc28d37be269ad152b4c38157c3pawelw
4360436b3c604bc28d37be269ad152b4c38157c3pawelw
4360436b3c604bc28d37be269ad152b4c38157c3pawelw
4360436b3c604bc28d37be269ad152b4c38157c3pawelw/*
4360436b3c604bc28d37be269ad152b4c38157c3pawelw * Set DEVI_DEVICE_REMOVED state in the SATA device target node.
4360436b3c604bc28d37be269ad152b4c38157c3pawelw */
4360436b3c604bc28d37be269ad152b4c38157c3pawelwstatic void
4360436b3c604bc28d37be269ad152b4c38157c3pawelwsata_set_device_removed(dev_info_t *tdip)
4360436b3c604bc28d37be269ad152b4c38157c3pawelw{
4360436b3c604bc28d37be269ad152b4c38157c3pawelw int circ;
4360436b3c604bc28d37be269ad152b4c38157c3pawelw
4360436b3c604bc28d37be269ad152b4c38157c3pawelw ASSERT(tdip != NULL);
4360436b3c604bc28d37be269ad152b4c38157c3pawelw
4360436b3c604bc28d37be269ad152b4c38157c3pawelw ndi_devi_enter(tdip, &circ);
4360436b3c604bc28d37be269ad152b4c38157c3pawelw mutex_enter(&DEVI(tdip)->devi_lock);
4360436b3c604bc28d37be269ad152b4c38157c3pawelw DEVI_SET_DEVICE_REMOVED(tdip);
4360436b3c604bc28d37be269ad152b4c38157c3pawelw mutex_exit(&DEVI(tdip)->devi_lock);
4360436b3c604bc28d37be269ad152b4c38157c3pawelw ndi_devi_exit(tdip, circ);
4360436b3c604bc28d37be269ad152b4c38157c3pawelw}
4360436b3c604bc28d37be269ad152b4c38157c3pawelw
4360436b3c604bc28d37be269ad152b4c38157c3pawelw
4360436b3c604bc28d37be269ad152b4c38157c3pawelw/*
4360436b3c604bc28d37be269ad152b4c38157c3pawelw * Set internal event instructing event daemon to try
4360436b3c604bc28d37be269ad152b4c38157c3pawelw * to perform the target node cleanup.
4360436b3c604bc28d37be269ad152b4c38157c3pawelw */
4360436b3c604bc28d37be269ad152b4c38157c3pawelwstatic void
c75976d12071ddd21443266260066ba036671682pawelwsata_set_target_node_cleanup(sata_hba_inst_t *sata_hba_inst,
c75976d12071ddd21443266260066ba036671682pawelw sata_address_t *saddr)
4360436b3c604bc28d37be269ad152b4c38157c3pawelw{
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (saddr->qual == SATA_ADDR_CPORT ||
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang saddr->qual == SATA_ADDR_DCPORT) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&SATA_CPORT_INFO(sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang saddr->cport)->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_CPORT_EVENT_FLAGS(sata_hba_inst, saddr->cport) |=
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_EVNT_TARGET_NODE_CLEANUP;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cport_tgtnode_clean = B_FALSE;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&SATA_CPORT_INFO(sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang saddr->cport)->cport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang } else {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_enter(&SATA_PMPORT_INFO(sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang saddr->cport, saddr->pmport)->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_PMPORT_EVENT_FLAGS(sata_hba_inst, saddr->cport,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang saddr->pmport) |= SATA_EVNT_TARGET_NODE_CLEANUP;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang SATA_PMPORT_INFO(sata_hba_inst, saddr->cport, saddr->pmport)->
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang pmport_tgtnode_clean = B_FALSE;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang mutex_exit(&SATA_PMPORT_INFO(sata_hba_inst,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang saddr->cport, saddr->pmport)->pmport_mutex);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang }
4360436b3c604bc28d37be269ad152b4c38157c3pawelw mutex_enter(&sata_hba_inst->satahba_mutex);
4360436b3c604bc28d37be269ad152b4c38157c3pawelw sata_hba_inst->satahba_event_flags |= SATA_EVNT_MAIN;
4360436b3c604bc28d37be269ad152b4c38157c3pawelw mutex_exit(&sata_hba_inst->satahba_mutex);
4360436b3c604bc28d37be269ad152b4c38157c3pawelw mutex_enter(&sata_mutex);
4360436b3c604bc28d37be269ad152b4c38157c3pawelw sata_event_pending |= SATA_EVNT_MAIN;
4360436b3c604bc28d37be269ad152b4c38157c3pawelw mutex_exit(&sata_mutex);
4360436b3c604bc28d37be269ad152b4c38157c3pawelw}
4360436b3c604bc28d37be269ad152b4c38157c3pawelw
4360436b3c604bc28d37be269ad152b4c38157c3pawelw
4360436b3c604bc28d37be269ad152b4c38157c3pawelw/*
4360436b3c604bc28d37be269ad152b4c38157c3pawelw * Check if the SATA device target node is in DEVI_DEVICE_REMOVED state,
4360436b3c604bc28d37be269ad152b4c38157c3pawelw * i.e. check if the target node state indicates that it belongs to a removed
4360436b3c604bc28d37be269ad152b4c38157c3pawelw * device.
4360436b3c604bc28d37be269ad152b4c38157c3pawelw *
4360436b3c604bc28d37be269ad152b4c38157c3pawelw * Returns B_TRUE if the target node is in DEVI_DEVICE_REMOVED state,
4360436b3c604bc28d37be269ad152b4c38157c3pawelw * B_FALSE otherwise.
4360436b3c604bc28d37be269ad152b4c38157c3pawelw */
4360436b3c604bc28d37be269ad152b4c38157c3pawelwstatic boolean_t
4360436b3c604bc28d37be269ad152b4c38157c3pawelwsata_check_device_removed(dev_info_t *tdip)
4360436b3c604bc28d37be269ad152b4c38157c3pawelw{
4360436b3c604bc28d37be269ad152b4c38157c3pawelw ASSERT(tdip != NULL);
4360436b3c604bc28d37be269ad152b4c38157c3pawelw
4360436b3c604bc28d37be269ad152b4c38157c3pawelw if (DEVI_IS_DEVICE_REMOVED(tdip))
4360436b3c604bc28d37be269ad152b4c38157c3pawelw return (B_TRUE);
4360436b3c604bc28d37be269ad152b4c38157c3pawelw else
4360436b3c604bc28d37be269ad152b4c38157c3pawelw return (B_FALSE);
4360436b3c604bc28d37be269ad152b4c38157c3pawelw}
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw/* ************************ FAULT INJECTTION **************************** */
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw#ifdef SATA_INJECT_FAULTS
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelwstatic uint32_t sata_fault_count = 0;
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelwstatic uint32_t sata_fault_suspend_count = 0;
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw/*
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw * Inject sata pkt fault
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw * It modifies returned values of the sata packet.
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik * It returns immediately if:
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik * pkt fault injection is not enabled (via sata_inject_fault,
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik * sata_inject_fault_count), or invalid fault is specified (sata_fault_type),
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik * or pkt does not contain command to be faulted (set in sata_fault_cmd), or
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik * pkt is not directed to specified fault controller/device
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik * (sata_fault_ctrl_dev and sata_fault_device).
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik * If fault controller is not specified, fault injection applies to all
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik * controllers and devices.
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik *
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw * First argument is the pointer to the executed sata packet.
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik * Second argument is a pointer to a value returned by the HBA tran_start
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw * function.
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik * Third argument specifies injected error. Injected sata packet faults
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw * are the satapkt_reason values.
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw * SATA_PKT_BUSY -1 Not completed, busy
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw * SATA_PKT_DEV_ERROR 1 Device reported error
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw * SATA_PKT_QUEUE_FULL 2 Not accepted, queue full
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw * SATA_PKT_PORT_ERROR 3 Not completed, port error
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw * SATA_PKT_CMD_UNSUPPORTED 4 Cmd unsupported
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw * SATA_PKT_ABORTED 5 Aborted by request
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw * SATA_PKT_TIMEOUT 6 Operation timeut
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw * SATA_PKT_RESET 7 Aborted by reset request
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw *
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik * Additional global variables affecting the execution:
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik *
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw * sata_inject_fault_count variable specifies number of times in row the
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw * error is injected. Value of -1 specifies permanent fault, ie. every time
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik * the fault injection point is reached, the fault is injected and a pause
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw * between fault injection specified by sata_inject_fault_pause_count is
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik * ignored). Fault injection routine decrements sata_inject_fault_count
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik * (if greater than zero) until it reaches 0. No fault is injected when
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik * sata_inject_fault_count is 0 (zero).
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw *
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw * sata_inject_fault_pause_count variable specifies number of times a fault
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw * injection is bypassed (pause between fault injections).
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw * If set to 0, a fault is injected only a number of times specified by
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw * sata_inject_fault_count.
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw *
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw * The fault counts are static, so for periodic errors they have to be manually
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw * reset to start repetition sequence from scratch.
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw * If the original value returned by the HBA tran_start function is not
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw * SATA_TRAN_ACCEPTED and pkt reason is not SATA_PKT_COMPLETED, no error
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw * is injected (to avoid masking real problems);
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw *
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw * NOTE: In its current incarnation, this function should be invoked only for
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw * commands executed in SYNCHRONOUS mode.
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw */
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw
f5f2d263454d943a366844932bdb677530ba733bFred Herardstatic void
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojciksata_inject_pkt_fault(sata_pkt_t *spkt, int *rval, int fault)
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw{
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik if (sata_inject_fault != SATA_INJECT_PKT_FAULT)
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw return;
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw if (sata_inject_fault_count == 0)
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw return;
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik if (fault == 0)
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik return;
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik if (sata_fault_cmd != spkt->satapkt_cmd.satacmd_cmd_reg)
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw return;
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik if (sata_fault_ctrl != NULL) {
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik sata_pkt_txlate_t *spx =
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik (sata_pkt_txlate_t *)spkt->satapkt_framework_private;
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik if (sata_fault_ctrl != NULL && sata_fault_ctrl !=
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik spx->txlt_sata_hba_inst->satahba_dip)
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik return;
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik if (sata_fault_device.satadev_addr.cport !=
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik spkt->satapkt_device.satadev_addr.cport ||
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik sata_fault_device.satadev_addr.pmport !=
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik spkt->satapkt_device.satadev_addr.pmport ||
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik sata_fault_device.satadev_addr.qual !=
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik spkt->satapkt_device.satadev_addr.qual)
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik return;
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik }
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik
1777a9b4600e4d6a49ee55688c79459805f22aaaPawel Wojcik /* Modify pkt return parameters */
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw if (*rval != SATA_TRAN_ACCEPTED ||
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw spkt->satapkt_reason != SATA_PKT_COMPLETED) {
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw sata_fault_count = 0;
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw sata_fault_suspend_count = 0;
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw return;
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw }
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw if (sata_fault_count == 0 && sata_fault_suspend_count != 0) {
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw /* Pause in the injection */
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw sata_fault_suspend_count -= 1;
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw return;
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw }
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw if (sata_fault_count == 0 && sata_fault_suspend_count == 0) {
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw /*
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw * Init inject fault cycle. If fault count is set to -1,
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw * it is a permanent fault.
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw */
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw if (sata_inject_fault_count != -1) {
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw sata_fault_count = sata_inject_fault_count;
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw sata_fault_suspend_count =
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw sata_inject_fault_pause_count;
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw if (sata_fault_suspend_count == 0)
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw sata_inject_fault_count = 0;
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw }
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw }
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw if (sata_fault_count != 0)
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw sata_fault_count -= 1;
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw switch (fault) {
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw case SATA_PKT_BUSY:
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw *rval = SATA_TRAN_BUSY;
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw spkt->satapkt_reason = SATA_PKT_BUSY;
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw break;
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw case SATA_PKT_QUEUE_FULL:
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw *rval = SATA_TRAN_QUEUE_FULL;
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw spkt->satapkt_reason = SATA_PKT_QUEUE_FULL;
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw break;
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw case SATA_PKT_CMD_UNSUPPORTED:
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw *rval = SATA_TRAN_CMD_UNSUPPORTED;
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw spkt->satapkt_reason = SATA_PKT_CMD_UNSUPPORTED;
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw break;
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw case SATA_PKT_PORT_ERROR:
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw /* This is "rejected" command */
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw *rval = SATA_TRAN_PORT_ERROR;
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw spkt->satapkt_reason = SATA_PKT_PORT_ERROR;
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw /* Additional error setup could be done here - port state */
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw break;
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw case SATA_PKT_DEV_ERROR:
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw spkt->satapkt_reason = SATA_PKT_DEV_ERROR;
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw /*
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw * Additional error setup could be done here
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw */
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw break;
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw case SATA_PKT_ABORTED:
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw spkt->satapkt_reason = SATA_PKT_ABORTED;
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw break;
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw case SATA_PKT_TIMEOUT:
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw spkt->satapkt_reason = SATA_PKT_TIMEOUT;
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw /* Additional error setup could be done here */
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw break;
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw case SATA_PKT_RESET:
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw spkt->satapkt_reason = SATA_PKT_RESET;
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw /*
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw * Additional error setup could be done here - device reset
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw */
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw break;
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw default:
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw break;
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw }
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw}
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw
4372d277de71fc7c19cb9f41df9b8757b34e2cc5pawelw#endif
f5f2d263454d943a366844932bdb677530ba733bFred Herard
f5f2d263454d943a366844932bdb677530ba733bFred Herard/*
f5f2d263454d943a366844932bdb677530ba733bFred Herard * SATA Trace Ring Buffer
f5f2d263454d943a366844932bdb677530ba733bFred Herard * ----------------------
f5f2d263454d943a366844932bdb677530ba733bFred Herard *
f5f2d263454d943a366844932bdb677530ba733bFred Herard * Overview
f5f2d263454d943a366844932bdb677530ba733bFred Herard *
f5f2d263454d943a366844932bdb677530ba733bFred Herard * The SATA trace ring buffer is a ring buffer created and managed by
f5f2d263454d943a366844932bdb677530ba733bFred Herard * the SATA framework module that can be used by any module or driver
f5f2d263454d943a366844932bdb677530ba733bFred Herard * within the SATA framework to store debug messages.
f5f2d263454d943a366844932bdb677530ba733bFred Herard *
f5f2d263454d943a366844932bdb677530ba733bFred Herard * Ring Buffer Interfaces:
f5f2d263454d943a366844932bdb677530ba733bFred Herard *
f5f2d263454d943a366844932bdb677530ba733bFred Herard * sata_vtrace_debug() <-- Adds debug message to ring buffer
f5f2d263454d943a366844932bdb677530ba733bFred Herard * sata_trace_debug() <-- Wraps varargs into sata_vtrace_debug()
f5f2d263454d943a366844932bdb677530ba733bFred Herard *
f5f2d263454d943a366844932bdb677530ba733bFred Herard * Note that the sata_trace_debug() interface was created to give
f5f2d263454d943a366844932bdb677530ba733bFred Herard * consumers the flexibilty of sending debug messages to ring buffer
f5f2d263454d943a366844932bdb677530ba733bFred Herard * as variable arguments. Consumers can send type va_list debug
f5f2d263454d943a366844932bdb677530ba733bFred Herard * messages directly to sata_vtrace_debug(). The sata_trace_debug()
f5f2d263454d943a366844932bdb677530ba733bFred Herard * and sata_vtrace_debug() relationship is similar to that of
f5f2d263454d943a366844932bdb677530ba733bFred Herard * cmn_err(9F) and vcmn_err(9F).
f5f2d263454d943a366844932bdb677530ba733bFred Herard *
f5f2d263454d943a366844932bdb677530ba733bFred Herard * Below is a diagram of the SATA trace ring buffer interfaces and
f5f2d263454d943a366844932bdb677530ba733bFred Herard * sample consumers:
f5f2d263454d943a366844932bdb677530ba733bFred Herard *
f5f2d263454d943a366844932bdb677530ba733bFred Herard * +---------------------------------+
f5f2d263454d943a366844932bdb677530ba733bFred Herard * | o o SATA Framework Module |
f5f2d263454d943a366844932bdb677530ba733bFred Herard * | o SATA o +------------------+ +------------------+
f5f2d263454d943a366844932bdb677530ba733bFred Herard * |o Trace o <--|sata_vtrace_debug/|<-----|SATA HBA Driver #1|
f5f2d263454d943a366844932bdb677530ba733bFred Herard * |o R-Buf o |sata_trace_debug |<--+ +------------------+
f5f2d263454d943a366844932bdb677530ba733bFred Herard * | o o +------------------+ | +------------------+
f5f2d263454d943a366844932bdb677530ba733bFred Herard * | o o ^ | +--|SATA HBA Driver #2|
f5f2d263454d943a366844932bdb677530ba733bFred Herard * | | | +------------------+
f5f2d263454d943a366844932bdb677530ba733bFred Herard * | +------------------+ |
f5f2d263454d943a366844932bdb677530ba733bFred Herard * | |SATA Debug Message| |
f5f2d263454d943a366844932bdb677530ba733bFred Herard * | +------------------+ |
f5f2d263454d943a366844932bdb677530ba733bFred Herard * +---------------------------------+
f5f2d263454d943a366844932bdb677530ba733bFred Herard *
f5f2d263454d943a366844932bdb677530ba733bFred Herard * Supporting Routines:
f5f2d263454d943a366844932bdb677530ba733bFred Herard *
f5f2d263454d943a366844932bdb677530ba733bFred Herard * sata_trace_rbuf_alloc() <-- Initializes ring buffer
f5f2d263454d943a366844932bdb677530ba733bFred Herard * sata_trace_rbuf_free() <-- Destroys ring buffer
f5f2d263454d943a366844932bdb677530ba733bFred Herard * sata_trace_dmsg_alloc() <-- Creates or reuses buffer in ring buffer
f5f2d263454d943a366844932bdb677530ba733bFred Herard * sata_trace_dmsg_free() <-- Destroys content of ring buffer
f5f2d263454d943a366844932bdb677530ba733bFred Herard *
f5f2d263454d943a366844932bdb677530ba733bFred Herard * The default SATA trace ring buffer size is defined by DMSG_RING_SIZE.
f5f2d263454d943a366844932bdb677530ba733bFred Herard * The ring buffer size can be adjusted by setting dmsg_ring_size in
f5f2d263454d943a366844932bdb677530ba733bFred Herard * /etc/system to desired size in unit of bytes.
f5f2d263454d943a366844932bdb677530ba733bFred Herard *
f5f2d263454d943a366844932bdb677530ba733bFred Herard * The individual debug message size in the ring buffer is restricted
f5f2d263454d943a366844932bdb677530ba733bFred Herard * to DMSG_BUF_SIZE.
f5f2d263454d943a366844932bdb677530ba733bFred Herard */
f5f2d263454d943a366844932bdb677530ba733bFred Herardvoid
f5f2d263454d943a366844932bdb677530ba733bFred Herardsata_vtrace_debug(dev_info_t *dip, const char *fmt, va_list ap)
f5f2d263454d943a366844932bdb677530ba733bFred Herard{
f5f2d263454d943a366844932bdb677530ba733bFred Herard sata_trace_dmsg_t *dmsg;
f5f2d263454d943a366844932bdb677530ba733bFred Herard
f5f2d263454d943a366844932bdb677530ba733bFred Herard if (sata_debug_rbuf == NULL) {
f5f2d263454d943a366844932bdb677530ba733bFred Herard return;
f5f2d263454d943a366844932bdb677530ba733bFred Herard }
f5f2d263454d943a366844932bdb677530ba733bFred Herard
f5f2d263454d943a366844932bdb677530ba733bFred Herard /*
f5f2d263454d943a366844932bdb677530ba733bFred Herard * If max size of ring buffer is smaller than size
f5f2d263454d943a366844932bdb677530ba733bFred Herard * required for one debug message then just return
f5f2d263454d943a366844932bdb677530ba733bFred Herard * since we have no room for the debug message.
f5f2d263454d943a366844932bdb677530ba733bFred Herard */
f5f2d263454d943a366844932bdb677530ba733bFred Herard if (sata_debug_rbuf->maxsize < (sizeof (sata_trace_dmsg_t))) {
f5f2d263454d943a366844932bdb677530ba733bFred Herard return;
f5f2d263454d943a366844932bdb677530ba733bFred Herard }
f5f2d263454d943a366844932bdb677530ba733bFred Herard
f5f2d263454d943a366844932bdb677530ba733bFred Herard mutex_enter(&sata_debug_rbuf->lock);
f5f2d263454d943a366844932bdb677530ba733bFred Herard
f5f2d263454d943a366844932bdb677530ba733bFred Herard /* alloc or reuse on ring buffer */
f5f2d263454d943a366844932bdb677530ba733bFred Herard dmsg = sata_trace_dmsg_alloc();
f5f2d263454d943a366844932bdb677530ba733bFred Herard
f5f2d263454d943a366844932bdb677530ba733bFred Herard if (dmsg == NULL) {
f5f2d263454d943a366844932bdb677530ba733bFred Herard /* resource allocation failed */
f5f2d263454d943a366844932bdb677530ba733bFred Herard mutex_exit(&sata_debug_rbuf->lock);
f5f2d263454d943a366844932bdb677530ba733bFred Herard return;
f5f2d263454d943a366844932bdb677530ba733bFred Herard }
f5f2d263454d943a366844932bdb677530ba733bFred Herard
f5f2d263454d943a366844932bdb677530ba733bFred Herard dmsg->dip = dip;
f5f2d263454d943a366844932bdb677530ba733bFred Herard gethrestime(&dmsg->timestamp);
f5f2d263454d943a366844932bdb677530ba733bFred Herard
f5f2d263454d943a366844932bdb677530ba733bFred Herard (void) vsnprintf(dmsg->buf, sizeof (dmsg->buf), fmt, ap);
f5f2d263454d943a366844932bdb677530ba733bFred Herard
f5f2d263454d943a366844932bdb677530ba733bFred Herard mutex_exit(&sata_debug_rbuf->lock);
f5f2d263454d943a366844932bdb677530ba733bFred Herard}
f5f2d263454d943a366844932bdb677530ba733bFred Herard
f5f2d263454d943a366844932bdb677530ba733bFred Herardvoid
f5f2d263454d943a366844932bdb677530ba733bFred Herardsata_trace_debug(dev_info_t *dip, const char *fmt, ...)
f5f2d263454d943a366844932bdb677530ba733bFred Herard{
f5f2d263454d943a366844932bdb677530ba733bFred Herard va_list ap;
f5f2d263454d943a366844932bdb677530ba733bFred Herard
f5f2d263454d943a366844932bdb677530ba733bFred Herard va_start(ap, fmt);
f5f2d263454d943a366844932bdb677530ba733bFred Herard sata_vtrace_debug(dip, fmt, ap);
f5f2d263454d943a366844932bdb677530ba733bFred Herard va_end(ap);
f5f2d263454d943a366844932bdb677530ba733bFred Herard}
f5f2d263454d943a366844932bdb677530ba733bFred Herard
f5f2d263454d943a366844932bdb677530ba733bFred Herard/*
f5f2d263454d943a366844932bdb677530ba733bFred Herard * This routine is used to manage debug messages
f5f2d263454d943a366844932bdb677530ba733bFred Herard * on ring buffer.
f5f2d263454d943a366844932bdb677530ba733bFred Herard */
f5f2d263454d943a366844932bdb677530ba733bFred Herardstatic sata_trace_dmsg_t *
f5f2d263454d943a366844932bdb677530ba733bFred Herardsata_trace_dmsg_alloc(void)
f5f2d263454d943a366844932bdb677530ba733bFred Herard{
f5f2d263454d943a366844932bdb677530ba733bFred Herard sata_trace_dmsg_t *dmsg_alloc, *dmsg = sata_debug_rbuf->dmsgp;
f5f2d263454d943a366844932bdb677530ba733bFred Herard
f5f2d263454d943a366844932bdb677530ba733bFred Herard if (sata_debug_rbuf->looped == TRUE) {
f5f2d263454d943a366844932bdb677530ba733bFred Herard sata_debug_rbuf->dmsgp = dmsg->next;
f5f2d263454d943a366844932bdb677530ba733bFred Herard return (sata_debug_rbuf->dmsgp);
f5f2d263454d943a366844932bdb677530ba733bFred Herard }
f5f2d263454d943a366844932bdb677530ba733bFred Herard
f5f2d263454d943a366844932bdb677530ba733bFred Herard /*
f5f2d263454d943a366844932bdb677530ba733bFred Herard * If we're looping for the first time,
f5f2d263454d943a366844932bdb677530ba733bFred Herard * connect the ring.
f5f2d263454d943a366844932bdb677530ba733bFred Herard */
f5f2d263454d943a366844932bdb677530ba733bFred Herard if (((sata_debug_rbuf->size + (sizeof (sata_trace_dmsg_t))) >
f5f2d263454d943a366844932bdb677530ba733bFred Herard sata_debug_rbuf->maxsize) && (sata_debug_rbuf->dmsgh != NULL)) {
f5f2d263454d943a366844932bdb677530ba733bFred Herard dmsg->next = sata_debug_rbuf->dmsgh;
f5f2d263454d943a366844932bdb677530ba733bFred Herard sata_debug_rbuf->dmsgp = sata_debug_rbuf->dmsgh;
f5f2d263454d943a366844932bdb677530ba733bFred Herard sata_debug_rbuf->looped = TRUE;
f5f2d263454d943a366844932bdb677530ba733bFred Herard return (sata_debug_rbuf->dmsgp);
f5f2d263454d943a366844932bdb677530ba733bFred Herard }
f5f2d263454d943a366844932bdb677530ba733bFred Herard
f5f2d263454d943a366844932bdb677530ba733bFred Herard /* If we've gotten this far then memory allocation is needed */
f5f2d263454d943a366844932bdb677530ba733bFred Herard dmsg_alloc = kmem_zalloc(sizeof (sata_trace_dmsg_t), KM_NOSLEEP);
f5f2d263454d943a366844932bdb677530ba733bFred Herard if (dmsg_alloc == NULL) {
f5f2d263454d943a366844932bdb677530ba733bFred Herard sata_debug_rbuf->allocfailed++;
f5f2d263454d943a366844932bdb677530ba733bFred Herard return (dmsg_alloc);
f5f2d263454d943a366844932bdb677530ba733bFred Herard } else {
f5f2d263454d943a366844932bdb677530ba733bFred Herard sata_debug_rbuf->size += sizeof (sata_trace_dmsg_t);
f5f2d263454d943a366844932bdb677530ba733bFred Herard }
f5f2d263454d943a366844932bdb677530ba733bFred Herard
f5f2d263454d943a366844932bdb677530ba733bFred Herard if (sata_debug_rbuf->dmsgp != NULL) {
f5f2d263454d943a366844932bdb677530ba733bFred Herard dmsg->next = dmsg_alloc;
f5f2d263454d943a366844932bdb677530ba733bFred Herard sata_debug_rbuf->dmsgp = dmsg->next;
f5f2d263454d943a366844932bdb677530ba733bFred Herard return (sata_debug_rbuf->dmsgp);
f5f2d263454d943a366844932bdb677530ba733bFred Herard } else {
f5f2d263454d943a366844932bdb677530ba733bFred Herard /*
f5f2d263454d943a366844932bdb677530ba733bFred Herard * We should only be here if we're initializing
f5f2d263454d943a366844932bdb677530ba733bFred Herard * the ring buffer.
f5f2d263454d943a366844932bdb677530ba733bFred Herard */
f5f2d263454d943a366844932bdb677530ba733bFred Herard if (sata_debug_rbuf->dmsgh == NULL) {
f5f2d263454d943a366844932bdb677530ba733bFred Herard sata_debug_rbuf->dmsgh = dmsg_alloc;
f5f2d263454d943a366844932bdb677530ba733bFred Herard } else {
f5f2d263454d943a366844932bdb677530ba733bFred Herard /* Something is wrong */
f5f2d263454d943a366844932bdb677530ba733bFred Herard kmem_free(dmsg_alloc, sizeof (sata_trace_dmsg_t));
f5f2d263454d943a366844932bdb677530ba733bFred Herard return (NULL);
f5f2d263454d943a366844932bdb677530ba733bFred Herard }
f5f2d263454d943a366844932bdb677530ba733bFred Herard
f5f2d263454d943a366844932bdb677530ba733bFred Herard sata_debug_rbuf->dmsgp = dmsg_alloc;
f5f2d263454d943a366844932bdb677530ba733bFred Herard return (sata_debug_rbuf->dmsgp);
f5f2d263454d943a366844932bdb677530ba733bFred Herard }
f5f2d263454d943a366844932bdb677530ba733bFred Herard}
f5f2d263454d943a366844932bdb677530ba733bFred Herard
f5f2d263454d943a366844932bdb677530ba733bFred Herard
f5f2d263454d943a366844932bdb677530ba733bFred Herard/*
f5f2d263454d943a366844932bdb677530ba733bFred Herard * Free all messages on debug ring buffer.
f5f2d263454d943a366844932bdb677530ba733bFred Herard */
f5f2d263454d943a366844932bdb677530ba733bFred Herardstatic void
f5f2d263454d943a366844932bdb677530ba733bFred Herardsata_trace_dmsg_free(void)
f5f2d263454d943a366844932bdb677530ba733bFred Herard{
f5f2d263454d943a366844932bdb677530ba733bFred Herard sata_trace_dmsg_t *dmsg_next, *dmsg = sata_debug_rbuf->dmsgh;
f5f2d263454d943a366844932bdb677530ba733bFred Herard
f5f2d263454d943a366844932bdb677530ba733bFred Herard while (dmsg != NULL) {
f5f2d263454d943a366844932bdb677530ba733bFred Herard dmsg_next = dmsg->next;
f5f2d263454d943a366844932bdb677530ba733bFred Herard kmem_free(dmsg, sizeof (sata_trace_dmsg_t));
f5f2d263454d943a366844932bdb677530ba733bFred Herard
f5f2d263454d943a366844932bdb677530ba733bFred Herard /*
f5f2d263454d943a366844932bdb677530ba733bFred Herard * If we've looped around the ring than we're done.
f5f2d263454d943a366844932bdb677530ba733bFred Herard */
f5f2d263454d943a366844932bdb677530ba733bFred Herard if (dmsg_next == sata_debug_rbuf->dmsgh) {
f5f2d263454d943a366844932bdb677530ba733bFred Herard break;
f5f2d263454d943a366844932bdb677530ba733bFred Herard } else {
f5f2d263454d943a366844932bdb677530ba733bFred Herard dmsg = dmsg_next;
f5f2d263454d943a366844932bdb677530ba733bFred Herard }
f5f2d263454d943a366844932bdb677530ba733bFred Herard }
f5f2d263454d943a366844932bdb677530ba733bFred Herard}
f5f2d263454d943a366844932bdb677530ba733bFred Herard
f5f2d263454d943a366844932bdb677530ba733bFred Herard
f5f2d263454d943a366844932bdb677530ba733bFred Herard/*
f5f2d263454d943a366844932bdb677530ba733bFred Herard * This function can block
f5f2d263454d943a366844932bdb677530ba733bFred Herard */
f5f2d263454d943a366844932bdb677530ba733bFred Herardstatic void
f5f2d263454d943a366844932bdb677530ba733bFred Herardsata_trace_rbuf_alloc(void)
f5f2d263454d943a366844932bdb677530ba733bFred Herard{
f5f2d263454d943a366844932bdb677530ba733bFred Herard sata_debug_rbuf = kmem_zalloc(sizeof (sata_trace_rbuf_t), KM_SLEEP);
f5f2d263454d943a366844932bdb677530ba733bFred Herard
f5f2d263454d943a366844932bdb677530ba733bFred Herard mutex_init(&sata_debug_rbuf->lock, NULL, MUTEX_DRIVER, NULL);
f5f2d263454d943a366844932bdb677530ba733bFred Herard
f5f2d263454d943a366844932bdb677530ba733bFred Herard if (dmsg_ring_size > 0) {
f5f2d263454d943a366844932bdb677530ba733bFred Herard sata_debug_rbuf->maxsize = (size_t)dmsg_ring_size;
f5f2d263454d943a366844932bdb677530ba733bFred Herard }
f5f2d263454d943a366844932bdb677530ba733bFred Herard}
f5f2d263454d943a366844932bdb677530ba733bFred Herard
f5f2d263454d943a366844932bdb677530ba733bFred Herard
f5f2d263454d943a366844932bdb677530ba733bFred Herardstatic void
f5f2d263454d943a366844932bdb677530ba733bFred Herardsata_trace_rbuf_free(void)
f5f2d263454d943a366844932bdb677530ba733bFred Herard{
f5f2d263454d943a366844932bdb677530ba733bFred Herard sata_trace_dmsg_free();
f5f2d263454d943a366844932bdb677530ba733bFred Herard mutex_destroy(&sata_debug_rbuf->lock);
f5f2d263454d943a366844932bdb677530ba733bFred Herard kmem_free(sata_debug_rbuf, sizeof (sata_trace_rbuf_t));
f5f2d263454d943a366844932bdb677530ba733bFred Herard}
f5f2d263454d943a366844932bdb677530ba733bFred Herard
f5f2d263454d943a366844932bdb677530ba733bFred Herard/*
f5f2d263454d943a366844932bdb677530ba733bFred Herard * If SATA_DEBUG is not defined then this routine is called instead
f5f2d263454d943a366844932bdb677530ba733bFred Herard * of sata_log() via the SATA_LOG_D macro.
f5f2d263454d943a366844932bdb677530ba733bFred Herard */
f5f2d263454d943a366844932bdb677530ba733bFred Herardstatic void
f5f2d263454d943a366844932bdb677530ba733bFred Herardsata_trace_log(sata_hba_inst_t *sata_hba_inst, uint_t level,
f5f2d263454d943a366844932bdb677530ba733bFred Herard const char *fmt, ...)
f5f2d263454d943a366844932bdb677530ba733bFred Herard{
f5f2d263454d943a366844932bdb677530ba733bFred Herard#ifndef __lock_lint
f5f2d263454d943a366844932bdb677530ba733bFred Herard _NOTE(ARGUNUSED(level))
f5f2d263454d943a366844932bdb677530ba733bFred Herard#endif
f5f2d263454d943a366844932bdb677530ba733bFred Herard
f5f2d263454d943a366844932bdb677530ba733bFred Herard dev_info_t *dip = NULL;
f5f2d263454d943a366844932bdb677530ba733bFred Herard va_list ap;
f5f2d263454d943a366844932bdb677530ba733bFred Herard
f5f2d263454d943a366844932bdb677530ba733bFred Herard if (sata_hba_inst != NULL) {
f5f2d263454d943a366844932bdb677530ba733bFred Herard dip = SATA_DIP(sata_hba_inst);
f5f2d263454d943a366844932bdb677530ba733bFred Herard }
f5f2d263454d943a366844932bdb677530ba733bFred Herard
f5f2d263454d943a366844932bdb677530ba733bFred Herard va_start(ap, fmt);
f5f2d263454d943a366844932bdb677530ba733bFred Herard sata_vtrace_debug(dip, fmt, ap);
f5f2d263454d943a366844932bdb677530ba733bFred Herard va_end(ap);
f5f2d263454d943a366844932bdb677530ba733bFred Herard}