sata.c revision 7a1efdfee8cbdecea34d3d866bbfb46e39b06e0a
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/*
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Use is subject to license terms.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#pragma ident "%Z%%M% %I% %E% SMI"
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * SATA Framework
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Generic SATA Host Adapter Implementation
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * NOTE: THIS VERSION DOES NOT SUPPORT ATAPI DEVICES,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * although there is some code related to these devices.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
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>
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>
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/* Debug flags - defined in sata.h */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfint sata_debug_flags = 0;
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
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int sata_func_enable = SATA_ENABLE_PROCESS_EVENTS;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#ifdef SATA_DEBUG
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#define SATA_LOG_D(args) sata_log args
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#else
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#define SATA_LOG_D(arg)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#endif
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
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
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Local functions
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void sata_remove_hba_instance(dev_info_t *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int sata_validate_sata_hba_tran(dev_info_t *, sata_hba_tran_t *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void sata_probe_ports(sata_hba_inst_t *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int sata_reprobe_port(sata_hba_inst_t *, sata_device_t *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void sata_make_device_nodes(dev_info_t *, sata_hba_inst_t *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic dev_info_t *sata_create_target_node(dev_info_t *, sata_hba_inst_t *,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_address_t *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int sata_validate_scsi_address(sata_hba_inst_t *,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf struct scsi_address *, sata_device_t *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int sata_validate_sata_address(sata_hba_inst_t *, int, int, int);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic sata_pkt_t *sata_pkt_alloc(sata_pkt_txlate_t *, int (*)(caddr_t));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void sata_pkt_free(sata_pkt_txlate_t *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int sata_dma_buf_setup(sata_pkt_txlate_t *, int, int (*)(caddr_t),
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf caddr_t, ddi_dma_attr_t *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int sata_probe_device(sata_hba_inst_t *, sata_device_t *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic sata_drive_info_t *sata_get_device_info(sata_hba_inst_t *,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device_t *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int sata_identify_device(sata_hba_inst_t *, sata_drive_info_t *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic struct buf *sata_alloc_local_buffer(sata_pkt_txlate_t *, int);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void sata_free_local_buffer(sata_pkt_txlate_t *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic uint64_t sata_check_capacity(sata_drive_info_t *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfvoid sata_adjust_dma_attr(sata_drive_info_t *, ddi_dma_attr_t *,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ddi_dma_attr_t *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int sata_fetch_device_identify_data(sata_hba_inst_t *,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_drive_info_t *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void sata_update_port_info(sata_hba_inst_t *, sata_device_t *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void sata_update_port_scr(sata_port_scr_t *, sata_device_t *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int sata_set_udma_mode(sata_hba_inst_t *, sata_drive_info_t *);
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelwstatic int sata_set_cache_mode(sata_hba_inst_t *, sata_drive_info_t *, int);
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelwstatic int sata_set_drive_features(sata_hba_inst_t *,
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw sata_drive_info_t *, int flag);
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelwstatic int sata_init_write_cache_mode(sata_hba_inst_t *,
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw sata_drive_info_t *sdinfo);
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelwstatic int sata_initialize_device(sata_hba_inst_t *, sata_drive_info_t *);
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);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void sata_process_device_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 *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void sata_process_device_detached(sata_hba_inst_t *, sata_address_t *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void sata_process_device_attached(sata_hba_inst_t *, 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 *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/* Local functions for ioctl */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int32_t sata_get_port_num(sata_hba_inst_t *, struct devctl_iocdata *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void sata_cfgadm_state(sata_hba_inst_t *, int32_t,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf devctl_ap_state_t *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic dev_info_t *sata_get_target_dip(dev_info_t *, int32_t);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic dev_info_t *sata_devt_to_devinfo(dev_t);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/* Local translation functions */
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 *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int sata_txlt_read(sata_pkt_txlate_t *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int sata_txlt_write(sata_pkt_txlate_t *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int sata_txlt_atapi(sata_pkt_txlate_t *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int sata_txlt_log_sense(sata_pkt_txlate_t *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int sata_txlt_log_select(sata_pkt_txlate_t *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int sata_txlt_mode_sense(sata_pkt_txlate_t *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int sata_txlt_mode_select(sata_pkt_txlate_t *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int sata_txlt_synchronize_cache(sata_pkt_txlate_t *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int sata_txlt_nodata_cmd_immediate(sata_pkt_txlate_t *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int sata_hba_start(sata_pkt_txlate_t *, int *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int sata_txlt_invalid_command(sata_pkt_txlate_t *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int sata_txlt_lba_out_of_range(sata_pkt_txlate_t *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void sata_txlt_rw_completion(sata_pkt_t *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void sata_txlt_atapi_completion(sata_pkt_t *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void sata_txlt_nodata_cmd_completion(sata_pkt_t *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic 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
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/* Local functions */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void sata_identdev_to_inquiry(sata_hba_inst_t *, sata_drive_info_t *,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf uint8_t *);
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 *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int sata_mode_select_page_8(sata_pkt_txlate_t *,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf struct mode_cache_scsi3 *, 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 *);
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 *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void sata_save_drive_settings(sata_drive_info_t *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void sata_show_drive_info(sata_hba_inst_t *, sata_drive_info_t *);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void sata_log(sata_hba_inst_t *, uint_t, char *fmt, ...);
c03acfcad7780db4ddf763511a82026680b3b2c1lsstatic int sata_fetch_smart_return_status(sata_hba_inst_t *,
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_drive_info_t *);
c03acfcad7780db4ddf763511a82026680b3b2c1lsstatic int sata_fetch_smart_data(sata_hba_inst_t *, sata_drive_info_t *,
c03acfcad7780db4ddf763511a82026680b3b2c1ls struct smart_data *);
c03acfcad7780db4ddf763511a82026680b3b2c1lsstatic int sata_smart_selftest_log(sata_hba_inst_t *,
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_drive_info_t *,
c03acfcad7780db4ddf763511a82026680b3b2c1ls struct smart_selftest_log *);
c03acfcad7780db4ddf763511a82026680b3b2c1lsstatic 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 *);
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 */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "Generic SATA Driver v%I%" /* 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
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
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw/* Default write cache setting */
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelwint sata_write_cache = 1;
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw
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
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))
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))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf_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))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf_NOTE(DATA_READABLE_WITHOUT_LOCK(sata_pmport_info::pmport_dev_type))
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))
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);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((rval = mod_install(&modlinkage)) != 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#ifdef SATA_DEBUG
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cmn_err(CE_WARN, "sata: _init: mod_install failed\n");
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#endif
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
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,
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw minclsyspri, 1, sata_tran->sata_tran_hba_num_cports,
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
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.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * (postponed until phase 2 of the development).
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
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.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_probe_ports(sata_hba_inst);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Create child nodes for all possible target devices currently
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * attached to controller's ports and port multiplier device ports.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_make_device_nodes(sata_tran->sata_tran_hba_dip, sata_hba_inst);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst->satahba_attached = 1;
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 *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * NOTE: cport support only, no port multiplier support.
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;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_drive_info_t *sdinfo;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int ncport;
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,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ncport);
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 !"));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (DDI_FAILURE);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
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));
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 *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * NOTE: Port Multiplier is not supported.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
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;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf dev_info_t *dip, *tdip;
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_drive_info_t *sdinfo;
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
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * handler rather then 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
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport = SCSI_TO_SATA_CPORT(comp_port);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf pmport = SCSI_TO_SATA_PMPORT(comp_port);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Only cport is considered now, i.e. SATA_ADDR_CPORT */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf qual = SATA_ADDR_CPORT;
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;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_addr.qual = SATA_ADDR_CPORT;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_rev = SATA_DEVICE_REV;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf switch (cmd) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case DEVCTL_AP_DISCONNECT:
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 *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * DEVCTL_AP_DISCONNECT invokes
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * sata_hba_inst->satahba_tran->
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * sata_tran_hotplug_ops->sata_tran_port_deactivate().
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * If successful, the device structure (if any) attached
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * to a port is removed and state of the port marked
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * appropriately.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Failure of the port_deactivate may keep port in
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * the active state, or may fail the port.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Check the current state of the port */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_reprobe_port(sata_hba_inst, &sata_device) !=
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_SUCCESS) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rv = EIO;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&SATA_CPORT_INFO(sata_hba_inst, cport)->
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (cportinfo->cport_state &
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (SATA_PSTATE_SHUTDOWN | SATA_PSTATE_FAILED)) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, cport)->
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rv = EIO;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw /* Sanity check */
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw if (SATA_PORT_DEACTIVATE_FUNC(sata_hba_inst) == NULL) {
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw /* No physical port deactivation supported. */
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw break;
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw }
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * set port's dev_state to not ready - this will disable
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * an access to an attached device.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo->cport_state &= ~SATA_STATE_READY;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (cportinfo->cport_dev_type != SATA_DTYPE_NONE) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo = cportinfo->cport_devp.cport_sata_drive;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ASSERT(sdinfo != NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((sdinfo->satadrv_type &
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (SATA_VALID_DEV_TYPE))) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * If a target node exists, try to offline
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * a device and remove target node.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&SATA_CPORT_INFO(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport)->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf tdip = sata_get_target_dip(dip, comp_port);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (tdip != NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* target node exist */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (ndi_devi_offline(tdip,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf NDI_DEVI_REMOVE) != NDI_SUCCESS) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Problem
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * A target node remained
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * attached. This happens when
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * the file was open or a node
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * was waiting for resources.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Cannot do anything about it.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_LOG_D((sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf CE_WARN,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_hba_ioctl: "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "disconnect: cannot "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "remove target node!!!"));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&SATA_CPORT_INFO(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport)->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Remove and release sata_drive_info
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * structure.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (SATA_CPORTINFO_DRV_INFO(cportinfo) !=
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_CPORTINFO_DRV_INFO(cportinfo) =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf NULL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (void) kmem_free((void *)sdinfo,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sizeof (sata_drive_info_t));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo->cport_dev_type =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_DTYPE_NONE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Note: PMult info requires different handling.
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw * Put PMult handling code here, when PMult is
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * supported.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, cport)->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Just ask HBA driver to deactivate port */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_addr.qual = SATA_ADDR_DCPORT;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rval = (*SATA_PORT_DEACTIVATE_FUNC(sata_hba_inst))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (dip, &sata_device);
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw /*
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw * Generate sysevent - EC_DR / ESC_DR_AP_STATE_CHANGE
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw * without the hint.
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw */
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw sata_gen_sysevent(sata_hba_inst,
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw &sata_device.satadev_addr, SE_NO_HINT);
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&SATA_CPORT_INFO(sata_hba_inst, cport)->
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_update_port_info(sata_hba_inst, &sata_device);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (rval != SATA_SUCCESS) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Port deactivation failure - do not
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * change port state unless the state
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * returned by HBA indicates a port failure.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_device.satadev_state & SATA_PSTATE_FAILED)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo->cport_state = SATA_PSTATE_FAILED;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rv = EIO;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw /*
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw * Deactivation succeded. From now on the framework
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw * will not know what is happening to the device, until
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw * the port is activated again.
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo->cport_state |= SATA_PSTATE_SHUTDOWN;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, cport)->cport_mutex);
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 */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((tdip = sata_get_target_dip(dip, comp_port)) != NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (ndi_devi_offline(tdip, NDI_UNCONFIG) !=
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf NDI_SUCCESS) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_LOG_D((sata_hba_inst, CE_WARN,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_hba_ioctl: unconfigure: "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "failed to unconfigure "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "device at cport %d", cport));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rv = EIO;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * The target node devi_state should be marked with
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * DEVI_DEVICE_OFFLINE by ndi_devi_offline().
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * This would be the indication for cfgadm that
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * the AP node occupant state is 'unconfigured'.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * This would indicate a failure on the part of cfgadm
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * to detect correct state of the node prior to this
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * call - one cannot unconfigure non-existing device.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_LOG_D((sata_hba_inst, CE_WARN,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_hba_ioctl: unconfigure: "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "attempt to unconfigure non-existing device "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "at cport %d", cport));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rv = ENXIO;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
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).
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * DEVCTL_AP_CONNECT would invoke
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * sata_hba_inst->satahba_tran->
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * sata_tran_hotplug_ops->sata_tran_port_activate().
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * If successful and a device is found attached to the port,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * the initialization sequence is executed to attach
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * a device structure to a port structure. The device is not
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * set in configured state (system-wise) by this operation.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * The state of the port and a device would be set
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * appropriately.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Note, that activating the port may generate link events,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * so is is important that following processing and the
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * event processing does not interfere with each other!
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * This operation may remove port failed state and will
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * try to make port active and in good standing.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* We only care about host sata cport for now */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (SATA_PORT_ACTIVATE_FUNC(sata_hba_inst) != NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Just let HBA driver to activate port */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((*SATA_PORT_ACTIVATE_FUNC(sata_hba_inst))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (dip, &sata_device) != SATA_SUCCESS) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Port activation failure.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&SATA_CPORT_INFO(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport)->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_update_port_info(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf &sata_device);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_device.satadev_state &
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_PSTATE_FAILED) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo->cport_state =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_PSTATE_FAILED;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&SATA_CPORT_INFO(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport)->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_LOG_D((sata_hba_inst, CE_WARN,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_hba_ioctl: connect: "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "failed to activate SATA cport %d",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rv = EIO;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Virgin port state - will be updated by the port re-probe. */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&SATA_CPORT_INFO(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport)->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo->cport_state = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&SATA_CPORT_INFO(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport)->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_reprobe_port(sata_hba_inst, &sata_device) ==
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_FAILURE)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rv = EIO;
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw /*
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw * Generate sysevent - EC_DR / ESC_DR_AP_STATE_CHANGE
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw * without the hint
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw */
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw sata_gen_sysevent(sata_hba_inst,
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw &sata_device.satadev_addr, SE_NO_HINT);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * If there is a device attached to the port, emit
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * a message.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (cportinfo->cport_dev_type != SATA_DTYPE_NONE) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_log(sata_hba_inst, CE_WARN,
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw "SATA device detected at port %d", cport);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case DEVCTL_AP_CONFIGURE:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf boolean_t target = TRUE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * A port may be in an active or shutdown state.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * If port is in a failed state, operation is aborted - one
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * has to use explicit connect or port activate request
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * to try to get a port into non-failed mode.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * If a port is in a shutdown state, arbitrarily invoke
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * sata_tran_port_activate() prior to any other operation.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Verify that port state is READY and there is a device
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * of a supported type attached to this port.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * If target node exists, a device was most likely offlined.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * If target node does not exist, create a target node an
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * attempt to online it.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * NO PMult or devices beyond PMult are supported yet.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* We only care about host controller's sata cport for now. */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (cportinfo->cport_state & SATA_PSTATE_FAILED) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rv = ENXIO;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Check the current state of the port */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_addr.qual = SATA_ADDR_CPORT;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rval = (*SATA_PROBE_PORT_FUNC(sata_hba_inst))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (dip, &sata_device);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&SATA_CPORT_INFO(sata_hba_inst, cport)->
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_update_port_info(sata_hba_inst, &sata_device);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (rval != SATA_SUCCESS ||
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (sata_device.satadev_state & SATA_PSTATE_FAILED)) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo->cport_state = SATA_PSTATE_FAILED;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, cport)->
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rv = EIO;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (cportinfo->cport_state & SATA_PSTATE_SHUTDOWN) {
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw target = FALSE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, cport)->
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (SATA_PORT_ACTIVATE_FUNC(sata_hba_inst) != NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Just let HBA driver to activate port */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((*SATA_PORT_ACTIVATE_FUNC(sata_hba_inst))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (dip, &sata_device) != SATA_SUCCESS) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Port activation failure - do not
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * change port state unless the state
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * returned by HBA indicates a port
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * failure.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&SATA_CPORT_INFO(
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst, cport)->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_update_port_info(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf &sata_device);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_device.satadev_state &
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_PSTATE_FAILED) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo->cport_state =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_PSTATE_FAILED;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&SATA_CPORT_INFO(
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst, cport)->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_LOG_D((sata_hba_inst, CE_WARN,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_hba_ioctl: configure: "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "failed to activate SATA cport %d",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rv = EIO;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw /*
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw * Generate sysevent - EC_DR / ESC_DR_AP_STATE_CHANGE
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw * without the hint.
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw */
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw sata_gen_sysevent(sata_hba_inst,
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw &sata_device.satadev_addr, SE_NO_HINT);
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&SATA_CPORT_INFO(sata_hba_inst, cport)->
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Virgin port state */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo->cport_state = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Always reprobe port, to get current device info.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, cport)->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_reprobe_port(sata_hba_inst, &sata_device) !=
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_SUCCESS) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rv = EIO;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (target == FALSE &&
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo->cport_dev_type != SATA_DTYPE_NONE) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw * That's the transition from "inactive" port
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw * to active one with device attached.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_log(sata_hba_inst, CE_WARN,
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw "SATA device detected at port %d",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * This is where real configure starts.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Change following check for PMult support.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (!(sata_device.satadev_type & SATA_VALID_DEV_TYPE)) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* No device to configure */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rv = ENXIO; /* No device to configure */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Here we may have a device in reset condition,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * but because we are just configuring it, there is
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * no need to process the reset other than just
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * to clear device reset condition in the HBA driver.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Setting the flag SATA_EVNT_CLEAR_DEVICE_RESET will
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * cause a first command sent the HBA driver with the request
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * to clear device reset condition.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&SATA_CPORT_INFO(sata_hba_inst, cport)->
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo = sata_get_device_info(sata_hba_inst, &sata_device);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sdinfo == NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rv = ENXIO;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, cport)->
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sdinfo->satadrv_event_flags &
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (SATA_EVNT_DEVICE_RESET | SATA_EVNT_INPROC_DEVICE_RESET))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_event_flags = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_event_flags |= SATA_EVNT_CLEAR_DEVICE_RESET;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, cport)->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((tdip = sata_get_target_dip(dip, comp_port)) != NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* target node still exists */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (ndi_devi_online(tdip, 0) != NDI_SUCCESS) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_LOG_D((sata_hba_inst, CE_WARN,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_hba_ioctl: configure: "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "onlining device at cport %d failed",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rv = EIO;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * No target node - need to create a new target node.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf tdip = sata_create_target_node(dip, sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf &sata_device.satadev_addr);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (tdip == NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* configure failed */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_LOG_D((sata_hba_inst, CE_WARN,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_hba_ioctl: configure: "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "configuring device at cport %d "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "failed", cport));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rv = EIO;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
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
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Override address qualifier - handle cport only for now */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf qual = SATA_ADDR_CPORT;
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;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_rev = SATA_DEVICE_REV;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf switch (ioc.cmd) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SATA_CFGA_RESET_PORT:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * There is no protection here for configured
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * device.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Sanity check */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (SATA_RESET_DPORT_FUNC(sata_hba_inst) == NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_LOG_D((sata_hba_inst, CE_WARN,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_hba_ioctl: "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_hba_tran missing required "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "function sata_tran_reset_dport"));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rv = EINVAL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* handle cport only for now */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_addr.qual = SATA_ADDR_CPORT;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((*SATA_RESET_DPORT_FUNC(sata_hba_inst))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (dip, &sata_device) != SATA_SUCCESS) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_LOG_D((sata_hba_inst, CE_WARN,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_hba_ioctl: reset port: "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "failed cport %d pmport %d",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport, pmport));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&SATA_CPORT_INFO(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport)->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_update_port_info(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf &sata_device);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_CPORT_STATE(sata_hba_inst, cport) =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_PSTATE_FAILED;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&SATA_CPORT_INFO(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport)->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rv = EIO;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Since the port was reset, it should be probed and
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * attached device reinitialized. At this point the
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * port state is unknown - it's state is HBA-specific.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Re-probe port to get its state.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_reprobe_port(sata_hba_inst, &sata_device) !=
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_SUCCESS) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rv = EIO;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SATA_CFGA_RESET_DEVICE:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * There is no protection here for configured
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * device.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Sanity check */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (SATA_RESET_DPORT_FUNC(sata_hba_inst) == NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_LOG_D((sata_hba_inst, CE_WARN,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_hba_ioctl: "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_hba_tran missing required "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "function sata_tran_reset_dport"));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rv = EINVAL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* handle only device attached to cports, for now */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_addr.qual = SATA_ADDR_DCPORT;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&SATA_CPORT_INFO(sata_hba_inst, cport)->
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo = sata_get_device_info(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf &sata_device);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sdinfo == NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&SATA_CPORT_INFO(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport)->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rv = EINVAL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, cport)->
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* only handle cport for now */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_addr.qual = SATA_ADDR_DCPORT;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((*SATA_RESET_DPORT_FUNC(sata_hba_inst))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (dip, &sata_device) != SATA_SUCCESS) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_LOG_D((sata_hba_inst, CE_WARN,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_hba_ioctl: reset device: failed "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "cport %d pmport %d", cport, pmport));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&SATA_CPORT_INFO(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport)->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_update_port_info(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf &sata_device);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Device info structure remains
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * attached. Another device reset or
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * port disconnect/connect and re-probing is
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * needed to change it's state
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_state &= ~SATA_STATE_READY;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_state |=
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_DSTATE_FAILED;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&SATA_CPORT_INFO(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport)->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rv = EIO;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Since the device was reset, we expect reset event
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * to be reported and processed.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SATA_CFGA_RESET_ALL:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int tcport;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * There is no protection here for configured
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * devices.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Sanity check */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (SATA_RESET_DPORT_FUNC(sata_hba_inst) == NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_LOG_D((sata_hba_inst, CE_WARN,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_hba_ioctl: "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_hba_tran missing required "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "function sata_tran_reset_dport"));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rv = EINVAL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Need to lock all ports, not just one.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * If any port is locked by event processing, fail
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * the whole operation.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * One port is already locked, but for simplicity
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * lock it again.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf for (tcport = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf tcport < SATA_NUM_CPORTS(sata_hba_inst);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf tcport++) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&SATA_CPORT_INFO(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf tcport)->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (((SATA_CPORT_INFO(sata_hba_inst, tcport)->
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport_event_flags) &
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_EVNT_LOCK_PORT_BUSY) != 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rv = EBUSY;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf &SATA_CPORT_INFO(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf tcport)->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_CPORT_INFO(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf tcport)->cport_event_flags |=
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_APCTL_LOCK_PORT_BUSY;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&SATA_CPORT_INFO(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf tcport)->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (rv == 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * All cports successfully locked.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Reset main SATA controller only for now -
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * no PMult.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_addr.qual =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_ADDR_CNTRL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((*SATA_RESET_DPORT_FUNC(sata_hba_inst))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (dip, &sata_device) != SATA_SUCCESS) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_LOG_D((sata_hba_inst, CE_WARN,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_hba_ioctl: reset controller "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "failed"));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rv = EIO;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Since ports were reset, they should be
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * re-probed and attached devices
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * reinitialized.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * At this point port states are unknown,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Re-probe ports to get their state -
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * cports only for now.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf for (tcport = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf tcport < SATA_NUM_CPORTS(sata_hba_inst);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf tcport++) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_addr.cport =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf tcport;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_addr.qual =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_ADDR_CPORT;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_reprobe_port(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf &sata_device) != SATA_SUCCESS)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rv = EIO;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Unlock all ports
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf for (tcport = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf tcport < SATA_NUM_CPORTS(sata_hba_inst);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf tcport++) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&SATA_CPORT_INFO(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf tcport)->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_CPORT_INFO(sata_hba_inst, tcport)->
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport_event_flags &=
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ~SATA_APCTL_LOCK_PORT_BUSY;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&SATA_CPORT_INFO(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf tcport)->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * This operation returns EFAULT if either reset
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * controller failed or a re-probbing of any ports
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * failed.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * We return here, because common return is for
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * a single cport operation.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (rv);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SATA_CFGA_PORT_DEACTIVATE:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Sanity check */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (SATA_PORT_DEACTIVATE_FUNC(sata_hba_inst) == NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rv = ENOTSUP;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Arbitrarily unconfigure attached device, if any.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Even if the unconfigure fails, proceed with the
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * port deactivation.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Handle only device attached to cports, for now */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_addr.qual = SATA_ADDR_DCPORT;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&SATA_CPORT_INFO(sata_hba_inst, cport)->
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo->cport_state &= ~SATA_STATE_READY;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (cportinfo->cport_dev_type != SATA_DTYPE_NONE) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Handle only device attached to cports,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * for now
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_addr.qual =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_ADDR_DCPORT;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo = sata_get_device_info(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf &sata_device);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sdinfo != NULL &&
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (sdinfo->satadrv_type &
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_VALID_DEV_TYPE)) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * If a target node exists, try to
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * offline a device and remove target
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * node.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&SATA_CPORT_INFO(
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst, cport)->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf tdip = sata_get_target_dip(dip, cport);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (tdip != NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* target node exist */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG1(SATA_DBG_IOCTL_IF,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_hba_ioctl: "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "port deactivate: "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "target node exists.",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (ndi_devi_offline(tdip,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf NDI_UNCONFIG) !=
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf NDI_SUCCESS) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_LOG_D((
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf CE_WARN,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_hba_ioctl:"
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "port deactivate: "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "failed to "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "unconfigure "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "device at cport "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "%d", cport));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (ndi_devi_offline(tdip,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf NDI_DEVI_REMOVE) !=
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf NDI_SUCCESS) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Problem;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * target node remained
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * attached.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Too bad...
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_LOG_D((
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf CE_WARN,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_hba_ioctl: "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "port deactivate: "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "failed to "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "unconfigure "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "device at "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "cport %d",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&SATA_CPORT_INFO(
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst, cport)->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * In any case,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * remove and release sata_drive_info
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * structure.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * (cport attached device ony, for now)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_CPORTINFO_DRV_INFO(cportinfo) =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf NULL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (void) kmem_free((void *)sdinfo,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sizeof (sata_drive_info_t));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo->cport_dev_type =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_DTYPE_NONE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Note: PMult info requires different
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * handling. This comment is a placeholder for
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * a code handling PMult, to be implemented
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * in phase 2.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo->cport_state &= ~(SATA_STATE_PROBED |
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_STATE_PROBING);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, cport)->
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* handle cport only for now */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_addr.qual = SATA_ADDR_CPORT;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Just let HBA driver to deactivate port */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rval = (*SATA_PORT_DEACTIVATE_FUNC(sata_hba_inst))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (dip, &sata_device);
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw /*
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw * Generate sysevent -
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw * EC_DR / ESC_DR_AP_STATE_CHANGE
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw * without the hint
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw */
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw sata_gen_sysevent(sata_hba_inst,
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw &sata_device.satadev_addr, SE_NO_HINT);
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&SATA_CPORT_INFO(sata_hba_inst, cport)->
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_update_port_info(sata_hba_inst, &sata_device);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (rval != SATA_SUCCESS) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Port deactivation failure - do not
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * change port state unless the state
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * returned by HBA indicates a port failure.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_device.satadev_state &
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_PSTATE_FAILED) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_CPORT_STATE(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport) = SATA_PSTATE_FAILED;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_LOG_D((sata_hba_inst, CE_WARN,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_hba_ioctl: port deactivate: "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "cannot deactivate SATA cport %d",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rv = EIO;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo->cport_state |= SATA_PSTATE_SHUTDOWN;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, cport)->
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SATA_CFGA_PORT_ACTIVATE:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf boolean_t dev_existed = TRUE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Sanity check */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (SATA_PORT_ACTIVATE_FUNC(sata_hba_inst) == NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rv = ENOTSUP;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* handle cport only for now */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (cportinfo->cport_state & SATA_PSTATE_SHUTDOWN ||
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo->cport_dev_type == SATA_DTYPE_NONE)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf dev_existed = FALSE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_addr.qual = SATA_ADDR_CPORT;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Just let HBA driver to activate port */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((*SATA_PORT_ACTIVATE_FUNC(sata_hba_inst))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (dip, &sata_device) != SATA_SUCCESS) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Port activation failure - do not
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * change port state unless the state
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * returned by HBA indicates a port failure.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&SATA_CPORT_INFO(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport)->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_update_port_info(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf &sata_device);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_device.satadev_state &
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_PSTATE_FAILED) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_CPORT_STATE(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport) = SATA_PSTATE_FAILED;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&SATA_CPORT_INFO(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport)->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_LOG_D((sata_hba_inst, CE_WARN,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_hba_ioctl: port activate: "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "cannot activate SATA cport %d",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rv = EIO;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&SATA_CPORT_INFO(sata_hba_inst, cport)->
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo->cport_state &= ~SATA_PSTATE_SHUTDOWN;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, cport)->
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Re-probe port to find its current state and
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * possibly attached device.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Port re-probing may change the cportinfo device
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * type if device is found attached.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * If port probing failed, the device type would be
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * set to SATA_DTYPE_NONE.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (void) sata_reprobe_port(sata_hba_inst, &sata_device);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw /*
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw * Generate sysevent -
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw * EC_DR / ESC_DR_AP_STATE_CHANGE
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw * without the hint.
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw */
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw sata_gen_sysevent(sata_hba_inst,
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw &sata_device.satadev_addr, SE_NO_HINT);
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (dev_existed == FALSE &&
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo->cport_dev_type != SATA_DTYPE_NONE) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * That's the transition from "inactive" port
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * state or active port without a device
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * attached to the active port state with
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * a device attached.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_log(sata_hba_inst, CE_WARN,
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw "SATA device detected at port %d", cport);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SATA_CFGA_PORT_SELF_TEST:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Sanity check */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (SATA_SELFTEST_FUNC(sata_hba_inst) == NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rv = ENOTSUP;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * There is no protection here for a configured
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * device attached to this port.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* only handle cport for now */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_addr.qual = SATA_ADDR_CPORT;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((*SATA_SELFTEST_FUNC(sata_hba_inst))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (dip, &sata_device) != SATA_SUCCESS) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_LOG_D((sata_hba_inst, CE_WARN,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_hba_ioctl: port selftest: "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "failed cport %d pmport %d",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport, pmport));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&SATA_CPORT_INFO(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport)->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_update_port_info(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf &sata_device);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_CPORT_STATE(sata_hba_inst, cport) =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_PSTATE_FAILED;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&SATA_CPORT_INFO(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport)->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rv = EIO;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Since the port was reset, it should be probed and
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * attached device reinitialized. At this point the
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * port state is unknown - it's state is HBA-specific.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Force port re-probing to get it into a known state.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_reprobe_port(sata_hba_inst, &sata_device) !=
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_SUCCESS) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rv = EIO;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SATA_CFGA_GET_DEVICE_PATH:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf char path[MAXPATHLEN];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf uint32_t size;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (void) strcpy(path, "/devices");
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((tdip = sata_get_target_dip(dip, ioc.port)) ==
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * No such device.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * If this is a request for a size, do not
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * return EINVAL for non-exisiting target,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * because cfgadm will indicate a meaningless
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * ioctl failure.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * If this is a real request for a path,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * indicate invalid argument.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (!ioc.get_size) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rv = EINVAL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (void) ddi_pathname(tdip, path + strlen(path));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf size = strlen(path) + 1;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (ioc.get_size) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (ddi_copyout((void *)&size,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ioc.buf, ioc.bufsiz, mode) != 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rv = EFAULT;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (ioc.bufsiz != size) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rv = EINVAL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else if (ddi_copyout((void *)&path,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ioc.buf, ioc.bufsiz, mode) != 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rv = EFAULT;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SATA_CFGA_GET_AP_TYPE:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf uint32_t type_len;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf const char *ap_type;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* cport only, no port multiplier support */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf switch (SATA_CPORT_DEV_TYPE(sata_hba_inst, cport)) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SATA_DTYPE_NONE:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ap_type = "port";
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SATA_DTYPE_ATADISK:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ap_type = "disk";
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SATA_DTYPE_ATAPICD:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ap_type = "cd/dvd";
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SATA_DTYPE_PMULT:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ap_type = "pmult";
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SATA_DTYPE_UNKNOWN:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ap_type = "unknown";
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf default:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ap_type = "unsupported";
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } /* end of dev_type switch */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf type_len = strlen(ap_type) + 1;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (ioc.get_size) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (ddi_copyout((void *)&type_len,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ioc.buf, ioc.bufsiz, mode) != 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rv = EFAULT;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (ioc.bufsiz != type_len) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rv = EINVAL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (ddi_copyout((void *)ap_type, ioc.buf,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ioc.bufsiz, mode) != 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rv = EFAULT;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SATA_CFGA_GET_MODEL_INFO:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf uint32_t info_len;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf char ap_info[sizeof (sdinfo->satadrv_id.ai_model) + 1];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * This operation should return to cfgadm the
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * device model information string
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&SATA_CPORT_INFO(sata_hba_inst, cport)->
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* only handle device connected to cport for now */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_addr.qual = SATA_ADDR_DCPORT;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo = sata_get_device_info(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf &sata_device);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sdinfo == NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rv = EINVAL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&SATA_CPORT_INFO(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport)->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf bcopy(sdinfo->satadrv_id.ai_model, ap_info,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sizeof (sdinfo->satadrv_id.ai_model));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf swab(ap_info, ap_info,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sizeof (sdinfo->satadrv_id.ai_model));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ap_info[sizeof (sdinfo->satadrv_id.ai_model)] = '\0';
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, cport)->
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf info_len = strlen(ap_info) + 1;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (ioc.get_size) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (ddi_copyout((void *)&info_len,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ioc.buf, ioc.bufsiz, mode) != 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rv = EFAULT;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (ioc.bufsiz < info_len) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rv = EINVAL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (ddi_copyout((void *)ap_info, ioc.buf,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ioc.bufsiz, mode) != 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rv = EFAULT;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SATA_CFGA_GET_REVFIRMWARE_INFO:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf uint32_t info_len;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf char ap_info[
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sizeof (sdinfo->satadrv_id.ai_fw) + 1];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * This operation should return to cfgadm the
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * device firmware revision information string
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&SATA_CPORT_INFO(sata_hba_inst, cport)->
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* only handle device connected to cport for now */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_addr.qual = SATA_ADDR_DCPORT;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo = sata_get_device_info(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf &sata_device);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sdinfo == NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&SATA_CPORT_INFO(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport)->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rv = EINVAL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf bcopy(sdinfo->satadrv_id.ai_fw, ap_info,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sizeof (sdinfo->satadrv_id.ai_fw));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf swab(ap_info, ap_info,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sizeof (sdinfo->satadrv_id.ai_fw));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ap_info[sizeof (sdinfo->satadrv_id.ai_fw)] = '\0';
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, cport)->
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf info_len = strlen(ap_info) + 1;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (ioc.get_size) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (ddi_copyout((void *)&info_len,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ioc.buf, ioc.bufsiz, mode) != 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rv = EFAULT;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (ioc.bufsiz < info_len) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rv = EINVAL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (ddi_copyout((void *)ap_info, ioc.buf,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ioc.bufsiz, mode) != 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rv = EFAULT;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SATA_CFGA_GET_SERIALNUMBER_INFO:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf uint32_t info_len;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf char ap_info[
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sizeof (sdinfo->satadrv_id.ai_drvser) + 1];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * This operation should return to cfgadm the
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * device serial number information string
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&SATA_CPORT_INFO(sata_hba_inst, cport)->
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* only handle device connected to cport for now */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_addr.qual = SATA_ADDR_DCPORT;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo = sata_get_device_info(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf &sata_device);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sdinfo == NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&SATA_CPORT_INFO(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport)->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rv = EINVAL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf bcopy(sdinfo->satadrv_id.ai_drvser, ap_info,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sizeof (sdinfo->satadrv_id.ai_drvser));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf swab(ap_info, ap_info,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sizeof (sdinfo->satadrv_id.ai_drvser));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ap_info[sizeof (sdinfo->satadrv_id.ai_drvser)] = '\0';
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, cport)->
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf info_len = strlen(ap_info) + 1;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (ioc.get_size) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (ddi_copyout((void *)&info_len,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ioc.buf, ioc.bufsiz, mode) != 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rv = EFAULT;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (ioc.bufsiz < info_len) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rv = EINVAL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (ddi_copyout((void *)ap_info, ioc.buf,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ioc.bufsiz, mode) != 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rv = EFAULT;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf default:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rv = EINVAL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } /* End of DEVCTL_AP_CONTROL cmd switch */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf default:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * If we got here, we got an IOCTL that SATA HBA Framework
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * does not recognize. Pass ioctl to HBA driver, in case
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * it could process it.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_tran_t *sata_tran = sata_hba_inst->satahba_tran;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf dev_info_t *mydip = SATA_DIP(sata_hba_inst);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG1(SATA_DBG_IOCTL_IF, sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "IOCTL 0x%2x not supported in SATA framework, "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "passthrough to HBA", cmd);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_tran->sata_tran_ioctl == NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rv = EINVAL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rval = (*sata_tran->sata_tran_ioctl)(mydip, cmd, arg);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (rval != 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG1(SATA_DBG_IOCTL_IF, sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "IOCTL 0x%2x failed in HBA", cmd);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rv = rval;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } /* End of main IOCTL switch */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (dcp) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ndi_dc_freehdl(dcp);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&SATA_CPORT_INFO(sata_hba_inst, cport)->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo->cport_event_flags &= ~SATA_APCTL_LOCK_PORT_BUSY;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, cport)->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (rv);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
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))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#endif
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device_t sata_device;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_drive_info_t *sdinfo;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst_t *sata_hba_inst;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
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 }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_device.satadev_type == SATA_DTYPE_ATAPICD) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_addr.cport)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (ndi_prop_update_string(DDI_DEV_T_NONE, tgt_dip,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "variant", "atapi") != DDI_PROP_SUCCESS) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_LOG_D((sata_hba_inst, CE_WARN,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_scsi_tgt_init: variant atapi "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "property could not be created"));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (DDI_FAILURE);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (DDI_SUCCESS);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_addr.cport)));
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;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rval = scsi_hba_probe(sd, callback);
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,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "pm-capable", 1)) != DDI_PROP_SUCCESS) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_log(sata_hba_inst, CE_WARN,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "device at port %d: will not be power-managed ",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SCSI_TO_SATA_CPORT(sd->sd_address.a_target));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_LOG_D((sata_hba_inst, CE_WARN,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "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;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
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;
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()
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * other than property for ATAPI device, if any
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_device.satadev_type == SATA_DTYPE_ATAPICD) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_addr.cport)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (ndi_prop_remove(DDI_DEV_T_NONE, tgt_dip, "variant") !=
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf DDI_PROP_SUCCESS)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_LOG_D((sata_hba_inst, CE_WARN,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_scsi_tgt_free: variant atapi "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "property could not be removed"));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_addr.cport)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
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 */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_sata_pkt->satapkt_device = sata_device;
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 ASSERT(spx->txlt_buf_dma_handle != NULL);
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 /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Allocate necessary DMA resources for the packet's buffer
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((rval = sata_dma_buf_setup(spx, flags, callback, arg,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf &cur_dma_attr)) != DDI_SUCCESS) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_pkt_free(spx);
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.
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 }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (new_pkt == TRUE) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_pkt_free(spx);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsi_hba_pkt_free(ap, pkt);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
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.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * 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
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * SCMD_WRITE_G1
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * SCMD_WRITE_G4
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * SCMD_WRITE_G5
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * SCMD_SEEK (noop)
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
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * for execution.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * TRAN_BADPKT if cmd was directed to invalid address.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * TRAN_FATAL_ERROR is command was rejected due to hardware error, including
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * unexpected removal of a device or some other unspecified error.
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;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_drive_info_t *sdinfo;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf struct buf *bp;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int cport;
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 /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Mutex-protected section below is just to identify device type
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * and switch to ATAPI processing, if necessary
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport = SCSI_TO_SATA_CPORT(ap->a_target);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&(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 if (sdinfo == NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst, cport)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_scsi_pkt->pkt_reason = CMD_DEV_GONE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (TRAN_FATAL_ERROR);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sdinfo->satadrv_type == SATA_DTYPE_ATAPICD) {
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
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;
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
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/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Implementation os 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) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* port reset - cport only */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_addr.qual = SATA_ADDR_CPORT;
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).
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Supported capabilities:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * auto-rqsense (always supported)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * tagged-qing (supported if HBA supports it)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * dma_max
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * interconnect-type (INTERCONNECT_SATA)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Request for other capabilities is rejected as unsupported.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Returns supported capability value, or -1 if capability is unsuppported or
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * 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)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (0);
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
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SCSI_CAP_TAGGED_QING:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * It is enough if the controller supports queuing, regardless
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * of the device. NCQ support is an internal implementation
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * feature used between HBA and the device.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (SATA_QDEPTH(sata_hba_inst) > 1)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rval = 1; /* Queuing supported */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf else
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rval = -1; /* Queuing not supported */
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
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
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * All supported capabilities are fixed/unchangeable.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Returns 0 for all supported capabilities and valid device, -1 otherwise.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_scsi_setcap(struct scsi_address *ap, char *cap, int value, int whom)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#ifndef __lock_lint
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf _NOTE(ARGUNUSED(value))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#endif
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 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)));
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
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf switch (scsi_hba_lookup_capstr(cap)) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SCSI_CAP_ARQ:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SCSI_CAP_SECTOR_SIZE:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SCSI_CAP_TAGGED_QING:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SCSI_CAP_DMA_MAX:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SCSI_CAP_INTERCONNECT_TYPE:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rval = 0; /* Capability cannot be changed */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
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 ASSERT(pkt != NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx = (sata_pkt_txlate_t *)pkt->pkt_ha_private;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (spx->txlt_buf_dma_handle != NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Free DMA resources - cookies and handles
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ASSERT(spx->txlt_dma_cookie_list != NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (void) kmem_free(spx->txlt_dma_cookie_list,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_dma_cookie_list_len * sizeof (ddi_dma_cookie_t));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (void) ddi_dma_unbind_handle(spx->txlt_buf_dma_handle);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (void) ddi_dma_free_handle(&spx->txlt_buf_dma_handle);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
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
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (spx->txlt_buf_dma_handle != NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Free DMA resources - cookies and handles
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ASSERT(spx->txlt_dma_cookie_list != NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (void) kmem_free(spx->txlt_dma_cookie_list,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_dma_cookie_list_len * sizeof (ddi_dma_cookie_t));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (void) ddi_dma_unbind_handle(spx->txlt_buf_dma_handle);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (void) ddi_dma_free_handle(&spx->txlt_buf_dma_handle);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
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
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;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (spx->txlt_buf_dma_handle != NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (spx->txlt_sata_pkt != NULL &&
c03acfcad7780db4ddf763511a82026680b3b2c1ls spx->txlt_sata_pkt->satapkt_cmd.satacmd_flags.
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_data_direction != SATA_DIR_NODATA_XFER) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rval = ddi_dma_sync(spx->txlt_buf_dma_handle, 0, 0,
c03acfcad7780db4ddf763511a82026680b3b2c1ls (spx->txlt_sata_pkt->satapkt_cmd.
c03acfcad7780db4ddf763511a82026680b3b2c1ls satacmd_flags.sata_data_direction &
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_DIR_WRITE) ?
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf DDI_DMA_SYNC_FORDEV : DDI_DMA_SYNC_FORCPU);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (rval == DDI_SUCCESS) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_LOG_D((spx->txlt_sata_hba_inst, CE_WARN,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_scsi_sync_pkt: sync pkt failed"));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
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 *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Returns TRAN_ACCEPT if device exists and sata_pkt was set-up.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Returns other TRAN_XXXXX values when error occured.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * This function should be called with port mutex held.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_txlt_generic_pkt_info(sata_pkt_txlate_t *spx)
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 };
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);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case 1:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* valid address but no device - it has disappeared ? */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_scsi_pkt->pkt_reason = CMD_DEV_GONE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (TRAN_FATAL_ERROR);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf default:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* all OK */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
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
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * TRAN_BUSY
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sdinfo->satadrv_event_flags &
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (SATA_EVNT_DEVICE_RESET | SATA_EVNT_INPROC_DEVICE_RESET)) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_scsi_pkt->pkt_reason = CMD_INCOMPLETE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG1(SATA_DBG_SCSI_IF, spx->txlt_sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_scsi_start: rejecting command because "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "of device reset state\n", NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (TRAN_BUSY);
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;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_scsi_pkt->pkt_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;
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/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Translate ATA(ATAPI) Identify (Packet) Device data to SCSI Inquiry data.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * SATA Identify Device data has to be valid in sata_rive_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
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Rely on the dev_type for setting paripheral qualifier */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Does DTYPE_RODIRECT apply to CD/DVD R/W devices ? */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf inq->inq_dtype = sdinfo->satadrv_type == SATA_DTYPE_ATADISK ?
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf DTYPE_DIRECT : DTYPE_RODIRECT;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf inq->inq_rmb = 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. */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf inq->inq_trmiop = 0; /* Supports TERMINATE I/O PROC msg ??? */
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
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#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 */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#else
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf bcopy(sid->ai_model, inq->inq_vid, 8); /* Vendor ID */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf bcopy(&sid->ai_model[8], 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 */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#endif
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;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense->es_add_code = SD_SCSI_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,
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw TQ_SLEEP) == 0)
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw /* Scheduling the callback failed */
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw return (TRAN_BUSY);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (TRAN_ACCEPT);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
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 */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_txlt_nodata_cmd_immediate(sata_pkt_txlate_t *spx)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int rval;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&(SATA_TXLT_CPORT_MUTEX(spx)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((rval = sata_txlt_generic_pkt_info(spx)) != TRAN_ACCEPT) {
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,
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw TQ_SLEEP) == 0)
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw /* Scheduling the callback failed */
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw return (TRAN_BUSY);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (TRAN_ACCEPT);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * SATA translate command: Inquiry / Identify Device
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Use cached Identify Device data for now, rather then issuing actual
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Device Identify cmd request. If device is detached and re-attached,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * asynchromous 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 */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int rval;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&(SATA_TXLT_CPORT_MUTEX(spx)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((rval = sata_txlt_generic_pkt_info(spx)) != TRAN_ACCEPT) {
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 |
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf 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;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense->es_add_code = SD_SCSI_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
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (!(scsipkt->pkt_cdbp[1] & EVPD)) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* 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 ?
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf 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
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * 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;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case INQUIRY_USN_PAGE:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Request for Unit Serial Number page
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf page_buf[0] = peripheral_device_type;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf page_buf[1] = INQUIRY_USN_PAGE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf page_buf[2] = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf page_buf[3] = 20; /* remaining page length */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf p = (uint8_t *)(sdinfo->satadrv_id.ai_drvser);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#ifdef _LITTLE_ENDIAN
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf swab(p, &page_buf[4], 20);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#else
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf bcopy(p, &page_buf[4], 20);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#endif
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf for (i = 0; i < 20; i++) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (page_buf[4 + i] == '\0' ||
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf page_buf[4 + i] == '\040') {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * 'i' contains string length.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Least significant character of the serial
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * number shall appear as the last byte,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * according to SBC-3 spec.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf p = &page_buf[20 + 4 - 1];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf for (j = i; j > 0; j--, p--) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *p = *(p - 20 + i);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf p = &page_buf[4];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf for (j = 20 - i; j > 0; j--) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *p++ = '\040';
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf count = MIN(bp->b_bcount, 24);
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 */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*FALLTHRU*/
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 =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SD_SCSI_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,
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw TQ_SLEEP) == 0)
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw /* Scheduling the callback failed */
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw return (TRAN_BUSY);
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (TRAN_ACCEPT);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * SATA translate command: Request Sense
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * emulated command (ATA version so far, no ATAPI)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Always NO SENSE, because any sense data should be reported by ARQ sense.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Returns TRAN_ACCEPT and appropriate values in scsi_pkt fields.
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;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int rval;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&(SATA_TXLT_CPORT_MUTEX(spx)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((rval = sata_txlt_generic_pkt_info(spx)) != TRAN_ACCEPT) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&(SATA_TXLT_CPORT_MUTEX(spx)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (rval);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&(SATA_TXLT_CPORT_MUTEX(spx)));
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
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (bp != NULL && bp->b_un.b_addr && bp->b_bcount) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int count = MIN(bp->b_bcount,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sizeof (struct scsi_extended_sense));
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;
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
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,
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw TQ_SLEEP) == 0)
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw /* Scheduling the callback failed */
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw return (TRAN_BUSY);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (TRAN_ACCEPT);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * SATA translate command: Test Unit Ready
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * At the moment this is an emulated command (ATA version so far, no ATAPI).
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * May be translated into Check Power Mode command in the future
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;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int power_state;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int rval;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&(SATA_TXLT_CPORT_MUTEX(spx)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((rval = sata_txlt_generic_pkt_info(spx)) != TRAN_ACCEPT) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&(SATA_TXLT_CPORT_MUTEX(spx)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (rval);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&(SATA_TXLT_CPORT_MUTEX(spx)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* At this moment, emulate it rather than execute anything */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf power_state = SATA_PWRMODE_ACTIVE;
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 switch (power_state) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SATA_PWRMODE_ACTIVE:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SATA_PWRMODE_IDLE:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *scsipkt->pkt_scbp = STATUS_GOOD;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf default:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* PWR mode standby */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *scsipkt->pkt_scbp = STATUS_CHECK;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense = sata_arq_sense(spx);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense->es_key = KEY_NOT_READY;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense->es_add_code = SD_SCSI_LU_NOT_READY;
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
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,
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw TQ_SLEEP) == 0)
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw /* Scheduling the callback failed */
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw return (TRAN_BUSY);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (TRAN_ACCEPT);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * SATA translate command: Start Stop Unit
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Translation depends on a command:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Start Unit translated into Idle Immediate
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Stop Unit translated into Standby Immediate
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Unload Media / NOT SUPPORTED YET
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Load Media / NOT SUPPROTED YET
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Power condition bits are ignored, so is Immediate bit
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Requesting synchronous execution.
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 struct scsi_extended_sense *sense;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst_t *shi = SATA_TXLT_HBA_INST(spx);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int cport = SATA_TXLT_CPORT(spx);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int rval;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int synch;
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
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((rval = sata_txlt_generic_pkt_info(spx)) != TRAN_ACCEPT) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&(SATA_TXLT_CPORT_MUTEX(spx)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (rval);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (scsipkt->pkt_cdbp[4] & 2) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Load/Unload Media - invalid request */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *scsipkt->pkt_scbp = STATUS_CHECK;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense = sata_arq_sense(spx);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense->es_key = KEY_ILLEGAL_REQUEST;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense->es_add_code = SD_SCSI_INVALID_FIELD_IN_CDB;
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", 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,
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw TQ_SLEEP) == 0)
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw /* Scheduling the callback failed */
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw return (TRAN_BUSY);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (TRAN_ACCEPT);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_addr_type = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_sec_count_lsb = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_lba_low_lsb = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_lba_mid_lsb = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_lba_high_lsb = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_features_reg = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_device_reg = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_status_reg = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (scsipkt->pkt_cdbp[4] & 1) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Start Unit */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_cmd_reg = SATAC_IDLE_IM;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Stop Unit */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_cmd_reg = SATAC_STANDBY_IM;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (!(spx->txlt_sata_pkt->satapkt_op_mode & SATA_OPMODE_SYNCH)) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Need to set-up a callback function */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_sata_pkt->satapkt_comp =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_txlt_nodata_cmd_completion;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf synch = FALSE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_sata_pkt->satapkt_op_mode = SATA_OPMODE_SYNCH;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf synch = TRUE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
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
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 mutex_exit(&SATA_CPORT_MUTEX(shi, cport));
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
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_txlt_nodata_cmd_completion(spx->txlt_sata_pkt);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (TRAN_ACCEPT);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
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.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * This is ATA version (non-ATAPI).
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;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int rval;
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
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((rval = sata_txlt_generic_pkt_info(spx)) != TRAN_ACCEPT) {
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) {
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,
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw TQ_SLEEP) == 0)
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
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 */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int rval;
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
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((rval = sata_txlt_generic_pkt_info(spx)) != TRAN_ACCEPT) {
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) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf len = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf bdlen = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (!(scsipkt->pkt_cdbp[1] & 8)) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (scsipkt->pkt_cdbp[0] == SCMD_MODE_SENSE_G1 &&
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (scsipkt->pkt_cdbp[0] & 0x10))
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 */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf 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 =
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls SD_SCSI_SAVING_PARAMS_NOT_SUP;
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;
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 }
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;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense->es_add_code = SD_SCSI_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 */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf 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,
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw TQ_SLEEP) == 0)
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 *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * NOTE: only caching mode select page is implemented.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Caching setup is remembered so it could be re-stored in case of
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * an unexpected device reset.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Returns TRAN_ACCEPT and appropriate values 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 */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int rval, stat;
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
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((rval = sata_txlt_generic_pkt_info(spx)) != TRAN_ACCEPT) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&(SATA_TXLT_CPORT_MUTEX(spx)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (rval);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
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;
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;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense->es_add_code = SD_SCSI_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 nointr_flag = scsipkt->pkt_flags & FLAG_NOINTR;
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 =
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls SD_SCSI_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
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 =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SD_SCSI_INVALID_FIELD_IN_PARAMETER_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;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int rv;
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,
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw TQ_SLEEP) == 0)
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 */
c03acfcad7780db4ddf763511a82026680b3b2c1ls int rval;
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
c03acfcad7780db4ddf763511a82026680b3b2c1ls if ((rval = sata_txlt_generic_pkt_info(spx)) != TRAN_ACCEPT) {
c03acfcad7780db4ddf763511a82026680b3b2c1ls mutex_exit(&(SATA_TXLT_CPORT_MUTEX(spx)));
c03acfcad7780db4ddf763511a82026680b3b2c1ls kmem_free(buf, MAX_LOG_SENSE_PAGE_SIZE);
c03acfcad7780db4ddf763511a82026680b3b2c1ls return (rval);
c03acfcad7780db4ddf763511a82026680b3b2c1ls }
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
c03acfcad7780db4ddf763511a82026680b3b2c1ls /* Reject not supported request for all but cummulative values */
c03acfcad7780db4ddf763511a82026680b3b2c1ls switch (pc) {
c03acfcad7780db4ddf763511a82026680b3b2c1ls case PC_CUMMULATIVE_VALUES:
c03acfcad7780db4ddf763511a82026680b3b2c1ls break;
c03acfcad7780db4ddf763511a82026680b3b2c1ls default:
c03acfcad7780db4ddf763511a82026680b3b2c1ls *scsipkt->pkt_scbp = STATUS_CHECK;
c03acfcad7780db4ddf763511a82026680b3b2c1ls sense = sata_arq_sense(spx);
c03acfcad7780db4ddf763511a82026680b3b2c1ls sense->es_key = KEY_ILLEGAL_REQUEST;
c03acfcad7780db4ddf763511a82026680b3b2c1ls sense->es_add_code = SD_SCSI_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:
c03acfcad7780db4ddf763511a82026680b3b2c1ls break;
c03acfcad7780db4ddf763511a82026680b3b2c1ls default:
c03acfcad7780db4ddf763511a82026680b3b2c1ls *scsipkt->pkt_scbp = STATUS_CHECK;
c03acfcad7780db4ddf763511a82026680b3b2c1ls sense = sata_arq_sense(spx);
c03acfcad7780db4ddf763511a82026680b3b2c1ls sense->es_key = KEY_ILLEGAL_REQUEST;
c03acfcad7780db4ddf763511a82026680b3b2c1ls sense->es_add_code = SD_SCSI_INVALID_FIELD_IN_CDB;
c03acfcad7780db4ddf763511a82026680b3b2c1ls goto done;
c03acfcad7780db4ddf763511a82026680b3b2c1ls }
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls if (bp != NULL && bp->b_un.b_addr && bp->b_bcount) {
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_id_t *sata_id;
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 /*
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 =
c03acfcad7780db4ddf763511a82026680b3b2c1ls SD_SCSI_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 =
c03acfcad7780db4ddf763511a82026680b3b2c1ls SD_SCSI_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 =
c03acfcad7780db4ddf763511a82026680b3b2c1ls SD_SCSI_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;
c03acfcad7780db4ddf763511a82026680b3b2c1ls default:
c03acfcad7780db4ddf763511a82026680b3b2c1ls /* Invalid request */
c03acfcad7780db4ddf763511a82026680b3b2c1ls *scsipkt->pkt_scbp = STATUS_CHECK;
c03acfcad7780db4ddf763511a82026680b3b2c1ls sense = sata_arq_sense(spx);
c03acfcad7780db4ddf763511a82026680b3b2c1ls sense->es_key = KEY_ILLEGAL_REQUEST;
c03acfcad7780db4ddf763511a82026680b3b2c1ls sense->es_add_code = SD_SCSI_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,
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw TQ_SLEEP) == 0)
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 */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic 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
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * (NO ATAPI implementation yet).
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.
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;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int rval;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int synch;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&(SATA_TXLT_CPORT_MUTEX(spx)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((rval = sata_txlt_generic_pkt_info(spx)) != TRAN_ACCEPT) {
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 /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Build cmd block depending on the device capability and
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * requested operation mode.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Do not bother with non-dma mode.
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) ||
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ((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
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) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sdinfo->satadrv_queue_depth > 1 &&
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_QDEPTH(spx->txlt_sata_hba_inst) > 1) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Queuing supported by controller and device */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((sata_func_enable & SATA_ENABLE_NCQ) &&
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (sdinfo->satadrv_features_support &
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_DEV_F_NCQ) &&
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (SATA_FEATURES(spx->txlt_sata_hba_inst) &
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_CTLF_NCQ)) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* NCQ supported - use FPDMA READ */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_cmd_reg =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATAC_READ_FPDMA_QUEUED;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_features_reg_ext =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_sec_count_msb;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_sec_count_msb = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Legacy queueing */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sdinfo->satadrv_features_support &
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_DEV_F_LBA48) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_cmd_reg =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf 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 {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_cmd_reg =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATAC_READ_DMA_QUEUED;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
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;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
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
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * (NO ATAPI implementation yet).
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 *
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;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int rval;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int synch;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&(SATA_TXLT_CPORT_MUTEX(spx)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((rval = sata_txlt_generic_pkt_info(spx)) != TRAN_ACCEPT) {
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 /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Build cmd block depending on the device capability and
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * requested operation mode.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Do not bother with non-dma mode.
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) ||
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ((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
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) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sdinfo->satadrv_queue_depth > 1 &&
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_QDEPTH(spx->txlt_sata_hba_inst) > 1) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Queuing supported by controller and device */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((sata_func_enable & SATA_ENABLE_NCQ) &&
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (sdinfo->satadrv_features_support &
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_DEV_F_NCQ) &&
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (SATA_FEATURES(spx->txlt_sata_hba_inst) &
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_CTLF_NCQ)) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* NCQ supported - use FPDMA WRITE */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_cmd_reg =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATAC_WRITE_FPDMA_QUEUED;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_features_reg_ext =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_sec_count_msb;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_sec_count_msb = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_rle_sata_cmd = NULL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Legacy queueing */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sdinfo->satadrv_features_support &
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_DEV_F_LBA48) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_cmd_reg =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf 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 {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_cmd_reg =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATAC_WRITE_DMA_QUEUED;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
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;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
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
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * NOTE: NOT FUNCTIONAL IMPLEMENTATION. THIS IS A PLACEHOLDER for the function
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * that will be fixed in phase 2 of the development.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Currently ATAPI is not supported. ATAPI devices are threated as not-valid
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * devices.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * This function is not called, since scsi_sata_start() will bail-out prior
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * to calling it.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_txlt_atapi(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 struct buf *bp = spx->txlt_sata_pkt->satapkt_cmd.satacmd_bp;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst_t *shi = SATA_TXLT_HBA_INST(spx);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int cport = SATA_TXLT_CPORT(spx);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int rval;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int synch;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf union scsi_cdb *cdbp = (union scsi_cdb *)scsipkt->pkt_cdbp;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&(SATA_TXLT_CPORT_MUTEX(spx)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((rval = sata_txlt_generic_pkt_info(spx)) != TRAN_ACCEPT) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&(SATA_TXLT_CPORT_MUTEX(spx)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (rval);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
c03acfcad7780db4ddf763511a82026680b3b2c1ls * scmd->satacmd_flags.sata_data_direction default -
c03acfcad7780db4ddf763511a82026680b3b2c1ls * SATA_DIR_NODATA_XFER - is set by
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * sata_txlt_generic_pkt_info().
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (scmd->satacmd_bp) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (scmd->satacmd_bp->b_flags & B_READ) {
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_flags.sata_data_direction = SATA_DIR_READ;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_flags.sata_data_direction =
c03acfcad7780db4ddf763511a82026680b3b2c1ls SATA_DIR_WRITE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_acdb_len = scsi_cdb_size[GETGROUP(cdbp)];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_cmd_reg = SATAC_PACKET;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf bcopy(cdbp, scmd->satacmd_acdb, 16);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * For non-read/write commands we need to
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * map buffer
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf switch ((uint_t)scsipkt->pkt_cdbp[0]) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SCMD_READ:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SCMD_READ_G1:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SCMD_READ_G5:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SCMD_READ_G4:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SCMD_WRITE:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SCMD_WRITE_G1:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SCMD_WRITE_G5:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SCMD_WRITE_G4:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf default:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (bp->b_flags & (B_PHYS | B_PAGEIO))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf bp_mapin(bp);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
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_atapi_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_atapi_completion(spx->txlt_sata_pkt);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (TRAN_ACCEPT);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Translate command: Synchronize Cache.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Translates into Flush Cache command.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * (NO ATAPI implementation yet).
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * NOTE: We should check if Flush Cache is supported by the device (ATAPI
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * devices)
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_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);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int rval;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int synch;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&(SATA_TXLT_CPORT_MUTEX(spx)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((rval = sata_txlt_generic_pkt_info(spx)) != TRAN_ACCEPT) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&(SATA_TXLT_CPORT_MUTEX(spx)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (rval);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_addr_type = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_cmd_reg = SATAC_FLUSH_CACHE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_device_reg = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_sec_count_lsb = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_lba_low_lsb = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_lba_mid_lsb = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_lba_high_lsb = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_features_reg = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_status_reg = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_error_reg = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG1(SATA_DBG_SCSI_IF, spx->txlt_sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_txlt_synchronize_cache\n", NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (!(spx->txlt_sata_pkt->satapkt_op_mode & SATA_OPMODE_SYNCH)) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Need to set-up a callback function */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_sata_pkt->satapkt_comp =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_txlt_nodata_cmd_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 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
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
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 *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Note 2: No port multiplier support for now.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_hba_start(sata_pkt_txlate_t *spx, int *rval)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int stat;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst_t *sata_hba_inst = spx->txlt_sata_hba_inst;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_drive_info_t *sdinfo;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device_t sata_device;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf uint8_t cmd;
c03acfcad7780db4ddf763511a82026680b3b2c1ls struct sata_cmd_flags cmd_flags;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ASSERT(spx->txlt_sata_pkt != NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ASSERT(mutex_owned(&SATA_CPORT_MUTEX(spx->txlt_sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_sata_pkt->satapkt_device.satadev_addr.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? */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sdinfo->satadrv_event_flags & SATA_EVNT_CLEAR_DEVICE_RESET) {
c03acfcad7780db4ddf763511a82026680b3b2c1ls spx->txlt_sata_pkt->satapkt_cmd.satacmd_flags.
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_clear_dev_reset = B_TRUE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_event_flags &= ~SATA_EVNT_CLEAR_DEVICE_RESET;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG1(SATA_DBG_EVENTS, sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_hba_start: clearing device reset state\n", NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cmd = spx->txlt_sata_pkt->satapkt_cmd.satacmd_cmd_reg;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cmd_flags = spx->txlt_sata_pkt->satapkt_cmd.satacmd_flags;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device = spx->txlt_sata_pkt->satapkt_device; /* local copy */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_addr.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
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&(SATA_CPORT_MUTEX(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_addr.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 */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf switch (stat) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case 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);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
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 ==
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_ADDR_CPORT)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_log(sata_hba_inst, CE_CONT,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "port %d error",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_addr.cport);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf else
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_log(sata_hba_inst, CE_CONT,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "port %d pmport %d error\n",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_addr.cport,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf 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 */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_update_port_info(sata_hba_inst, &sata_device);
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 */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_addr.cport)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (void) sata_txlt_invalid_command(spx);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&(SATA_CPORT_MUTEX(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_addr.cport)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (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
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 */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf 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 */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_event_flags |=
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_EVNT_CLEAR_DEVICE_RESET;
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 |
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf 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;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense->es_add_code = SD_SCSI_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,
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw TQ_SLEEP) == 0)
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;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *lba = (*lba << 8) | sata_cmd->satacmd_lba_high_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));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense->es_valid = 1; /* Valid sense */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense->es_class = 7; /* Response code 0x70 - current err */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense->es_key = KEY_NO_SENSE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense->es_info_1 = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense->es_info_2 = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense->es_info_3 = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense->es_info_4 = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense->es_add_len = 6; /* Additional length */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense->es_cmd_info[0] = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense->es_cmd_info[1] = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense->es_cmd_info[2] = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense->es_cmd_info[3] = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense->es_add_code = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense->es_qual_code = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (sense);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
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;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
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;
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;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense->es_info_1 = (lba & 0xFF0000) >> 16;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense->es_info_1 = (lba & 0xFF00) >> 8;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense->es_info_1 = 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 =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SD_SCSI_UNREC_READ_ERROR;
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 =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SD_SCSI_WRITE_ERROR;
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:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* scsipkt->pkt_reason = CMD_TIMEOUT; */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsipkt->pkt_reason = CMD_INCOMPLETE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* No extended sense key ? */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SATA_PKT_ABORTED:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsipkt->pkt_reason = CMD_ABORTED;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* No extended sense key ? */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SATA_PKT_RESET:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsipkt->pkt_reason = CMD_RESET;
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
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((scsipkt->pkt_flags & FLAG_NOINTR) == 0 &&
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsipkt->pkt_comp != NULL)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* scsi callback required */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (*scsipkt->pkt_comp)(scsipkt);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * NON FUNCTIONAL IMPLEMENTATION. THIS IS A PLACE HOLDER.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * ATAPI devices are not supported currently (are not be attached recognized
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * as valid devices).
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Will be fixed in phase 2 of the development.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_txlt_atapi_completion(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_arq_status *arqs;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
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;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsipkt->pkt_resid = 0;
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 | STATE_ARQ_DONE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsipkt->pkt_reason = CMD_CMPLT;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
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
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf bcopy(sata_pkt->satapkt_cmd.satacmd_rqsense,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf &arqs->sts_sensedata, SATA_ATAPI_RQSENSE_LEN);
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 */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (*scsipkt->pkt_comp)(scsipkt);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
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
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_txlt_nodata_cmd_completion(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:
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 break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* No extended sense key - no info available */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SATA_PKT_TIMEOUT:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* scsipkt->pkt_reason = CMD_TIMEOUT; */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsipkt->pkt_reason = CMD_INCOMPLETE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* No extended sense key ? */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SATA_PKT_ABORTED:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsipkt->pkt_reason = CMD_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;
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 if ((scsipkt->pkt_flags & FLAG_NOINTR) == 0 &&
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsipkt->pkt_comp != NULL)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* scsi callback required */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (*scsipkt->pkt_comp)(scsipkt);
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
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((sata_id->ai_cmdset82 & SATA_LOOK_AHEAD) &&
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf !(sata_id->ai_features85 & SATA_LOOK_AHEAD)) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf page->dra = 1; /* Read Ahead disabled */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf page->rcd = 1; /* Read Cache disabled */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((sata_id->ai_cmdset82 & SATA_WRITE_CACHE) &&
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (sata_id->ai_features85 & SATA_WRITE_CACHE))
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;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_id->ai_cmdset82 & SATA_LOOK_AHEAD) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf page->dra = 1;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf page->rcd = 1;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_id->ai_cmdset82 & SATA_WRITE_CACHE)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf page->wce = 1;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (PAGELENGTH_DAD_MODE_CACHE_SCSI3 +
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf 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
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls return (PAGELENGTH_INFO_EXCPT + sizeof (struct mode_info_excpt_page));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Build Mode sense power condition page
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * NOT IMPLEMENTED.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_build_msense_page_1a(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/*
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
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * supported, quietly ignore them.
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 */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (PAGELENGTH_DAD_MODE_CACHE_SCSI3 +
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sizeof (struct mode_page) < parmlen) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *scsipkt->pkt_scbp = STATUS_CHECK;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense = sata_arq_sense(spx);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense->es_key = KEY_ILLEGAL_REQUEST;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sense->es_add_code = SD_SCSI_INVALID_FIELD_IN_PARAMETER_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 /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * We can manipulate only write cache and read ahead
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * (read cache) setting.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (!(sata_id->ai_cmdset82 & SATA_LOOK_AHEAD) &&
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf !(sata_id->ai_cmdset82 & SATA_WRITE_CACHE)) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * None of the features is supported - ignore
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *rval = TRAN_ACCEPT;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (SATA_SUCCESS);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Current setting of Read Ahead (and Read Cache) */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_id->ai_features85 & SATA_LOOK_AHEAD)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf dra = 0; /* 0 == not disabled */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf else
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf dra = 1;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Current setting of Write Cache */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_id->ai_features85 & SATA_WRITE_CACHE)
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 }
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) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Need to flip read ahead setting */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (dra == 0)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Disable read ahead / read cache */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_features_reg =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATAC_SF_DISABLE_READ_AHEAD;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf else
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Enable read ahead / read cache */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_features_reg =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATAC_SF_ENABLE_READ_AHEAD;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Transfer command to HBA */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_hba_start(spx, rval) != 0)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Pkt not accepted for execution.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (SATA_FAILURE);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *dmod = 1;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Now process return */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (spx->txlt_sata_pkt->satapkt_reason !=
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_PKT_COMPLETED) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf goto failure; /* Terminate */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Note that the packet is not removed, so it could be re-used */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (page->wce != wce) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Need to flip Write Cache setting */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (page->wce == 1)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Enable write cache */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_features_reg =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATAC_SF_ENABLE_WRITE_CACHE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf else
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Disable write cache */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_features_reg =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATAC_SF_DISABLE_WRITE_CACHE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Transfer command to HBA */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_hba_start(spx, rval) != 0)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Pkt not accepted for execution.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (SATA_FAILURE);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *dmod = 1;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Now process return */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (spx->txlt_sata_pkt->satapkt_reason !=
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_PKT_COMPLETED) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf goto 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".
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls *
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls * Return 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.
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 */
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls 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;
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls sense->es_add_code = SD_SCSI_INVALID_FIELD_IN_PARAMETER_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;
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls sense->es_add_code = SD_SCSI_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
c03acfcad7780db4ddf763511a82026680b3b2c1ls/*
c03acfcad7780db4ddf763511a82026680b3b2c1ls * sata_build_lsense_page0() is used to create the
c03acfcad7780db4ddf763511a82026680b3b2c1ls * SCSI LOG SENSE page 0 (supported log pages)
c03acfcad7780db4ddf763511a82026680b3b2c1ls *
c03acfcad7780db4ddf763511a82026680b3b2c1ls * Currently supported pages are 0, 0x10, 0x2f and 0x30
c03acfcad7780db4ddf763511a82026680b3b2c1ls * (supported log pages, self-test results, informational exceptions
c03acfcad7780db4ddf763511a82026680b3b2c1ls * and Sun vendor specific 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.
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;
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.
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) {
c03acfcad7780db4ddf763511a82026680b3b2c1ls int index;
c03acfcad7780db4ddf763511a82026680b3b2c1ls struct smart_ext_selftest_log_entry *entry;
c03acfcad7780db4ddf763511a82026680b3b2c1ls uint16_t block_num;
c03acfcad7780db4ddf763511a82026680b3b2c1ls int count;
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 */
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
c03acfcad7780db4ddf763511a82026680b3b2c1ls lpp->param_code[0] = 0;
c03acfcad7780db4ddf763511a82026680b3b2c1ls lpp->param_code[1] = count;
c03acfcad7780db4ddf763511a82026680b3b2c1ls lpp->param_ctrl_flags = 0;
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;
c03acfcad7780db4ddf763511a82026680b3b2c1ls add_sense_code = SD_SCSI_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];
c03acfcad7780db4ddf763511a82026680b3b2c1ls lpp->param_values[4] = 0;
c03acfcad7780db4ddf763511a82026680b3b2c1ls lpp->param_values[5] = 0;
c03acfcad7780db4ddf763511a82026680b3b2c1ls lpp->param_values[6] = entry->
c03acfcad7780db4ddf763511a82026680b3b2c1ls smart_ext_selftest_log_failing_lba[5];
c03acfcad7780db4ddf763511a82026680b3b2c1ls lpp->param_values[7] = entry->
c03acfcad7780db4ddf763511a82026680b3b2c1ls smart_ext_selftest_log_failing_lba[4];
c03acfcad7780db4ddf763511a82026680b3b2c1ls lpp->param_values[8] = entry->
c03acfcad7780db4ddf763511a82026680b3b2c1ls smart_ext_selftest_log_failing_lba[3];
c03acfcad7780db4ddf763511a82026680b3b2c1ls lpp->param_values[9] = entry->
c03acfcad7780db4ddf763511a82026680b3b2c1ls smart_ext_selftest_log_failing_lba[2];
c03acfcad7780db4ddf763511a82026680b3b2c1ls lpp->param_values[10] = entry->
c03acfcad7780db4ddf763511a82026680b3b2c1ls smart_ext_selftest_log_failing_lba[1];
c03acfcad7780db4ddf763511a82026680b3b2c1ls lpp->param_values[11] = entry->
c03acfcad7780db4ddf763511a82026680b3b2c1ls smart_ext_selftest_log_failing_lba[0];
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 =
c03acfcad7780db4ddf763511a82026680b3b2c1ls logdir.read_log_ext_nblks[0]
c03acfcad7780db4ddf763511a82026680b3b2c1ls [EXT_SMART_SELFTEST_LOG_PAGE
c03acfcad7780db4ddf763511a82026680b3b2c1ls - 1];
c03acfcad7780db4ddf763511a82026680b3b2c1ls block_num |= logdir.
c03acfcad7780db4ddf763511a82026680b3b2c1ls read_log_ext_nblks[1]
c03acfcad7780db4ddf763511a82026680b3b2c1ls [EXT_SMART_SELFTEST_LOG_PAGE
c03acfcad7780db4ddf763511a82026680b3b2c1ls - 1] << 8;
c03acfcad7780db4ddf763511a82026680b3b2c1ls --block_num;
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;
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
c03acfcad7780db4ddf763511a82026680b3b2c1ls lpp->param_code[0] = 0;
c03acfcad7780db4ddf763511a82026680b3b2c1ls lpp->param_code[1] = count;
c03acfcad7780db4ddf763511a82026680b3b2c1ls lpp->param_ctrl_flags = 0;
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;
c03acfcad7780db4ddf763511a82026680b3b2c1ls add_sense_code = SD_SCSI_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];
c03acfcad7780db4ddf763511a82026680b3b2c1ls lpp->param_values[4] = 0;
c03acfcad7780db4ddf763511a82026680b3b2c1ls lpp->param_values[5] = 0;
c03acfcad7780db4ddf763511a82026680b3b2c1ls lpp->param_values[6] = 0;
c03acfcad7780db4ddf763511a82026680b3b2c1ls lpp->param_values[7] = 0;
c03acfcad7780db4ddf763511a82026680b3b2c1ls lpp->param_values[8] = entry->
c03acfcad7780db4ddf763511a82026680b3b2c1ls smart_selftest_log_failing_lba[3];
c03acfcad7780db4ddf763511a82026680b3b2c1ls lpp->param_values[9] = entry->
c03acfcad7780db4ddf763511a82026680b3b2c1ls smart_selftest_log_failing_lba[2];
c03acfcad7780db4ddf763511a82026680b3b2c1ls lpp->param_values[10] = entry->
c03acfcad7780db4ddf763511a82026680b3b2c1ls smart_selftest_log_failing_lba[1];
c03acfcad7780db4ddf763511a82026680b3b2c1ls lpp->param_values[11] = entry->
c03acfcad7780db4ddf763511a82026680b3b2c1ls smart_selftest_log_failing_lba[0];
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->
c03acfcad7780db4ddf763511a82026680b3b2c1ls 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
c03acfcad7780db4ddf763511a82026680b3b2c1ls * SCSI LOG SENSE page 0x10 (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.
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 */
c03acfcad7780db4ddf763511a82026680b3b2c1ls lpp->param_values[0] = 0;
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
c03acfcad7780db4ddf763511a82026680b3b2c1ls lpp->param_values[2] = temp;
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
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/* ************************** LOCAL FUNCTIONS ************************** */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Validate sata_tran info
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * SATA_FAILURE returns if structure is inconsistent or structure revision
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * does not match one used by the framework.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Returns SATA_SUCCESS if sata_hba_tran has matching revision and contains
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * required function pointers.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Returns SATA_FAILURE otherwise.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_validate_sata_hba_tran(dev_info_t *dip, sata_hba_tran_t *sata_tran)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_tran->sata_tran_hba_rev != SATA_TRAN_HBA_REV) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_log(NULL, CE_WARN,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata: invalid sata_hba_tran version %d for driver %s",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_tran->sata_tran_hba_rev, ddi_driver_name(dip));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (SATA_FAILURE);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (dip != sata_tran->sata_tran_hba_dip) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_LOG_D((NULL, CE_WARN,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata: inconsistent sata_tran_hba_dip "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "%p / %p", sata_tran->sata_tran_hba_dip, dip));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (SATA_FAILURE);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_tran->sata_tran_probe_port == NULL ||
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_tran->sata_tran_start == NULL ||
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_tran->sata_tran_abort == NULL ||
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_tran->sata_tran_reset_dport == NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_LOG_D((NULL, CE_WARN, "sata: sata_hba_tran missing "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "required functions"));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (SATA_SUCCESS);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Remove HBA instance from sata_hba_list.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_remove_hba_instance(dev_info_t *dip)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst_t *sata_hba_inst;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&sata_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf for (sata_hba_inst = sata_hba_list;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst != (struct sata_hba_inst *)NULL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst = sata_hba_inst->satahba_next) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_hba_inst->satahba_dip == dip)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_hba_inst == (struct sata_hba_inst *)NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#ifdef SATA_DEBUG
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cmn_err(CE_WARN, "sata_remove_hba_instance: "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "unknown HBA instance\n");
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#endif
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ASSERT(FALSE);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_hba_inst == sata_hba_list) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_list = sata_hba_inst->satahba_next;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_hba_list) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_list->satahba_prev =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (struct sata_hba_inst *)NULL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_hba_inst == sata_hba_list_tail) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_list_tail = NULL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else if (sata_hba_inst == sata_hba_list_tail) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_list_tail = sata_hba_inst->satahba_prev;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_hba_list_tail) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_list_tail->satahba_next =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (struct sata_hba_inst *)NULL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst->satahba_prev->satahba_next =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst->satahba_next;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst->satahba_next->satahba_prev =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst->satahba_prev;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&sata_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Probe all SATA ports of the specified HBA instance.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * This function is called only from sata_hba_attach(). It does not have to
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * be protected by controller mutex, because the hba_attached flag is not set
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * yet and no one would be touching this HBA instance other then this thread.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Determines if port is active and what type of the device is attached
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * (if any). Allocates necessary structures for each port.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Creates attachment point minor node for each non-failed port.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_probe_ports(sata_hba_inst_t *sata_hba_inst)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf dev_info_t *dip = SATA_DIP(sata_hba_inst);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int ncport, npmport;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_cport_info_t *cportinfo;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_drive_info_t *drive;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_pmult_info_t *pminfo;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_pmport_info_t *pmportinfo;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device_t sata_device;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int rval;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf dev_t minor_number;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf char name[16];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Probe controller ports first, to find port status and
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * any port multiplier attached.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf for (ncport = 0; ncport < SATA_NUM_CPORTS(sata_hba_inst); ncport++) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* allocate cport structure */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo = kmem_zalloc(sizeof (sata_cport_info_t), KM_SLEEP);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ASSERT(cportinfo != NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_init(&cportinfo->cport_mutex, NULL, MUTEX_DRIVER, NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&cportinfo->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo->cport_addr.cport = ncport;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo->cport_addr.pmport = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo->cport_addr.qual = SATA_ADDR_CPORT;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo->cport_state &= ~SATA_PORT_STATE_CLEAR_MASK;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo->cport_state |= SATA_STATE_PROBING;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_CPORT_INFO(sata_hba_inst, ncport) = cportinfo;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Regardless if a port is usable or not, create
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * an attachment point
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&cportinfo->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf minor_number =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_MAKE_AP_MINOR(ddi_get_instance(dip), ncport, 0, 0);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (void) sprintf(name, "%d", ncport);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (ddi_create_minor_node(dip, name, S_IFCHR,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf minor_number, DDI_NT_SATA_ATTACHMENT_POINT, 0) !=
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf DDI_SUCCESS) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_log(sata_hba_inst, CE_WARN, "sata_hba_attach: "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "cannot create sata attachment point for port %d",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ncport);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Probe port */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_addr.cport = ncport;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_addr.pmport = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_addr.qual = SATA_ADDR_CPORT;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_rev = SATA_DEVICE_REV;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rval = (*SATA_PROBE_PORT_FUNC(sata_hba_inst))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (dip, &sata_device);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&cportinfo->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_update_port_scr(&cportinfo->cport_scr, &sata_device);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (rval != SATA_SUCCESS) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Something went wrong? Fail the port */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo->cport_state = SATA_PSTATE_FAILED;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&cportinfo->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf continue;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo->cport_state &= ~SATA_STATE_PROBING;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo->cport_state |= SATA_STATE_PROBED;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo->cport_dev_type = sata_device.satadev_type;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo->cport_state |= SATA_STATE_READY;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (cportinfo->cport_dev_type == SATA_DTYPE_NONE) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&cportinfo->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf continue;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (cportinfo->cport_dev_type != SATA_DTYPE_PMULT) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * There is some device attached.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Allocate device info structure
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&cportinfo->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf drive = kmem_zalloc(sizeof (sata_drive_info_t),
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf KM_SLEEP);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&cportinfo->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_CPORTINFO_DRV_INFO(cportinfo) = drive;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf drive->satadrv_addr = cportinfo->cport_addr;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf drive->satadrv_addr.qual = SATA_ADDR_DCPORT;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf drive->satadrv_type = cportinfo->cport_dev_type;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf drive->satadrv_state = SATA_STATE_UNKNOWN;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ASSERT(cportinfo->cport_dev_type == SATA_DTYPE_PMULT);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&cportinfo->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf pminfo = kmem_zalloc(sizeof (sata_pmult_info_t),
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf KM_SLEEP);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&cportinfo->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ASSERT(pminfo != NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_CPORTINFO_PMULT_INFO(cportinfo) = pminfo;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf pminfo->pmult_addr.cport = cportinfo->cport_addr.cport;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf pminfo->pmult_addr.pmport = SATA_PMULT_HOSTPORT;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf pminfo->pmult_addr.qual = SATA_ADDR_PMPORT;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf pminfo->pmult_num_dev_ports =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_add_info;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_init(&pminfo->pmult_mutex, NULL, MUTEX_DRIVER,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf pminfo->pmult_state = SATA_STATE_PROBING;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Probe Port Multiplier ports */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf for (npmport = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf npmport < pminfo->pmult_num_dev_ports;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf npmport++) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&cportinfo->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf pmportinfo = kmem_zalloc(
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sizeof (sata_pmport_info_t), KM_SLEEP);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&cportinfo->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ASSERT(pmportinfo != NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf pmportinfo->pmport_addr.cport = ncport;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf pmportinfo->pmport_addr.pmport = npmport;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf pmportinfo->pmport_addr.qual =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_ADDR_PMPORT;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf pminfo->pmult_dev_port[npmport] = pmportinfo;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_init(&pmportinfo->pmport_mutex, NULL,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf MUTEX_DRIVER, NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_addr.pmport = npmport;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_addr.qual =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_ADDR_PMPORT;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&cportinfo->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Create an attachment point */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf minor_number = SATA_MAKE_AP_MINOR(
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ddi_get_instance(dip), ncport, npmport, 1);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (void) sprintf(name, "%d.%d", ncport, npmport);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (ddi_create_minor_node(dip, name, S_IFCHR,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf minor_number, DDI_NT_SATA_ATTACHMENT_POINT,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf 0) != DDI_SUCCESS) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_log(sata_hba_inst, CE_WARN,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_hba_attach: "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "cannot create sata attachment "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "point for port %d pmult port %d",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ncport, npmport);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rval = (*SATA_PROBE_PORT_FUNC(sata_hba_inst))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (dip, &sata_device);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&cportinfo->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* sata_update_port_info() */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_update_port_scr(&pmportinfo->pmport_scr,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf &sata_device);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (rval != SATA_SUCCESS) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf pmportinfo->pmport_state =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_PSTATE_FAILED;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf continue;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf pmportinfo->pmport_state &=
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ~SATA_STATE_PROBING;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf pmportinfo->pmport_state |= SATA_STATE_PROBED;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf pmportinfo->pmport_dev_type =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_type;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf pmportinfo->pmport_state |= SATA_STATE_READY;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (pmportinfo->pmport_dev_type ==
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_DTYPE_NONE)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf continue;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Port multipliers cannot be chained */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ASSERT(pmportinfo->pmport_dev_type !=
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_DTYPE_PMULT);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * There is something attached to Port
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Multiplier device port
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Allocate device info structure
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&cportinfo->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf drive = kmem_zalloc(
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sizeof (sata_drive_info_t), KM_SLEEP);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rval = (*SATA_PROBE_PORT_FUNC(sata_hba_inst))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (dip, &sata_device);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&cportinfo->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* sata_update_port_info() */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_update_port_scr(&pmportinfo->pmport_scr,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf &sata_device);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf pmportinfo->pmport_sata_drive = drive;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf drive->satadrv_addr.cport =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf pmportinfo->pmport_addr.cport;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf drive->satadrv_addr.pmport = npmport;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf drive->satadrv_addr.qual = SATA_ADDR_DPMPORT;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf drive->satadrv_type = pmportinfo->
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf pmport_dev_type;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf drive->satadrv_state = SATA_STATE_UNKNOWN;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf pmportinfo->pmport_state =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_STATE_PROBED | SATA_STATE_READY;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&cportinfo->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Create SATA device nodes for specified HBA instance (SCSI target
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * device nodes).
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * This function is called only from sata_hba_attach(). The hba_attached flag
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * is not set yet, so no ports or device data structures would be touched
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * by anyone other then this thread, therefore per-port mutex protection is
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * not needed.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * The assumption is that there are no target and attachment point minor nodes
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * created by the boot subsystems, so we do not need to prune device tree.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * An AP (Attachement Point) node is created for each SATA device port even
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * when there is no device attached.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * A target node is created when there is a supported type of device attached,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * but may be removed if it cannot be put online.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * This function cannot be called from an interrupt context.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * ONLY DISK TARGET NODES ARE CREATED NOW
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_make_device_nodes(dev_info_t *pdip, sata_hba_inst_t *sata_hba_inst)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int ncport, npmport;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_cport_info_t *cportinfo;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_pmult_info_t *pminfo;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_pmport_info_t *pmportinfo;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf dev_info_t *cdip; /* child dip */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device_t sata_device;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int rval;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw * Walk through pre-probed sata ports info in sata_hba_inst structure
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf for (ncport = 0; ncport < SATA_NUM_CPORTS(sata_hba_inst); ncport++) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo = SATA_CPORT_INFO(sata_hba_inst, ncport);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&cportinfo->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (!(cportinfo->cport_state & SATA_STATE_PROBED)) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&cportinfo->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf continue;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (cportinfo->cport_state == SATA_PSTATE_FAILED) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&cportinfo->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf continue;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (cportinfo->cport_dev_type == SATA_DTYPE_NONE) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* No device attached to the controller port */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&cportinfo->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf continue;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Some device is attached to a controller port.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * We rely on controllers distinquishing between no-device,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * attached port multiplier and other kind of attached device.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * We need to get Identify Device data and determine
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * positively the dev type before trying to attach
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * the target driver.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_rev = SATA_DEVICE_REV;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (cportinfo->cport_dev_type != SATA_DTYPE_PMULT) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Not port multiplier.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_addr = cportinfo->cport_addr;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_addr.qual = SATA_ADDR_DCPORT;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&cportinfo->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rval = sata_probe_device(sata_hba_inst, &sata_device);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (rval != SATA_SUCCESS ||
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_type == SATA_DTYPE_UNKNOWN)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf continue;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&cportinfo->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((sata_device.satadev_type &
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_VALID_DEV_TYPE) == 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Could not determine device type or
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * a device is not supported.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Degrade this device to unknown.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo->cport_dev_type = SATA_DTYPE_UNKNOWN;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&cportinfo->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf continue;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo->cport_dev_type = sata_device.satadev_type;
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw mutex_exit(&cportinfo->cport_mutex);
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw if (sata_initialize_device(sata_hba_inst,
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw SATA_CPORTINFO_DRV_INFO(cportinfo)) != SATA_SUCCESS)
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw /* Retry */
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw (void) sata_initialize_device(sata_hba_inst,
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw SATA_CPORTINFO_DRV_INFO(cportinfo));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw mutex_enter(&cportinfo->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_show_drive_info(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_CPORTINFO_DRV_INFO(cportinfo));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&cportinfo->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cdip = sata_create_target_node(pdip, sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf &sata_device.satadev_addr);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&cportinfo->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (cdip == NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Attaching target node failed.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * We retain sata_drive_info structure...
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (SATA_CPORTINFO_DRV_INFO(cportinfo))->
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf satadrv_type = SATA_DTYPE_UNKNOWN;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (SATA_CPORTINFO_DRV_INFO(cportinfo))->
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf satadrv_state = SATA_STATE_UNKNOWN;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo->cport_dev_type = SATA_DTYPE_UNKNOWN;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&cportinfo->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf continue;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (SATA_CPORTINFO_DRV_INFO(cportinfo))->
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf satadrv_state = SATA_STATE_READY;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* This must be Port Multiplier type */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (cportinfo->cport_dev_type != SATA_DTYPE_PMULT) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_LOG_D((sata_hba_inst, CE_WARN,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_make_device_nodes: "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "unknown dev type %x",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo->cport_dev_type));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&cportinfo->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf continue;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf pminfo = SATA_CPORTINFO_PMULT_INFO(cportinfo);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf for (npmport = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf npmport < pminfo->pmult_num_dev_ports;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf npmport++) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf pmportinfo = pminfo->pmult_dev_port[npmport];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (pmportinfo->pmport_state &
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_PSTATE_FAILED) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf continue;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (pmportinfo->pmport_dev_type &
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_DTYPE_NONE)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* No device attached */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf continue;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_addr =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf pmportinfo->pmport_addr;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_addr.qual =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_ADDR_DPMPORT;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&cportinfo->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rval = sata_probe_device(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf &sata_device);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (rval != SATA_SUCCESS ||
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_type ==
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_DTYPE_UNKNOWN) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&cportinfo->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf continue;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&cportinfo->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((sata_device.satadev_type &
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_VALID_DEV_TYPE) == 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Could not determine device type.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Degrade this device to unknown.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf pmportinfo->pmport_dev_type =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_DTYPE_UNKNOWN;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf continue;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf pmportinfo->pmport_dev_type =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_type;
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw mutex_exit(&cportinfo->cport_mutex);
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw if (sata_initialize_device(sata_hba_inst,
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw pmportinfo->pmport_sata_drive) !=
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw SATA_SUCCESS)
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw /* Retry */
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw (void) sata_initialize_device(
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw sata_hba_inst,
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw pmportinfo->pmport_sata_drive);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw mutex_enter(&cportinfo->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_show_drive_info(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf pmportinfo->pmport_sata_drive);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&cportinfo->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cdip = sata_create_target_node(pdip,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst, &sata_device.satadev_addr);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&cportinfo->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (cdip == NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Attaching target node failed.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * We retain sata_drive_info
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * structure...
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf pmportinfo->pmport_sata_drive->
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf satadrv_type = SATA_DTYPE_UNKNOWN;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf pmportinfo->pmport_sata_drive->
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf satadrv_state = SATA_STATE_UNKNOWN;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf pmportinfo->pmport_dev_type =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_DTYPE_UNKNOWN;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf continue;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf pmportinfo->pmport_sata_drive->
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf satadrv_state |= SATA_STATE_READY;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&cportinfo->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Create scsi target node for attached device, create node properties and
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * attach the node.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * The node could be removed if the device onlining fails.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * A dev_info_t pointer is returned if operation is successful, NULL is
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * returned otherwise.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic dev_info_t *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_create_target_node(dev_info_t *dip, sata_hba_inst_t *sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_address_t *sata_addr)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf dev_info_t *cdip = NULL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int rval;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf char *nname = NULL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf char **compatible = NULL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int ncompatible;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf struct scsi_inquiry inq;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device_t sata_device;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_drive_info_t *sdinfo;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int target;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int i;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_rev = SATA_DEVICE_REV;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_addr = *sata_addr;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&(SATA_CPORT_MUTEX(sata_hba_inst, sata_addr->cport)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo = sata_get_device_info(sata_hba_inst, &sata_device);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf target = SATA_TO_SCSI_TARGET(sata_addr->cport,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_addr->pmport, sata_addr->qual);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sdinfo == NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_addr->cport)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_LOG_D((sata_hba_inst, CE_WARN,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_create_target_node: no sdinfo for target %x",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf target));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * create scsi inquiry data, expected by
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * scsi_hba_nodename_compatible_get()
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_identdev_to_inquiry(sata_hba_inst, sdinfo, (uint8_t *)&inq);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst, sata_addr->cport)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* determine the node name and compatible */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsi_hba_nodename_compatible_get(&inq, NULL,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf inq.inq_dtype, NULL, &nname, &compatible, &ncompatible);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#ifdef SATA_DEBUG
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_debug_flags & SATA_DBG_NODES) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (nname == NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cmn_err(CE_NOTE, "sata_create_target_node: "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "cannot determine nodename for target %d\n",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf target);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cmn_err(CE_WARN, "sata_create_target_node: "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "target %d nodename: %s\n", target, nname);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (compatible == NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cmn_err(CE_WARN,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_create_target_node: no compatible name\n");
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf for (i = 0; i < ncompatible; i++) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cmn_err(CE_WARN, "sata_create_target_node: "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "compatible name: %s\n", compatible[i]);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#endif
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* if nodename can't be determined, log error and exit */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (nname == NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_LOG_D((sata_hba_inst, CE_WARN,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_create_target_node: cannot determine nodename "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "for target %d\n", target));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsi_hba_nodename_compatible_free(nname, compatible);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Create scsi target node
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ndi_devi_alloc_sleep(dip, nname, (pnode_t)DEVI_SID_NODEID, &cdip);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rval = ndi_prop_update_string(DDI_DEV_T_NONE, cdip,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "device-type", "scsi");
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (rval != DDI_PROP_SUCCESS) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_LOG_D((sata_hba_inst, CE_WARN, "sata_create_target_node: "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "updating device_type prop failed %d", rval));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf goto fail;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Create target node properties: target & lun
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rval = ndi_prop_update_int(DDI_DEV_T_NONE, cdip, "target", target);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (rval != DDI_PROP_SUCCESS) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_LOG_D((sata_hba_inst, CE_WARN, "sata_create_target_node: "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "updating target prop failed %d", rval));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf goto fail;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rval = ndi_prop_update_int(DDI_DEV_T_NONE, cdip, "lun", 0);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (rval != DDI_PROP_SUCCESS) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_LOG_D((sata_hba_inst, CE_WARN, "sata_create_target_node: "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "updating target prop failed %d", rval));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf goto fail;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* decorate the node with compatible */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (ndi_prop_update_string_array(DDI_DEV_T_NONE, cdip, "compatible",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf compatible, ncompatible) != DDI_PROP_SUCCESS) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_LOG_D((sata_hba_inst, CE_WARN,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_create_target_node: FAIL compatible props cdip 0x%p",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (void *)cdip));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf goto fail;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw /*
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw * Set default write cache mode
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw */
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw rval = sata_init_write_cache_mode(sata_hba_inst, sdinfo);
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw if (rval != SATA_SUCCESS) {
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw sata_log(sata_hba_inst, CE_WARN, "sata_create_target_node: "
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw "cannot set deafult write cache mode for "
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw "device at port %d", sata_addr->cport);
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw }
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Now, try to attach the driver. If probing of the device fails,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * the target node may be removed
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rval = ndi_devi_online(cdip, NDI_ONLINE_ATTACH);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsi_hba_nodename_compatible_free(nname, compatible);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (rval == NDI_SUCCESS)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (cdip);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* target node was removed - are we sure? */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlffail:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsi_hba_nodename_compatible_free(nname, compatible);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ddi_prop_remove_all(cdip);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rval = ndi_devi_free(cdip);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (rval != NDI_SUCCESS) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_LOG_D((sata_hba_inst, CE_WARN, "sata_create_target_node: "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "node removal failed %d", rval));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_log(sata_hba_inst, CE_WARN, "sata_create_target_node: "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "cannot create target node for device at port %d",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_addr->cport);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Re-probe sata port, check for a device and attach necessary info
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * structures when necessary. Identify Device data is fetched, if possible.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Assumption: sata address is already validated.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * SATA_SUCCESS is returned if port is re-probed sucessfully, regardless of
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * the presence of a device and its type.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * SATA_FAILURE is returned if one of the operations failed.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_reprobe_port(sata_hba_inst_t *sata_hba_inst, sata_device_t *sata_device)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_cport_info_t *cportinfo;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_drive_info_t *sdinfo;
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw boolean_t init_device = B_FALSE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int rval;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* We only care about host sata cport for now */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo = SATA_CPORT_INFO(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device->satadev_addr.cport);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* probe port */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&cportinfo->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo->cport_state &= ~SATA_PORT_STATE_CLEAR_MASK;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo->cport_state |= SATA_STATE_PROBING;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&cportinfo->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rval = (*SATA_PROBE_PORT_FUNC(sata_hba_inst))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (SATA_DIP(sata_hba_inst), sata_device);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&cportinfo->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (rval != SATA_SUCCESS) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo->cport_state = SATA_PSTATE_FAILED;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&cportinfo->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_LOG_D((sata_hba_inst, CE_WARN, "sata_hba_ioctl: "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "connect: port probbing failed"));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (SATA_FAILURE);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * update sata port state and set device type
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_update_port_info(sata_hba_inst, sata_device);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo->cport_state |= SATA_STATE_PROBED;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Sanity check - Port is active? Is the link active?
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Is there any device attached?
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((cportinfo->cport_state &
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (SATA_PSTATE_SHUTDOWN | SATA_PSTATE_FAILED)) ||
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (cportinfo->cport_scr.sstatus & SATA_PORT_DEVLINK_UP_MASK) !=
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_PORT_DEVLINK_UP) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Port in non-usable state or no link active/no device.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Free info structure if necessary (direct attached drive
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * only, for now!
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo = SATA_CPORTINFO_DRV_INFO(cportinfo);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_CPORTINFO_DRV_INFO(cportinfo) = NULL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Add here differentiation for device attached or not */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo->cport_dev_type = SATA_DTYPE_NONE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&cportinfo->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sdinfo != NULL)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf kmem_free(sdinfo, sizeof (sata_drive_info_t));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (SATA_SUCCESS);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo->cport_state |= SATA_STATE_READY;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo->cport_dev_type = sata_device->satadev_type;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo = SATA_CPORTINFO_DRV_INFO(cportinfo);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * If we are re-probing the port, there may be
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * sata_drive_info structure attached
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * (or sata_pm_info, if PMult is supported).
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_device->satadev_type == SATA_DTYPE_NONE) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * There is no device, so remove device info structure,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * if necessary. Direct attached drive only!
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_CPORTINFO_DRV_INFO(cportinfo) = NULL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo->cport_dev_type = SATA_DTYPE_NONE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sdinfo != NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf kmem_free(sdinfo, sizeof (sata_drive_info_t));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_log(sata_hba_inst, CE_WARN,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "SATA device detached "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "from port %d", cportinfo->cport_addr.cport);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&cportinfo->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (SATA_SUCCESS);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_device->satadev_type != SATA_DTYPE_PMULT) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sdinfo == NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * There is some device attached, but there is
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * no sata_drive_info structure - allocate one
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&cportinfo->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo = kmem_zalloc(
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sizeof (sata_drive_info_t), KM_SLEEP);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&cportinfo->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Recheck, if port state did not change when we
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * released mutex.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (cportinfo->cport_state & SATA_STATE_READY) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_CPORTINFO_DRV_INFO(cportinfo) = sdinfo;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_addr = cportinfo->cport_addr;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_addr.qual = SATA_ADDR_DCPORT;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_type = SATA_DTYPE_UNKNOWN;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_state = SATA_STATE_UNKNOWN;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Port is not in ready state, we
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * cannot attach a device.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&cportinfo->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf kmem_free(sdinfo, sizeof (sata_drive_info_t));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (SATA_SUCCESS);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw /*
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw * Since we are adding device, presumably new one,
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw * indicate that it should be initalized,
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw * as well as some internal framework states).
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw */
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw init_device = B_TRUE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo->cport_dev_type = SATA_DTYPE_UNKNOWN;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device->satadev_addr.qual = sdinfo->satadrv_addr.qual;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo->cport_dev_type = SATA_DTYPE_UNKNOWN;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&cportinfo->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (SATA_SUCCESS);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&cportinfo->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Figure out what kind of device we are really
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * dealing with.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw rval = sata_probe_device(sata_hba_inst, sata_device);
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw /* Set initial device features, if necessary */
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw if (rval == SATA_SUCCESS && init_device == B_TRUE) {
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw if (sata_initialize_device(sata_hba_inst, sdinfo) !=
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw SATA_SUCCESS)
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw /* retry */
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw (void) sata_initialize_device(sata_hba_inst, sdinfo);
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw }
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw return (rval);
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw}
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw/*
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw * Initialize device
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw * Specified device is initialized to a default state.
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw * At this point only read cache and UDMA modes are set here.
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw * Write cache mode should be set when a disk is configured.
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw *
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw * Only SATA disks are initialized for now.
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw *
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw * Returns SATA_SUCCESS if all device features are set successfully,
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw * SATA_FAILURE otherwise
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw */
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelwstatic int
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelwsata_initialize_device(sata_hba_inst_t *sata_hba_inst,
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw sata_drive_info_t *sdinfo)
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw{
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw sata_save_drive_settings(sdinfo);
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw sdinfo->satadrv_settings |= SATA_DEV_READ_AHEAD;
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw return (sata_set_drive_features(sata_hba_inst, sdinfo, 0));
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw}
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw/*
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw * Initialize write cache mode.
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw *
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw * The default write cache setting is provided by sata_write_cache
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw * static variable:
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw * 1 - enable
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw * 0 - disable
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw * any other value - current drive setting
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw *
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw * In the future, it may be overridden by the
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw * disk-write-cache-enable property setting, if it is defined.
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw * Returns SATA_SUCCESS if all device features are set successfully,
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw * SATA_FAILURE otherwise.
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw */
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelwstatic int
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelwsata_init_write_cache_mode(sata_hba_inst_t *sata_hba_inst,
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw sata_drive_info_t *sdinfo)
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw{
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw if (sata_write_cache == 1)
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw sdinfo->satadrv_settings |= SATA_DEV_WRITE_CACHE;
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw else if (sata_write_cache == 0)
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw sdinfo->satadrv_settings &= ~SATA_DEV_WRITE_CACHE;
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw /*
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw * When sata_write_cache value is not 0 or 1,
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw * a current setting of the drive's write cache is used.
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw *
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw * Now set the write cache mode
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw */
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw return (sata_set_drive_features(sata_hba_inst, sdinfo, 0));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Validate sata address.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Specified cport, pmport and qualifier has to match
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * passed sata_scsi configuration info.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * The presence of an attached device is not verified.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Returns 0 when address is valid, -1 otherwise.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_validate_sata_address(sata_hba_inst_t *sata_hba_inst, int cport,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int pmport, int qual)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (qual == SATA_ADDR_DCPORT && pmport != 0)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf goto invalid_address;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (cport >= SATA_NUM_CPORTS(sata_hba_inst))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf goto invalid_address;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((qual == SATA_ADDR_DPMPORT || qual == SATA_ADDR_PMPORT) &&
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ((SATA_CPORT_DEV_TYPE(sata_hba_inst, cport) != SATA_DTYPE_PMULT) ||
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (SATA_PMULT_INFO(sata_hba_inst, cport) == NULL) ||
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (pmport >= SATA_NUM_PMPORTS(sata_hba_inst, cport))))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf goto invalid_address;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (0);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfinvalid_address:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (-1);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Validate scsi address
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * SCSI target address is translated into SATA cport/pmport and compared
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * with a controller port/device configuration. LUN has to be 0.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Returns 0 if a scsi target refers to an attached device,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * returns 1 if address is valid but device is not attached,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * returns -1 if bad address or device is of an unsupported type.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Upon return sata_device argument is set.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_validate_scsi_address(sata_hba_inst_t *sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf struct scsi_address *ap, sata_device_t *sata_device)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int cport, pmport, qual, rval;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rval = -1; /* Invalid address */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (ap->a_lun != 0)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf goto out;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf qual = SCSI_TO_SATA_ADDR_QUAL(ap->a_target);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport = SCSI_TO_SATA_CPORT(ap->a_target);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf pmport = SCSI_TO_SATA_PMPORT(ap->a_target);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (qual != SATA_ADDR_DCPORT && qual != SATA_ADDR_DPMPORT)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf goto out;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_validate_sata_address(sata_hba_inst, cport, pmport, qual) ==
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_cport_info_t *cportinfo;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_pmult_info_t *pmultinfo;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_drive_info_t *sdinfo = NULL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rval = 1; /* Valid sata address */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo = SATA_CPORT_INFO(sata_hba_inst, cport);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (qual == SATA_ADDR_DCPORT) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (cportinfo == NULL ||
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo->cport_dev_type == SATA_DTYPE_NONE)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf goto out;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (cportinfo->cport_dev_type == SATA_DTYPE_PMULT ||
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (cportinfo->cport_dev_type &
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_VALID_DEV_TYPE) == 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rval = -1;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf goto out;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo = SATA_CPORTINFO_DRV_INFO(cportinfo);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else if (qual == SATA_ADDR_DPMPORT) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf pmultinfo = SATA_CPORTINFO_PMULT_INFO(cportinfo);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (pmultinfo == NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rval = -1;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf goto out;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (SATA_PMPORT_INFO(sata_hba_inst, cport, pmport) ==
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf NULL ||
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_PMPORT_DEV_TYPE(sata_hba_inst, cport,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf pmport) == SATA_DTYPE_NONE)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf goto out;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo = SATA_PMPORT_DRV_INFO(sata_hba_inst, cport,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf pmport);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rval = -1;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf goto out;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((sdinfo == NULL) ||
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (sdinfo->satadrv_type & SATA_VALID_DEV_TYPE) == 0)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf goto out;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device->satadev_type = sdinfo->satadrv_type;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device->satadev_addr.qual = qual;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device->satadev_addr.cport = cport;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device->satadev_addr.pmport = pmport;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device->satadev_rev = SATA_DEVICE_REV_1;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (0);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfout:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (rval == 1) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG2(SATA_DBG_SCSI_IF, sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_validate_scsi_address: no valid target %x lun %x",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ap->a_target, ap->a_lun);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (rval);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Find dip corresponding to passed device number
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Returns NULL if invalid device number is passed or device cannot be found,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Returns dip is device is found.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic dev_info_t *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_devt_to_devinfo(dev_t dev)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf dev_info_t *dip;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#ifndef __lock_lint
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf struct devnames *dnp;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf major_t major = getmajor(dev);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int instance = SATA_MINOR2INSTANCE(getminor(dev));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (major >= devcnt)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf dnp = &devnamesp[major];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf LOCK_DEV_OPS(&(dnp->dn_lock));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf dip = dnp->dn_head;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf while (dip && (ddi_get_instance(dip) != instance)) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf dip = ddi_get_next(dip);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf UNLOCK_DEV_OPS(&(dnp->dn_lock));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#endif
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (dip);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Probe device.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * This function issues Identify Device command and initialize local
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * sata_drive_info structure if the device can be identified.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * The device type is determined by examining Identify Device
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * command response.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * If the sata_hba_inst has linked drive info structure for this
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * device address, the Identify Device data is stored into sata_drive_info
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * structure linked to the port info structure.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * sata_device has to refer to the valid sata port(s) for HBA described
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * by sata_hba_inst structure.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Returns: SATA_SUCCESS if device type was successfully probed and port-linked
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * drive info structure was updated;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * SATA_FAILURE if there is no device, or device was not probed
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * successully.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * If a device cannot be identified, sata_device's dev_state and dev_type
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * fields are set to unknown.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_probe_device(sata_hba_inst_t *sata_hba_inst, sata_device_t *sata_device)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_drive_info_t *sdinfo;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_drive_info_t new_sdinfo; /* local drive info struct */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int retry_cnt;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ASSERT((SATA_CPORT_STATE(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device->satadev_addr.cport) &
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (SATA_STATE_PROBED | SATA_STATE_READY)) != 0);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device->satadev_type = SATA_DTYPE_NONE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&(SATA_CPORT_MUTEX(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device->satadev_addr.cport)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Get pointer to port-linked sata device info structure */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo = sata_get_device_info(sata_hba_inst, sata_device);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sdinfo != NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_state &=
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ~(SATA_STATE_PROBED | SATA_STATE_READY);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_state |= SATA_STATE_PROBING;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* No device to probe */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device->satadev_addr.cport)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device->satadev_type = SATA_DTYPE_NONE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device->satadev_state = SATA_STATE_UNKNOWN;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (SATA_FAILURE);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Need to issue both types of identify device command and
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * determine device type by examining retreived data/status.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * First, ATA Identify Device.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf bzero(&new_sdinfo, sizeof (sata_drive_info_t));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf new_sdinfo.satadrv_addr = sata_device->satadev_addr;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device->satadev_addr.cport)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf for (retry_cnt = 0; retry_cnt <= SATA_DEVICE_IDENTIFY_RETRY;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf retry_cnt++) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf new_sdinfo.satadrv_type = SATA_DTYPE_ATADISK;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_identify_device(sata_hba_inst, &new_sdinfo) == 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Got something responding to ATA Identify Device */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device->satadev_type = new_sdinfo.satadrv_type;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (SATA_FEATURES(sata_hba_inst) & SATA_CTLF_ATAPI) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * HBA supports ATAPI - try to issue Identify Packet
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Device command.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf new_sdinfo.satadrv_type = SATA_DTYPE_ATAPICD;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_identify_device(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf &new_sdinfo) == 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Got something responding to Identify Packet
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Device cmd.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Set UDMA mode here as well ? - phase 2 */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device->satadev_type =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf new_sdinfo.satadrv_type;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (retry_cnt <= SATA_DEVICE_IDENTIFY_RETRY) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* save device info, if possible */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&(SATA_CPORT_MUTEX(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device->satadev_addr.cport)));
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 (SATA_FAILURE);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Copy drive info into the port-linked drive info structure.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *sdinfo = new_sdinfo;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_state &= ~SATA_STATE_PROBING;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_state |= SATA_STATE_PROBED;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_device->satadev_addr.qual == SATA_ADDR_DCPORT)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_CPORT_DEV_TYPE(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device->satadev_addr.cport) =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_type;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf else /* SATA_ADDR_DPMPORT */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_PMPORT_DEV_TYPE(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device->satadev_addr.cport,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device->satadev_addr.pmport) =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_type;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device->satadev_addr.cport)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (SATA_SUCCESS);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlffailure:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Looks like we cannot determine the device type.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&(SATA_CPORT_MUTEX(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device->satadev_addr.cport)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo = sata_get_device_info(sata_hba_inst, sata_device);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sdinfo != NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device->satadev_type = SATA_DTYPE_UNKNOWN;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_type = SATA_DTYPE_UNKNOWN;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_state &= ~SATA_STATE_PROBING;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_state = SATA_STATE_PROBED;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_device->satadev_addr.qual == SATA_ADDR_DCPORT)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_CPORT_DEV_TYPE(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device->satadev_addr.cport) =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_DTYPE_UNKNOWN;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* SATA_ADDR_DPMPORT */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((SATA_PMULT_INFO(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device->satadev_addr.cport) != NULL) &&
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (SATA_PMPORT_INFO(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device->satadev_addr.cport,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device->satadev_addr.pmport) != NULL))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_PMPORT_DEV_TYPE(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device->satadev_addr.cport,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device->satadev_addr.pmport) =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_DTYPE_UNKNOWN;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device->satadev_addr.cport)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (SATA_FAILURE);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Get pointer to sata_drive_info structure.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * The sata_device has to contain address (cport, pmport and qualifier) for
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * specified sata_scsi structure.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Returns NULL if device address is not valid for this HBA configuration.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Otherwise, returns a pointer to sata_drive_info structure.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * This function should be called with a port mutex held.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic sata_drive_info_t *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_get_device_info(sata_hba_inst_t *sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device_t *sata_device)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf uint8_t cport = sata_device->satadev_addr.cport;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf uint8_t pmport = sata_device->satadev_addr.pmport;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf uint8_t qual = sata_device->satadev_addr.qual;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (cport >= SATA_NUM_CPORTS(sata_hba_inst))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (!(SATA_CPORT_STATE(sata_hba_inst, cport) &
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (SATA_STATE_PROBED | SATA_STATE_READY)))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Port not probed yet */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (SATA_CPORT_DEV_TYPE(sata_hba_inst, cport) == SATA_DTYPE_NONE)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (qual == SATA_ADDR_DCPORT) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Request for a device on a controller port */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (SATA_CPORT_DEV_TYPE(sata_hba_inst, cport) ==
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_DTYPE_PMULT)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Port multiplier attached */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (SATA_CPORT_DRV_INFO(sata_hba_inst, cport));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (qual == SATA_ADDR_DPMPORT) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (SATA_CPORT_DEV_TYPE(sata_hba_inst, cport) !=
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_DTYPE_PMULT)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (pmport > SATA_NUM_PMPORTS(sata_hba_inst, cport))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (SATA_PMPORT_DRV_INFO(sata_hba_inst, cport, pmport));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* we should not get here */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * sata_identify_device.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Send Identify Device command to SATA HBA driver.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * If command executes successfully, update sata_drive_info structure pointed
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * to by sdinfo argument, including Identify Device data.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * If command fails, invalidate data in sata_drive_info.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Cannot be called from interrupt level.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Returns 0 if device was identified as supported device, -1 otherwise.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_identify_device(sata_hba_inst_t *sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_drive_info_t *sdinfo)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf uint16_t cfg_word;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int i;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* fetch device identify data */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_fetch_device_identify_data(sata_hba_inst, sdinfo) != 0)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf goto fail_unknown;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cfg_word = sdinfo->satadrv_id.ai_config;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sdinfo->satadrv_type == SATA_DTYPE_ATADISK &&
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (cfg_word & SATA_ATA_TYPE_MASK) != SATA_ATA_TYPE) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Change device type to reflect Identify Device data */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (((cfg_word & SATA_ATAPI_TYPE_MASK) ==
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_ATAPI_TYPE) &&
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ((cfg_word & SATA_ATAPI_ID_DEV_TYPE) ==
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_ATAPI_CDROM_DEV)) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_type = SATA_DTYPE_ATAPICD;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_type = SATA_DTYPE_UNKNOWN;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else if (sdinfo->satadrv_type == SATA_DTYPE_ATAPICD &&
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (((cfg_word & SATA_ATAPI_TYPE_MASK) != SATA_ATAPI_TYPE) ||
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ((cfg_word & SATA_ATAPI_ID_DEV_TYPE) != SATA_ATAPI_CDROM_DEV))) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Change device type to reflect Identify Device data ! */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((sdinfo->satadrv_id.ai_config & SATA_ATA_TYPE_MASK) ==
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_ATA_TYPE) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_type = SATA_DTYPE_ATADISK;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_type = SATA_DTYPE_UNKNOWN;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sdinfo->satadrv_type == SATA_DTYPE_ATADISK) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sdinfo->satadrv_capacity == 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Non-LBA disk. Too bad... */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_log(sata_hba_inst, CE_WARN,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "SATA disk device at port %d does not support LBA",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_addr.cport);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf goto fail_unknown;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Check for Ultra DMA modes 6 through 0 being supported */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf for (i = 6; i >= 0; --i) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sdinfo->satadrv_id.ai_ultradma & (1 << i))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * At least UDMA 4 mode has to be supported. If mode 4 or
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * higher are not supported by the device, fail this
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * device.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (i < 4) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* No required Ultra DMA mode supported */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_log(sata_hba_inst, CE_WARN,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "SATA disk device at port %d does not support UDMA "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "mode 4 or higher", sdinfo->satadrv_addr.cport);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_LOG_D((sata_hba_inst, CE_WARN,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "mode 4 or higher required, %d supported", i));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf goto fail_unknown;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (0);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlffail_unknown:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Invalidate sata_drive_info ? */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_type = SATA_DTYPE_UNKNOWN;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_state = SATA_STATE_UNKNOWN;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (-1);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Log/display device information
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_show_drive_info(sata_hba_inst_t *sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_drive_info_t *sdinfo)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int valid_version;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf char msg_buf[MAXPATHLEN];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Show HBA path */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (void) ddi_pathname(SATA_DIP(sata_hba_inst), msg_buf);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cmn_err(CE_CONT, "?%s :\n", msg_buf);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sdinfo->satadrv_type == SATA_DTYPE_UNKNOWN) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (void) sprintf(msg_buf,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "Unsupported SATA device type (cfg 0x%x) at ",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_id.ai_config);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (void) sprintf(msg_buf, "SATA %s device at",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_type == SATA_DTYPE_ATADISK ?
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "disk":"CD/DVD (ATAPI)");
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sdinfo->satadrv_addr.qual == SATA_ADDR_DCPORT)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cmn_err(CE_CONT, "?\t%s port %d\n",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf msg_buf, sdinfo->satadrv_addr.cport);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf else
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cmn_err(CE_CONT, "?\t%s port %d pmport %d\n",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf msg_buf, sdinfo->satadrv_addr.cport,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_addr.pmport);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf bcopy(&sdinfo->satadrv_id.ai_model, msg_buf,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sizeof (sdinfo->satadrv_id.ai_model));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf swab(msg_buf, msg_buf, sizeof (sdinfo->satadrv_id.ai_model));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf msg_buf[sizeof (sdinfo->satadrv_id.ai_model)] = '\0';
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cmn_err(CE_CONT, "?\tmodel %s\n", msg_buf);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf bcopy(&sdinfo->satadrv_id.ai_fw, msg_buf,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sizeof (sdinfo->satadrv_id.ai_fw));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf swab(msg_buf, msg_buf, sizeof (sdinfo->satadrv_id.ai_fw));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf msg_buf[sizeof (sdinfo->satadrv_id.ai_fw)] = '\0';
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cmn_err(CE_CONT, "?\tfirmware %s\n", msg_buf);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf bcopy(&sdinfo->satadrv_id.ai_drvser, msg_buf,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sizeof (sdinfo->satadrv_id.ai_drvser));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf swab(msg_buf, msg_buf, sizeof (sdinfo->satadrv_id.ai_drvser));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf msg_buf[sizeof (sdinfo->satadrv_id.ai_drvser)] = '\0';
c03acfcad7780db4ddf763511a82026680b3b2c1ls cmn_err(CE_CONT, "?\tserial number %s\n", msg_buf);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#ifdef SATA_DEBUG
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sdinfo->satadrv_id.ai_majorversion != 0 &&
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_id.ai_majorversion != 0xffff) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int i;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf for (i = 14; i >= 2; i--) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sdinfo->satadrv_id.ai_majorversion & (1 << i)) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf valid_version = i;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cmn_err(CE_CONT,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "?\tATA/ATAPI-%d supported, majver 0x%x minver 0x%x\n",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf valid_version,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_id.ai_majorversion,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_id.ai_minorversion);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#endif
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Log some info */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cmn_err(CE_CONT, "?\tsupported features:\n");
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf msg_buf[0] = '\0';
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sdinfo->satadrv_features_support & SATA_DEV_F_LBA48)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (void) strlcat(msg_buf, "48-bit LBA", MAXPATHLEN);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf else if (sdinfo->satadrv_features_support & SATA_DEV_F_LBA28)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (void) strlcat(msg_buf, "28-bit LBA", MAXPATHLEN);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sdinfo->satadrv_features_support & SATA_DEV_F_DMA)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (void) strlcat(msg_buf, ", DMA", MAXPATHLEN);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sdinfo->satadrv_features_support & SATA_DEV_F_NCQ)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (void) strlcat(msg_buf, ", Native Command Queueing",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf MAXPATHLEN);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf else if (sdinfo->satadrv_id.ai_cmdset83 & SATA_RW_DMA_QUEUED_CMD)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (void) strlcat(msg_buf, ", Queuing", MAXPATHLEN);
c03acfcad7780db4ddf763511a82026680b3b2c1ls if ((sdinfo->satadrv_id.ai_cmdset82 & SATA_SMART_SUPPORTED) &&
c03acfcad7780db4ddf763511a82026680b3b2c1ls (sdinfo->satadrv_id.ai_features85 & SATA_SMART_ENABLED))
c03acfcad7780db4ddf763511a82026680b3b2c1ls (void) strlcat(msg_buf, ", SMART", MAXPATHLEN);
c03acfcad7780db4ddf763511a82026680b3b2c1ls if ((sdinfo->satadrv_id.ai_cmdset84 & SATA_SMART_SELF_TEST_SUPPORTED) &&
c03acfcad7780db4ddf763511a82026680b3b2c1ls (sdinfo->satadrv_id.ai_features87 & SATA_SMART_SELF_TEST_SUPPORTED))
c03acfcad7780db4ddf763511a82026680b3b2c1ls (void) strlcat(msg_buf, ", SMART self-test", MAXPATHLEN);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cmn_err(CE_CONT, "?\t %s\n", msg_buf);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sdinfo->satadrv_features_support & SATA_DEV_F_SATA2)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cmn_err(CE_CONT, "?\tSATA1 & SATA2 compatible\n");
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf else if (sdinfo->satadrv_features_support & SATA_DEV_F_SATA1)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cmn_err(CE_CONT, "?\tSATA1 compatible\n");
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#ifdef __i386
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (void) sprintf(msg_buf, "\tcapacity = %llu sectors\n",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_capacity);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#else
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (void) sprintf(msg_buf, "\tcapacity = %lu sectors\n",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_capacity);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#endif
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cmn_err(CE_CONT, "?%s", msg_buf);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * sata_save_drive_settings extracts current setting of the device and stores
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * it for future reference, in case the device setup would need to be restored
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * after the device reset.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * At the moment only read ahead and write cache settings are saved, if the
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * device supports these features at all.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_save_drive_settings(sata_drive_info_t *sdinfo)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (!(sdinfo->satadrv_id.ai_cmdset82 & SATA_LOOK_AHEAD) &&
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf !(sdinfo->satadrv_id.ai_cmdset82 & SATA_WRITE_CACHE)) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* None of the features is supported - do nothing */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Current setting of Read Ahead (and Read Cache) */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sdinfo->satadrv_id.ai_features85 & SATA_LOOK_AHEAD)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_settings |= SATA_DEV_READ_AHEAD;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf else
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_settings &= ~SATA_DEV_READ_AHEAD;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Current setting of Write Cache */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sdinfo->satadrv_id.ai_features85 & SATA_WRITE_CACHE)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_settings |= SATA_DEV_WRITE_CACHE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf else
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_settings &= ~SATA_DEV_WRITE_CACHE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * sata_check_capacity function determines a disk capacity
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * and addressing mode (LBA28/LBA48) by examining a disk identify device data.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * NOTE: CHS mode is not supported! If a device does not support LBA,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * this function is not called.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Returns device capacity in number of blocks, i.e. largest addressable LBA+1
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic uint64_t
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_check_capacity(sata_drive_info_t *sdinfo)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf uint64_t capacity = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int i;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sdinfo->satadrv_type != SATA_DTYPE_ATADISK ||
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf !sdinfo->satadrv_id.ai_cap & SATA_LBA_SUPPORT)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Capacity valid only for LBA-addressable disk devices */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (0);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((sdinfo->satadrv_id.ai_validinfo & SATA_VALIDINFO_88) &&
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (sdinfo->satadrv_id.ai_cmdset83 & SATA_EXT48) &&
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (sdinfo->satadrv_id.ai_features86 & SATA_EXT48)) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* LBA48 mode supported and enabled */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_features_support |= SATA_DEV_F_LBA48 |
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_DEV_F_LBA28;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf for (i = 3; i >= 0; --i) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf capacity <<= 16;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf capacity += sdinfo->satadrv_id.ai_addrsecxt[i];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf capacity = sdinfo->satadrv_id.ai_addrsec[1];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf capacity <<= 16;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf capacity += sdinfo->satadrv_id.ai_addrsec[0];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (capacity >= 0x1000000)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* LBA28 mode */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_features_support |= SATA_DEV_F_LBA28;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (capacity);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Allocate consistent buffer for DMA transfer
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Cannot be called from interrupt level or with mutex held - it may sleep.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Returns pointer to allocated buffer structure, or NULL if allocation failed.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic struct buf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_alloc_local_buffer(sata_pkt_txlate_t *spx, int len)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf struct scsi_address ap;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf struct buf *bp;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ddi_dma_attr_t cur_dma_attr;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ASSERT(spx->txlt_sata_pkt != NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ap.a_hba_tran = spx->txlt_sata_hba_inst->satahba_scsi_tran;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ap.a_target = SATA_TO_SCSI_TARGET(
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_sata_pkt->satapkt_device.satadev_addr.cport,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_sata_pkt->satapkt_device.satadev_addr.pmport,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_sata_pkt->satapkt_device.satadev_addr.qual);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ap.a_lun = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf bp = scsi_alloc_consistent_buf(&ap, NULL, len,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf B_READ, SLEEP_FUNC, NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (bp != NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Allocate DMA resources for this buffer */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_sata_pkt->satapkt_cmd.satacmd_bp = bp;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * We use a local version of the dma_attr, to account
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * for a device addressing limitations.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * sata_adjust_dma_attr() will handle sdinfo == NULL which
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * will cause dma attributes to be adjusted to a lowest
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * acceptable level.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_adjust_dma_attr(NULL,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_DMA_ATTR(spx->txlt_sata_hba_inst), &cur_dma_attr);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_dma_buf_setup(spx, PKT_CONSISTENT,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SLEEP_FUNC, NULL, &cur_dma_attr) != DDI_SUCCESS) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsi_free_consistent_buf(bp);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_sata_pkt->satapkt_cmd.satacmd_bp = NULL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf bp = NULL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (bp);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Release local buffer (consistent buffer for DMA transfer) allocated
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * via sata_alloc_local_buffer().
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_free_local_buffer(sata_pkt_txlate_t *spx)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ASSERT(spx->txlt_sata_pkt != NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ASSERT(spx->txlt_dma_cookie_list != NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ASSERT(spx->txlt_dma_cookie_list_len != 0);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ASSERT(spx->txlt_buf_dma_handle != NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ASSERT(spx->txlt_sata_pkt->satapkt_cmd.satacmd_bp != NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_sata_pkt->satapkt_cmd.satacmd_num_dma_cookies = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_sata_pkt->satapkt_cmd.satacmd_dma_cookie_list = NULL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Free DMA resources */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (void) ddi_dma_unbind_handle(spx->txlt_buf_dma_handle);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ddi_dma_free_handle(&spx->txlt_buf_dma_handle);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_buf_dma_handle = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf kmem_free(spx->txlt_dma_cookie_list,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_dma_cookie_list_len * sizeof (ddi_dma_cookie_t));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_dma_cookie_list = NULL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_dma_cookie_list_len = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Free buffer */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scsi_free_consistent_buf(spx->txlt_sata_pkt->satapkt_cmd.satacmd_bp);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Allocate sata_pkt
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Pkt structure version and embedded strcutures version are initialized.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * sata_pkt and sata_pkt_txlate structures are cross-linked.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Since this may be called in interrupt context by sata_scsi_init_pkt,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * callback argument determines if it can sleep or not.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Hence, it should not be called from interrupt context.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * If successful, non-NULL pointer to a sata pkt is returned.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Upon failure, NULL pointer is returned.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic sata_pkt_t *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_pkt_alloc(sata_pkt_txlate_t *spx, int (*callback)(caddr_t))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_pkt_t *spkt;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int kmsflag;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf kmsflag = (callback == SLEEP_FUNC) ? KM_SLEEP : KM_NOSLEEP;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spkt = kmem_zalloc(sizeof (sata_pkt_t), kmsflag);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (spkt == NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_LOG_D((spx->txlt_sata_hba_inst, CE_WARN,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_pkt_alloc: failed"));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spkt->satapkt_rev = SATA_PKT_REV;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spkt->satapkt_cmd.satacmd_rev = SATA_CMD_REV;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spkt->satapkt_device.satadev_rev = SATA_DEVICE_REV;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spkt->satapkt_framework_private = spx;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_sata_pkt = spkt;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (spkt);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Free sata pkt allocated via sata_pkt_alloc()
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_pkt_free(sata_pkt_txlate_t *spx)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ASSERT(spx->txlt_sata_pkt != NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ASSERT(spx->txlt_sata_pkt->satapkt_cmd.satacmd_bp == NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf kmem_free(spx->txlt_sata_pkt, sizeof (sata_pkt_t));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_sata_pkt = NULL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Adjust DMA attributes.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * SCSI cmds block count is up to 24 bits, SATA cmd block count vary
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * from 8 bits to 16 bits, depending on a command being used.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Limiting max block count arbitrarily to 256 for all read/write
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * commands may affects performance, so check both the device and
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * controller capability before adjusting dma attributes.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * For ATAPI CD/DVD dma granularity has to be adjusted as well,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * because these devices support block size of 2k rather
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * then 512 bytes.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfvoid
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_adjust_dma_attr(sata_drive_info_t *sdinfo, ddi_dma_attr_t *dma_attr,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ddi_dma_attr_t *adj_dma_attr)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf uint32_t count_max;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Copy original attributes */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *adj_dma_attr = *dma_attr;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Things to consider: device addressing capability,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * "excessive" controller DMA capabilities.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * If a device is being probed/initialized, there are
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * no device info - use default limits then.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sdinfo == NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf count_max = dma_attr->dma_attr_granular * 0x100;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (dma_attr->dma_attr_count_max > count_max)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf adj_dma_attr->dma_attr_count_max = count_max;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (dma_attr->dma_attr_maxxfer > count_max)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf adj_dma_attr->dma_attr_maxxfer = count_max;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sdinfo->satadrv_type == SATA_DTYPE_ATAPICD) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* arbitrarily modify controller dma granularity */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf adj_dma_attr->dma_attr_granular = SATA_ATAPI_SECTOR_SIZE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sdinfo->satadrv_features_support & (SATA_DEV_F_LBA48)) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * 16-bit sector count may be used - we rely on
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * the assumption that only read and write cmds
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * will request more than 256 sectors worth of data
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf count_max = adj_dma_attr->dma_attr_granular * 0x10000;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * 8-bit sector count will be used - default limits
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * for dma attributes
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf count_max = adj_dma_attr->dma_attr_granular * 0x100;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Adjust controler dma attributes, if necessary
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (dma_attr->dma_attr_count_max > count_max)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf adj_dma_attr->dma_attr_count_max = count_max;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (dma_attr->dma_attr_maxxfer > count_max)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf adj_dma_attr->dma_attr_maxxfer = count_max;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Allocate DMA resources for the buffer
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * This function handles initial DMA resource allocation as well as
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * DMA window shift and may be called repeatedly for the same DMA window
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * until all DMA cookies in the DMA window are processed.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Returns DDI_SUCCESS upon successful operation,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * returns failure code returned by failing commands or DDI_FAILURE when
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * internal cleanup failed.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_dma_buf_setup(sata_pkt_txlate_t *spx, int flags,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int (*callback)(caddr_t), caddr_t arg,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ddi_dma_attr_t *cur_dma_attr)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int rval;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ddi_dma_cookie_t cookie;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf off_t offset;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf size_t size;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int max_sg_len, req_sg_len, i;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf uint_t dma_flags;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf struct buf *bp;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf uint64_t max_txfer_len;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf uint64_t cur_txfer_len;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ASSERT(spx->txlt_sata_pkt != NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf bp = spx->txlt_sata_pkt->satapkt_cmd.satacmd_bp;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ASSERT(bp != NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (spx->txlt_buf_dma_handle == NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * No DMA resources allocated so far - this is a first call
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * for this sata pkt.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rval = ddi_dma_alloc_handle(SATA_DIP(spx->txlt_sata_hba_inst),
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cur_dma_attr, callback, arg, &spx->txlt_buf_dma_handle);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (rval != DDI_SUCCESS) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_LOG_D((spx->txlt_sata_hba_inst, CE_WARN,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_dma_buf_setup: no buf DMA resources %x",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rval));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (rval);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (bp->b_flags & B_READ)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf dma_flags = DDI_DMA_READ;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf else
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf dma_flags = DDI_DMA_WRITE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (flags & PKT_CONSISTENT)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf dma_flags |= DDI_DMA_CONSISTENT;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (flags & PKT_DMA_PARTIAL)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf dma_flags |= DDI_DMA_PARTIAL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rval = ddi_dma_buf_bind_handle(spx->txlt_buf_dma_handle,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf bp, dma_flags, callback, arg,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf &cookie, &spx->txlt_curwin_num_dma_cookies);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf switch (rval) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case DDI_DMA_PARTIAL_MAP:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG1(SATA_DBG_DMA_SETUP, spx->txlt_sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_dma_buf_setup: DMA Partial Map\n", NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Partial DMA mapping.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Retrieve number of DMA windows for this request.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (ddi_dma_numwin(spx->txlt_buf_dma_handle,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf &spx->txlt_num_dma_win) != DDI_SUCCESS) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (void) ddi_dma_unbind_handle(
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_buf_dma_handle);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (void) ddi_dma_free_handle(
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf &spx->txlt_buf_dma_handle);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_buf_dma_handle = NULL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_LOG_D((spx->txlt_sata_hba_inst, CE_WARN,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_dma_buf_setup: numwin failed\n"));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (DDI_FAILURE);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_cur_dma_win = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case DDI_DMA_MAPPED:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* DMA fully mapped */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_num_dma_win = 1;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_cur_dma_win = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf default:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* DMA mapping failed */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (void) ddi_dma_free_handle(&spx->txlt_buf_dma_handle);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_buf_dma_handle = NULL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_LOG_D((spx->txlt_sata_hba_inst, CE_WARN,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_dma_buf_setup: buf dma handle binding "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "failed %x\n", rval));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (rval);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_curwin_processed_dma_cookies = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_dma_cookie_list = NULL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * DMA setup is reused. Check if we need to process more
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * cookies in current window, or to get next window, if any.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ASSERT(spx->txlt_curwin_processed_dma_cookies <=
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_curwin_num_dma_cookies);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (spx->txlt_curwin_processed_dma_cookies ==
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_curwin_num_dma_cookies) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * All cookies from current DMA window were processed.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Get next DMA window.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_cur_dma_win++;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (spx->txlt_cur_dma_win < spx->txlt_num_dma_win) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (void) ddi_dma_getwin(spx->txlt_buf_dma_handle,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_cur_dma_win, &offset, &size,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf &cookie,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf &spx->txlt_curwin_num_dma_cookies);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_curwin_processed_dma_cookies = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* No more windows! End of request! */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* What to do? - panic for now */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ASSERT(spx->txlt_cur_dma_win >=
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_num_dma_win);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_curwin_num_dma_cookies = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_curwin_processed_dma_cookies = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_sata_pkt->
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf satapkt_cmd.satacmd_num_dma_cookies = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (DDI_SUCCESS);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* There better be at least one DMA cookie */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ASSERT((spx->txlt_curwin_num_dma_cookies -
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_curwin_processed_dma_cookies) > 0);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (spx->txlt_curwin_processed_dma_cookies == 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Processing a new DMA window - set-up dma cookies list.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * We may reuse previously allocated cookie array if it is
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * possible.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (spx->txlt_dma_cookie_list != NULL &&
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_dma_cookie_list_len <
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_curwin_num_dma_cookies) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * New DMA window contains more cookies than
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * the previous one. We need larger cookie list - free
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * the old one.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (void) kmem_free(spx->txlt_dma_cookie_list,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_dma_cookie_list_len *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sizeof (ddi_dma_cookie_t));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_dma_cookie_list = NULL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_dma_cookie_list_len = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (spx->txlt_dma_cookie_list == NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Allocate new dma cookie array */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_dma_cookie_list = kmem_zalloc(
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sizeof (ddi_dma_cookie_t) *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_curwin_num_dma_cookies, KM_SLEEP);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_dma_cookie_list_len =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_curwin_num_dma_cookies;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Copy all DMA cookies into local list, so we will know their
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * dma_size in advance of setting the sata_pkt.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * One cookie was already fetched, so copy it.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *(&spx->txlt_dma_cookie_list[0]) = cookie;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf for (i = 1; i < spx->txlt_curwin_num_dma_cookies; i++) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ddi_dma_nextcookie(spx->txlt_buf_dma_handle, &cookie);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *(&spx->txlt_dma_cookie_list[i]) = cookie;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG2(SATA_DBG_DMA_SETUP, spx->txlt_sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_dma_buf_setup: sliding within DMA window, "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "cur cookie %d, total cookies %d\n",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_curwin_processed_dma_cookies,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_curwin_num_dma_cookies);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Set-up sata_pkt cookie list.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * No single cookie transfer size would exceed max transfer size of
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * an ATA command used for addressed device (tha adjustment of the dma
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * attributes took care of this). But there may be more
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * then one cookie, so the cmd cookie list has to be
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * constrained by both a maximum scatter gather list length and
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * a maximum transfer size restriction of an ATA command.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf max_sg_len = cur_dma_attr->dma_attr_sgllen;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf req_sg_len = MIN(max_sg_len,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (spx->txlt_curwin_num_dma_cookies -
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_curwin_processed_dma_cookies));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ASSERT(req_sg_len > 0);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf max_txfer_len = MAX((cur_dma_attr->dma_attr_granular * 0x100),
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cur_dma_attr->dma_attr_maxxfer);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* One cookie should be always available */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_sata_pkt->satapkt_cmd.satacmd_dma_cookie_list =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf &spx->txlt_dma_cookie_list[spx->txlt_curwin_processed_dma_cookies];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_sata_pkt->satapkt_cmd.satacmd_num_dma_cookies = 1;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cur_txfer_len =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (uint64_t)spx->txlt_dma_cookie_list[
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_curwin_processed_dma_cookies].dmac_size;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_curwin_processed_dma_cookies++;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ASSERT(cur_txfer_len <= max_txfer_len);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Add more cookies to the scatter-gather list */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf for (i = 1; i < req_sg_len; i++) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (cur_txfer_len < max_txfer_len) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Check if the next cookie could be used by
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * this sata_pkt.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((cur_txfer_len +
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_dma_cookie_list[
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_curwin_processed_dma_cookies].
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf dmac_size) <= max_txfer_len) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Yes, transfer lenght is within bounds */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_sata_pkt->
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf satapkt_cmd.satacmd_num_dma_cookies++;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cur_txfer_len +=
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_dma_cookie_list[
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_curwin_processed_dma_cookies].
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf dmac_size;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_curwin_processed_dma_cookies++;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* No, transfer would exceed max lenght. */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG3(SATA_DBG_DMA_SETUP,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "ncookies %d, size 0x%lx, "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "max_size 0x%lx\n",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_sata_pkt->
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf satapkt_cmd.satacmd_num_dma_cookies,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cur_txfer_len, max_txfer_len);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Cmd max transfer length reached */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG3(SATA_DBG_DMA_SETUP, spx->txlt_sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "Max transfer length? "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "ncookies %d, size 0x%lx, max_size 0x%lx\n",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_sata_pkt->
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf satapkt_cmd.satacmd_num_dma_cookies,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cur_txfer_len, max_txfer_len);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ASSERT(cur_txfer_len != 0);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_total_residue -= cur_txfer_len;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (DDI_SUCCESS);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Fetch Device Identify data.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Send DEVICE IDENTIFY command to a device and get the device identify data.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * The device_info structure has to be set to device type (for selecting proper
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * device identify command).
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Returns 0 if success, -1 otherwise.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Cannot be called in an interrupt context.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_fetch_device_identify_data(sata_hba_inst_t *sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_drive_info_t *sdinfo)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf struct buf *bp;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_pkt_t *spkt;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_cmd_t *scmd;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_pkt_txlate_t *spx;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int rval;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx = kmem_zalloc(sizeof (sata_pkt_txlate_t), KM_SLEEP);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_sata_hba_inst = sata_hba_inst;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_scsi_pkt = NULL; /* No scsi pkt involved */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spkt = sata_pkt_alloc(spx, SLEEP_FUNC);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (spkt == NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf kmem_free(spx, sizeof (sata_pkt_txlate_t));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (-1);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* address is needed now */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spkt->satapkt_device.satadev_addr = sdinfo->satadrv_addr;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Allocate buffer for Identify Data return data
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf bp = sata_alloc_local_buffer(spx, sizeof (sata_id_t));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (bp == NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_pkt_free(spx);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf kmem_free(spx, sizeof (sata_pkt_txlate_t));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_LOG_D((sata_hba_inst, CE_WARN,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_fetch_device_identify_data: "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "cannot allocate buffer for ID"));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (-1);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Fill sata_pkt */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_state = SATA_STATE_PROBING;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spkt->satapkt_device.satadev_addr = sdinfo->satadrv_addr;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spkt->satapkt_op_mode = SATA_OPMODE_SYNCH | SATA_OPMODE_INTERRUPTS;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Synchronous mode, no callback */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spkt->satapkt_comp = NULL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Timeout 30s */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spkt->satapkt_time = sata_default_pkt_time;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd = &spkt->satapkt_cmd;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_bp = bp;
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_flags.sata_data_direction = SATA_DIR_READ;
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_flags.sata_ignore_dev_reset = B_TRUE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Build Identify Device cmd in the sata_pkt */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_addr_type = 0; /* N/A */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_sec_count_lsb = 0; /* N/A */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_lba_low_lsb = 0; /* N/A */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_lba_mid_lsb = 0; /* N/A */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_lba_high_lsb = 0; /* N/A */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_features_reg = 0; /* N/A */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_device_reg = 0; /* Always device 0 */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sdinfo->satadrv_type == SATA_DTYPE_ATAPICD) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Identify Packet Device cmd */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_cmd_reg = SATAC_ID_PACKET_DEVICE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Identify Device cmd - mandatory for all other devices */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_cmd_reg = SATAC_ID_DEVICE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Send pkt to SATA HBA driver */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((*SATA_START_FUNC(sata_hba_inst))(SATA_DIP(sata_hba_inst), spkt) !=
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_TRAN_ACCEPTED ||
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spkt->satapkt_reason != SATA_PKT_COMPLETED) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Woops, no Identify Data.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Invalidate sata_drive_info ?
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rval = -1;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Update sata_drive_info */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rval = ddi_dma_sync(spx->txlt_buf_dma_handle, 0, 0,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf DDI_DMA_SYNC_FORKERNEL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (rval != DDI_SUCCESS) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_LOG_D((spx->txlt_sata_hba_inst, CE_WARN,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_fetch_device_identify_data: "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sync pkt failed"));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rval = -1;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf goto fail;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf bcopy(bp->b_un.b_addr, &sdinfo->satadrv_id,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sizeof (sata_id_t));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_features_support = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sdinfo->satadrv_type == SATA_DTYPE_ATADISK) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Retrieve capacity (disks only) and addressing mode
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_capacity = sata_check_capacity(sdinfo);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * For ATAPI devices one has to issue Get Capacity cmd
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * (not needed at the moment)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_capacity = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Setup supported features flags */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sdinfo->satadrv_id.ai_cap & SATA_DMA_SUPPORT)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_features_support |= SATA_DEV_F_DMA;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Check for NCQ support */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sdinfo->satadrv_id.ai_satacap != 0 &&
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_id.ai_satacap != 0xffff) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* SATA compliance */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sdinfo->satadrv_id.ai_satacap & SATA_NCQ)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_features_support |=
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_DEV_F_NCQ;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sdinfo->satadrv_id.ai_satacap &
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (SATA_1_SPEED | SATA_2_SPEED)) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sdinfo->satadrv_id.ai_satacap &
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_2_SPEED)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_features_support |=
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_DEV_F_SATA2;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sdinfo->satadrv_id.ai_satacap &
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_1_SPEED)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_features_support |=
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_DEV_F_SATA1;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_features_support |=
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_DEV_F_SATA1;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_queue_depth = sdinfo->satadrv_id.ai_qdepth;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sdinfo->satadrv_id.ai_cmdset83 & SATA_RW_DMA_QUEUED_CMD)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sdinfo->satadrv_queue_depth == 0)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_queue_depth = 1;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rval = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlffail:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Free allocated resources */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_free_local_buffer(spx);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_sata_pkt->satapkt_cmd.satacmd_bp = NULL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_pkt_free(spx);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf kmem_free(spx, sizeof (sata_pkt_txlate_t));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (rval);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * SATA spec requires that the device supports at least UDMA 4 mode and
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * UDMA mode is selected.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Some devices (bridged devices) may not come-up with default UDMA mode
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * set correctly, so this function is setting it.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Returns SATA_SUCCESS if proper UDMA mode is selected.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Returns SATA_FAILURE if proper UDMA mode could not be selected.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_set_udma_mode(sata_hba_inst_t *sata_hba_inst, sata_drive_info_t *sdinfo)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_pkt_t *spkt;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_cmd_t *scmd;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_pkt_txlate_t *spx;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int result = SATA_SUCCESS;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int i, mode;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ASSERT(sdinfo != NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ASSERT(sata_hba_inst != NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Find highest Ultra DMA mode supported */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf for (mode = 6; mode >= 0; --mode) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sdinfo->satadrv_id.ai_ultradma & (1 << mode))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (mode < 4)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (SATA_FAILURE);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Find UDMA mode currently selected */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf for (i = 6; i >= 0; --i) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sdinfo->satadrv_id.ai_ultradma & (1 << (i + 8)))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (i < mode) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Set UDMA mode via SET FEATURES COMMAND */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Prepare packet for SET FEATURES COMMAND */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx = kmem_zalloc(sizeof (sata_pkt_txlate_t), KM_SLEEP);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_sata_hba_inst = sata_hba_inst;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spx->txlt_scsi_pkt = NULL; /* No scsi pkt involved */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spkt = sata_pkt_alloc(spx, SLEEP_FUNC);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (spkt == NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf result = SATA_FAILURE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf goto failure;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Fill sata_pkt */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spkt->satapkt_device.satadev_addr = sdinfo->satadrv_addr;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Timeout 30s */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spkt->satapkt_time = sata_default_pkt_time;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Synchronous mode, no callback, interrupts */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spkt->satapkt_op_mode =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_OPMODE_SYNCH | SATA_OPMODE_INTERRUPTS;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spkt->satapkt_comp = NULL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd = &spkt->satapkt_cmd;
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_flags.sata_data_direction = SATA_DIR_NODATA_XFER;
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_flags.sata_ignore_dev_reset = B_TRUE;
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 scmd->satacmd_features_reg = SATAC_SF_TRANSFER_MODE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf scmd->satacmd_sec_count_lsb =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATAC_TRANSFER_MODE_ULTRA_DMA | mode;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Transfer command to HBA */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((*SATA_START_FUNC(sata_hba_inst))(SATA_DIP(sata_hba_inst),
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spkt) != SATA_TRAN_ACCEPTED ||
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf spkt->satapkt_reason != SATA_PKT_COMPLETED) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Pkt execution failed */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf result = SATA_FAILURE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlffailure:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (result == SATA_FAILURE)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_LOG_D((sata_hba_inst, CE_WARN,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_set_udma_mode: could not set UDMA "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "mode %", mode));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Free allocated resources */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (spkt != NULL)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_pkt_free(spx);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (void) kmem_free(spx, sizeof (sata_pkt_txlate_t));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (result);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw/*
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw * Set device caching mode.
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw * One of the following operations should be specified:
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw * SATAC_SF_ENABLE_READ_AHEAD
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw * SATAC_SF_DISABLE_READ_AHEAD
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw * SATAC_SF_ENABLE_WRITE_CACHE
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw * SATAC_SF_DISABLE_WRITE_CACHE
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw *
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw * If operation fails, system log messgage is emitted.
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw * Returns SATA_SUCCESS when the operation succeeds, SATA_FAILURE otherwise.
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw */
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelwstatic int
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelwsata_set_cache_mode(sata_hba_inst_t *sata_hba_inst, sata_drive_info_t *sdinfo,
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw int cache_op)
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw{
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw sata_pkt_t *spkt;
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw sata_cmd_t *scmd;
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw sata_pkt_txlate_t *spx;
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw int rval = SATA_SUCCESS;
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw char *infop;
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw ASSERT(sdinfo != NULL);
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw ASSERT(sata_hba_inst != NULL);
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw ASSERT(cache_op == SATAC_SF_ENABLE_READ_AHEAD ||
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw cache_op == SATAC_SF_DISABLE_READ_AHEAD ||
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw cache_op == SATAC_SF_ENABLE_WRITE_CACHE ||
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw cache_op == SATAC_SF_DISABLE_WRITE_CACHE);
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw /* Prepare packet for SET FEATURES COMMAND */
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw spx = kmem_zalloc(sizeof (sata_pkt_txlate_t), KM_SLEEP);
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw spx->txlt_sata_hba_inst = sata_hba_inst;
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw spx->txlt_scsi_pkt = NULL; /* No scsi pkt involved */
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw spkt = sata_pkt_alloc(spx, SLEEP_FUNC);
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw if (spkt == NULL) {
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw rval = SATA_FAILURE;
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw goto failure;
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw }
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw /* Fill sata_pkt */
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw spkt->satapkt_device.satadev_addr = sdinfo->satadrv_addr;
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw /* Timeout 30s */
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw spkt->satapkt_time = sata_default_pkt_time;
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw /* Synchronous mode, no callback, interrupts */
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw spkt->satapkt_op_mode =
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw SATA_OPMODE_SYNCH | SATA_OPMODE_INTERRUPTS;
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw spkt->satapkt_comp = NULL;
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw scmd = &spkt->satapkt_cmd;
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw scmd->satacmd_flags.sata_data_direction = SATA_DIR_NODATA_XFER;
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw scmd->satacmd_flags.sata_ignore_dev_reset = B_TRUE;
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw scmd->satacmd_addr_type = 0;
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw scmd->satacmd_device_reg = 0;
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw scmd->satacmd_status_reg = 0;
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw scmd->satacmd_error_reg = 0;
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw scmd->satacmd_cmd_reg = SATAC_SET_FEATURES;
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw scmd->satacmd_features_reg = cache_op;
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw /* Transfer command to HBA */
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw if (((*SATA_START_FUNC(sata_hba_inst))(
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw SATA_DIP(sata_hba_inst), spkt) != 0) ||
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw (spkt->satapkt_reason != SATA_PKT_COMPLETED)) {
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw /* Pkt execution failed */
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw switch (cache_op) {
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw case SATAC_SF_ENABLE_READ_AHEAD:
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw infop = "enabling read ahead failed";
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw break;
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw case SATAC_SF_DISABLE_READ_AHEAD:
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw infop = "disabling read ahead failed";
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw break;
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw case SATAC_SF_ENABLE_WRITE_CACHE:
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw infop = "enabling write cache failed";
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw break;
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw case SATAC_SF_DISABLE_WRITE_CACHE:
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw infop = "disabling write cache failed";
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw break;
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw }
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw SATA_LOG_D((sata_hba_inst, CE_WARN, "%s", infop));
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw rval = SATA_FAILURE;
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw }
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelwfailure:
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw /* Free allocated resources */
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw if (spkt != NULL)
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw sata_pkt_free(spx);
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw (void) kmem_free(spx, sizeof (sata_pkt_txlate_t));
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw return (rval);
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw}
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Update port SCR block
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_update_port_scr(sata_port_scr_t *port_scr, sata_device_t *device)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf port_scr->sstatus = device->satadev_scr.sstatus;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf port_scr->serror = device->satadev_scr.serror;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf port_scr->scontrol = device->satadev_scr.scontrol;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf port_scr->sactive = device->satadev_scr.sactive;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf port_scr->snotific = device->satadev_scr.snotific;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Update state and copy port ss* values from passed sata_device structure.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * sata_address is validated - if not valid, nothing is changed in sata_scsi
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * configuration struct.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * SATA_PSTATE_SHUTDOWN in port state is not reset to 0 by this function
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * regardless of the state in device argument.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Port mutex should be held while calling this function.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_update_port_info(sata_hba_inst_t *sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device_t *sata_device)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ASSERT(mutex_owned(&SATA_CPORT_MUTEX(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device->satadev_addr.cport)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_device->satadev_addr.qual == SATA_ADDR_CPORT ||
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device->satadev_addr.qual == SATA_ADDR_DCPORT) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_cport_info_t *cportinfo;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (SATA_NUM_CPORTS(sata_hba_inst) <=
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device->satadev_addr.cport)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo = SATA_CPORT_INFO(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device->satadev_addr.cport);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_update_port_scr(&cportinfo->cport_scr, sata_device);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Preserve SATA_PSTATE_SHUTDOWN flag */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo->cport_state &= ~(SATA_PSTATE_PWRON |
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_PSTATE_PWROFF | SATA_PSTATE_FAILED);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo->cport_state |=
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device->satadev_state & SATA_PSTATE_VALID;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_pmport_info_t *pmportinfo;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((sata_device->satadev_addr.qual != SATA_ADDR_PMPORT) ||
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (sata_device->satadev_addr.qual != SATA_ADDR_DPMPORT) ||
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_NUM_PMPORTS(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device->satadev_addr.cport) <
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device->satadev_addr.pmport)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf pmportinfo = SATA_PMPORT_INFO(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device->satadev_addr.cport,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device->satadev_addr.pmport);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_update_port_scr(&pmportinfo->pmport_scr, sata_device);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Preserve SATA_PSTATE_SHUTDOWN flag */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf pmportinfo->pmport_state &=
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ~(SATA_PSTATE_PWRON | SATA_PSTATE_PWROFF |
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_PSTATE_FAILED);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf pmportinfo->pmport_state |=
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device->satadev_state & SATA_PSTATE_VALID;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Extract SATA port specification from an IOCTL argument.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * This function return the port the user land send us as is, unless it
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * cannot retrieve port spec, then -1 is returned.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Note: Only cport - no port multiplier port.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int32_t
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_get_port_num(sata_hba_inst_t *sata_hba_inst, struct devctl_iocdata *dcp)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int32_t port;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Extract port number from nvpair in dca structure */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (nvlist_lookup_int32(ndi_dc_get_ap_data(dcp), "port", &port) != 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_LOG_D((sata_hba_inst, CE_NOTE,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_get_port_num: invalid port spec 0x%x in ioctl",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf port));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf port = -1;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (port);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Get dev_info_t pointer to the device node pointed to by port argument.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * NOTE: target argument is a value used in ioctls to identify
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * the AP - it is not a sata_address.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * It is a combination of cport, pmport and address qualifier, encodded same
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * way as a scsi target number.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * At this moment it carries only cport number.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * No PMult hotplug support.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Returns dev_info_t pointer if target device was found, NULL otherwise.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic dev_info_t *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_get_target_dip(dev_info_t *dip, int32_t port)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf dev_info_t *cdip = NULL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int target, tgt;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int ncport;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int circ;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ncport = port & SATA_CFGA_CPORT_MASK;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf target = SATA_TO_SCSI_TARGET(ncport, 0, SATA_ADDR_DCPORT);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ndi_devi_enter(dip, &circ);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf for (cdip = ddi_get_child(dip); cdip != NULL; ) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf dev_info_t *next = ddi_get_next_sibling(cdip);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf tgt = ddi_prop_get_int(DDI_DEV_T_ANY, cdip,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf DDI_PROP_DONTPASS, "target", -1);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (tgt == -1) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * This is actually an error condition, but not
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * a fatal one. Just continue the search.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cdip = next;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf continue;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (tgt == target)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cdip = next;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ndi_devi_exit(dip, circ);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (cdip);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * sata_cfgadm_state:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Use the sata port state and state of the target node to figure out
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * the cfgadm_state.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * The port argument is a value with encoded cport,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * pmport and address qualifier, in the same manner as a scsi target number.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * SCSI_TO_SATA_CPORT macro extracts cport number,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * SCSI_TO_SATA_PMPORT extracts pmport number and
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * SCSI_TO_SATA_ADDR_QUAL extracts port mulitplier qualifier flag.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * For now, support is for cports only - no pmultiplier ports.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_cfgadm_state(sata_hba_inst_t *sata_hba_inst, int32_t port,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf devctl_ap_state_t *ap_state)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf uint16_t cport;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int port_state;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Cport only */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport = SCSI_TO_SATA_CPORT(port);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf port_state = SATA_CPORT_STATE(sata_hba_inst, cport);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (port_state & SATA_PSTATE_SHUTDOWN ||
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf port_state & SATA_PSTATE_FAILED) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ap_state->ap_rstate = AP_RSTATE_DISCONNECTED;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ap_state->ap_ostate = AP_OSTATE_UNCONFIGURED;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (port_state & SATA_PSTATE_FAILED)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ap_state->ap_condition = AP_COND_FAILED;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf else
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ap_state->ap_condition = AP_COND_UNKNOWN;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Need to check pmult device port here as well, when supported */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Port is enabled and ready */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf switch (SATA_CPORT_DEV_TYPE(sata_hba_inst, cport)) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SATA_DTYPE_NONE:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* No device attached */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ap_state->ap_rstate = AP_RSTATE_EMPTY;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ap_state->ap_ostate = AP_OSTATE_UNCONFIGURED;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ap_state->ap_condition = AP_COND_OK;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SATA_DTYPE_UNKNOWN:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SATA_DTYPE_ATAPINONCD:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SATA_DTYPE_PMULT: /* Until PMult is supported */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Unknown device attached */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ap_state->ap_rstate = AP_RSTATE_CONNECTED;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ap_state->ap_ostate = AP_OSTATE_UNCONFIGURED;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ap_state->ap_condition = AP_COND_UNKNOWN;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SATA_DTYPE_ATADISK:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf case SATA_DTYPE_ATAPICD:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf dev_info_t *tdip = NULL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf dev_info_t *dip = NULL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int circ;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf dip = SATA_DIP(sata_hba_inst);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf tdip = sata_get_target_dip(dip, port);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ap_state->ap_rstate = AP_RSTATE_CONNECTED;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (tdip != NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ndi_devi_enter(dip, &circ);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&(DEVI(tdip)->devi_lock));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((DEVI_IS_DEVICE_OFFLINE(tdip)) ||
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (DEVI_IS_DEVICE_DOWN(tdip))) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ap_state->ap_ostate = AP_OSTATE_UNCONFIGURED;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ap_state->ap_ostate = AP_OSTATE_CONFIGURED;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ap_state->ap_condition = AP_COND_OK;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&(DEVI(tdip)->devi_lock));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ndi_devi_exit(dip, circ);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ap_state->ap_ostate = AP_OSTATE_UNCONFIGURED;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ap_state->ap_condition = AP_COND_UNKNOWN;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf default:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ap_state->ap_rstate = AP_RSTATE_CONNECTED;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ap_state->ap_ostate = AP_OSTATE_UNCONFIGURED;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ap_state->ap_condition = AP_COND_UNKNOWN;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * This is actually internal error condition (non fatal),
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * beacuse we already checked all defined device types.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_LOG_D((sata_hba_inst, CE_WARN,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_cfgadm_state: Internal error: "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "unknown device type"));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Start or terminate the thread, depending on flag arg and current state
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_event_thread_control(int startstop)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf static int sata_event_thread_terminating = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf static int sata_event_thread_starting = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int i;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&sata_event_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (startstop == 0 && (sata_event_thread_starting == 1 ||
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_event_thread_terminating == 1)) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&sata_event_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (startstop == 1 && sata_event_thread_starting == 1) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&sata_event_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (startstop == 1 && sata_event_thread_terminating == 1) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_event_thread_starting = 1;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* wait til terminate operation completes */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf i = SATA_EVNT_DAEMON_TERM_WAIT/SATA_EVNT_DAEMON_TERM_TIMEOUT;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf while (sata_event_thread_terminating == 1) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (i-- <= 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_event_thread_starting = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&sata_event_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#ifdef SATA_DEBUG
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cmn_err(CE_WARN, "sata_event_thread_control: "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "timeout waiting for thread to terminate");
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#endif
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&sata_event_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf delay(drv_usectohz(SATA_EVNT_DAEMON_TERM_TIMEOUT));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&sata_event_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (startstop == 1) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_event_thread == NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_event_thread = thread_create(NULL, 0,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (void (*)())sata_event_daemon,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf &sata_hba_list, 0, &p0, TS_RUN, minclsyspri);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_event_thread_starting = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&sata_event_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * If we got here, thread may need to be terminated
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_event_thread != NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int i;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Signal event thread to go away */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_event_thread_terminating = 1;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_event_thread_terminate = 1;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cv_signal(&sata_event_cv);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Wait til daemon terminates.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf i = SATA_EVNT_DAEMON_TERM_WAIT/SATA_EVNT_DAEMON_TERM_TIMEOUT;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf while (sata_event_thread_terminate == 1) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&sata_event_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (i-- <= 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Daemon did not go away !!! */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#ifdef SATA_DEBUG
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cmn_err(CE_WARN, "sata_event_thread_control: "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "cannot terminate event daemon thread");
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#endif
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&sata_event_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf delay(drv_usectohz(SATA_EVNT_DAEMON_TERM_TIMEOUT));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&sata_event_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_event_thread_terminating = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ASSERT(sata_event_thread_terminating == 0);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ASSERT(sata_event_thread_starting == 0);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&sata_event_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Log sata message
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * dev pathname msg line preceeds the logged message.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_log(sata_hba_inst_t *sata_hba_inst, uint_t level, char *fmt, ...)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf char pathname[128];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf dev_info_t *dip;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf va_list ap;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&sata_log_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf va_start(ap, fmt);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (void) vsprintf(sata_log_buf, fmt, ap);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf va_end(ap);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_hba_inst != NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf dip = SATA_DIP(sata_hba_inst);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (void) ddi_pathname(dip, pathname);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf pathname[0] = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (level == CE_CONT) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_debug_flags == 0)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cmn_err(level, "?%s:\n %s\n", pathname, sata_log_buf);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf else
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cmn_err(level, "%s:\n %s\n", pathname, sata_log_buf);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cmn_err(level, "%s:\n %s", pathname, sata_log_buf);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&sata_log_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/* ******** Asynchronous HBA events handling & hotplugging support ******** */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * SATA HBA event notification function.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Events reported by SATA HBA drivers per HBA instance relate to a change in
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * a port and/or device state or a controller itself.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Events for different addresses/addr types cannot be combined.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * A warning message is generated for each event type.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Events are not processed by this function, so only the
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * event flag(s)is set for an affected entity and the event thread is
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * waken up. Event daemon thread processes all events.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * NOTE: Since more than one event may be reported at the same time, one
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * cannot determine a sequence of events when opposite event are reported, eg.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * LINK_LOST and LINK_ESTABLISHED. Actual port status during event processing
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * is taking precedence over reported events, i.e. may cause ignoring some
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * events.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#define SATA_EVENT_MAX_MSG_LENGTH 79
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfvoid
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_hba_event_notify(dev_info_t *dip, sata_device_t *sata_device, int event)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst_t *sata_hba_inst = NULL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_address_t *saddr;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_drive_info_t *sdinfo;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_port_stats_t *pstats;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int cport, pmport;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf char buf1[SATA_EVENT_MAX_MSG_LENGTH + 1];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf char buf2[SATA_EVENT_MAX_MSG_LENGTH + 1];
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf char *lcp;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf static char *err_msg_evnt_1 =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_hba_event_notify: invalid port event 0x%x ";
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf static char *err_msg_evnt_2 =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_hba_event_notify: invalid device event 0x%x ";
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int linkevent;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * There is a possibility that an event will be generated on HBA
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * that has not completed attachment or is detaching.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * HBA driver should prevent this, but just in case it does not,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * we need to ignore events for such HBA.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&sata_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf for (sata_hba_inst = sata_hba_list; sata_hba_inst != NULL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst = sata_hba_inst->satahba_next) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (SATA_DIP(sata_hba_inst) == dip)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_hba_inst->satahba_attached == 1)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf break;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&sata_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_hba_inst == NULL)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* HBA not attached */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ASSERT(sata_device != NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Validate address before - do not proceed with invalid address.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf saddr = &sata_device->satadev_addr;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (saddr->cport >= SATA_NUM_CPORTS(sata_hba_inst))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (saddr->qual == SATA_ADDR_PMPORT ||
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf saddr->qual == SATA_ADDR_DPMPORT)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Port Multiplier not supported yet */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport = saddr->cport;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf pmport = saddr->pmport;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf buf1[0] = buf2[0] = '\0';
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Events refer to devices, ports and controllers - each has
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * unique address. Events for different addresses cannot be combined.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (saddr->qual & (SATA_ADDR_CPORT | SATA_ADDR_PMPORT)) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&(SATA_CPORT_MUTEX(sata_hba_inst, cport)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* qualify this event(s) */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((event & SATA_EVNT_PORT_EVENTS) == 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Invalid event for the device port */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (void) sprintf(buf2, err_msg_evnt_1,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf event & SATA_EVNT_PORT_EVENTS);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst, cport)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf goto event_info;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (saddr->qual == SATA_ADDR_CPORT) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Controller's device port event */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (SATA_CPORT_INFO(sata_hba_inst, cport))->
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport_event_flags |=
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf event & SATA_EVNT_PORT_EVENTS;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf pstats =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf &(SATA_CPORT_INFO(sata_hba_inst, cport))->
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport_stats;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Port multiplier's device port event */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (SATA_PMPORT_INFO(sata_hba_inst, cport, pmport))->
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf pmport_event_flags |=
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf event & SATA_EVNT_PORT_EVENTS;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf pstats =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf &(SATA_PMPORT_INFO(sata_hba_inst, cport, pmport))->
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf pmport_stats;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Add to statistics and log the message. We have to do it
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * here rather than in the event daemon, because there may be
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * multiple events occuring before they are processed.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf linkevent = event &
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (SATA_EVNT_LINK_LOST | SATA_EVNT_LINK_ESTABLISHED);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (linkevent) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (linkevent == (SATA_EVNT_LINK_LOST |
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_EVNT_LINK_ESTABLISHED)) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* This is likely event combination */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (void) strlcat(buf1, "link lost/established, ",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_EVENT_MAX_MSG_LENGTH);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw if (pstats->link_lost < 0xffffffffffffffffULL)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf pstats->link_lost++;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (pstats->link_established <
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw 0xffffffffffffffffULL)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf pstats->link_established++;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf linkevent = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else if (linkevent & SATA_EVNT_LINK_LOST) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (void) strlcat(buf1, "link lost, ",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_EVENT_MAX_MSG_LENGTH);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw if (pstats->link_lost < 0xffffffffffffffffULL)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf pstats->link_lost++;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (void) strlcat(buf1, "link established, ",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_EVENT_MAX_MSG_LENGTH);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (pstats->link_established <
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw 0xffffffffffffffffULL)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf pstats->link_established++;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (event & SATA_EVNT_DEVICE_ATTACHED) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (void) strlcat(buf1, "device attached, ",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_EVENT_MAX_MSG_LENGTH);
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw if (pstats->device_attached < 0xffffffffffffffffULL)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf pstats->device_attached++;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (event & SATA_EVNT_DEVICE_DETACHED) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (void) strlcat(buf1, "device detached, ",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_EVENT_MAX_MSG_LENGTH);
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw if (pstats->device_detached < 0xffffffffffffffffULL)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf pstats->device_detached++;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (event & SATA_EVNT_PWR_LEVEL_CHANGED) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG1(SATA_DBG_EVENTS, sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "port %d power level changed", cport);
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw if (pstats->port_pwr_changed < 0xffffffffffffffffULL)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf pstats->port_pwr_changed++;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((event & ~SATA_EVNT_PORT_EVENTS) != 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* There should be no other events for this address */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (void) sprintf(buf2, err_msg_evnt_1,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf event & ~SATA_EVNT_PORT_EVENTS);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst, cport)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else if (saddr->qual & (SATA_ADDR_DCPORT | SATA_ADDR_DPMPORT)) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&(SATA_CPORT_MUTEX(sata_hba_inst, cport)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* qualify this event */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((event & SATA_EVNT_DEVICE_RESET) == 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Invalid event for a device */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (void) sprintf(buf2, err_msg_evnt_2,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf event & SATA_EVNT_DEVICE_RESET);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst, cport)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf goto event_info;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* drive event */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo = sata_get_device_info(sata_hba_inst, sata_device);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sdinfo != NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (event & SATA_EVNT_DEVICE_RESET) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (void) strlcat(buf1, "device reset, ",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_EVENT_MAX_MSG_LENGTH);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sdinfo->satadrv_stats.drive_reset <
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw 0xffffffffffffffffULL)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_stats.drive_reset++;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_event_flags |=
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_EVNT_DEVICE_RESET;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((event & ~SATA_EVNT_DEVICE_RESET) != 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Invalid event for a device */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (void) sprintf(buf2, err_msg_evnt_2,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf event & ~SATA_EVNT_DRIVE_EVENTS);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst, cport)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (saddr->qual != SATA_ADDR_NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Wrong address qualifier */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_LOG_D((sata_hba_inst, CE_WARN,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_hba_event_notify: invalid address 0x%x",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *(uint32_t *)saddr));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((event & SATA_EVNT_CONTROLLER_EVENTS) == 0 ||
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (event & ~SATA_EVNT_CONTROLLER_EVENTS) != 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Invalid event for the controller */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_LOG_D((sata_hba_inst, CE_WARN,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_hba_event_notify: invalid event 0x%x for "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "controller",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf event & SATA_EVNT_CONTROLLER_EVENTS));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf buf1[0] = '\0';
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* This may be a frequent and not interesting event */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG1(SATA_DBG_EVENTS, sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "controller power level changed\n", NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&sata_hba_inst->satahba_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_hba_inst->satahba_stats.ctrl_pwr_change <
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw 0xffffffffffffffffULL)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst->satahba_stats.ctrl_pwr_change++;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst->satahba_event_flags |=
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_EVNT_PWR_LEVEL_CHANGED;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&sata_hba_inst->satahba_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * If we got here, there is something to do with this HBA
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * instance.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&sata_hba_inst->satahba_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst->satahba_event_flags |= SATA_EVNT_MAIN;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&sata_hba_inst->satahba_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&sata_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_event_pending |= SATA_EVNT_MAIN; /* global event indicator */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&sata_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Tickle event thread */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&sata_event_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_event_thread_active == 0)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cv_signal(&sata_event_cv);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&sata_event_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfevent_info:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (buf1[0] != '\0') {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf lcp = strrchr(buf1, ',');
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (lcp != NULL)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *lcp = '\0';
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (saddr->qual == SATA_ADDR_CPORT ||
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf saddr->qual == SATA_ADDR_DCPORT) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (buf1[0] != '\0') {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_log(sata_hba_inst, CE_NOTE, "port %d: %s\n",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport, buf1);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (buf2[0] != '\0') {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_log(sata_hba_inst, CE_NOTE, "port %d: %s\n",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport, buf2);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else if (saddr->qual == SATA_ADDR_PMPORT ||
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf saddr->qual == SATA_ADDR_DPMPORT) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (buf1[0] != '\0') {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_log(sata_hba_inst, CE_NOTE,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "port %d pmport %d: %s\n", cport, pmport, buf1);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (buf2[0] != '\0') {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_log(sata_hba_inst, CE_NOTE,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "port %d pmport %d: %s\n", cport, pmport, buf2);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Event processing thread.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Arg is a pointer to the sata_hba_list pointer.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * It is not really needed, because sata_hba_list is global and static
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_event_daemon(void *arg)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#ifndef __lock_lint
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf _NOTE(ARGUNUSED(arg))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#endif
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst_t *sata_hba_inst;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf clock_t lbolt;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG1(SATA_DBG_EVENTS_DAEMON, NULL,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "SATA event daemon started\n", NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfloop:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Process events here. Walk through all registered HBAs
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&sata_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf for (sata_hba_inst = sata_hba_list; sata_hba_inst != NULL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst = sata_hba_inst->satahba_next) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ASSERT(sata_hba_inst != NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&sata_hba_inst->satahba_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_hba_inst->satahba_attached != 1 ||
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (sata_hba_inst->satahba_event_flags &
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_EVNT_SKIP) != 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&sata_hba_inst->satahba_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf continue;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_hba_inst->satahba_event_flags & SATA_EVNT_MAIN) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst->satahba_event_flags |= SATA_EVNT_SKIP;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&sata_hba_inst->satahba_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&sata_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Got the controller with pending event */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_process_controller_events(sata_hba_inst);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Since global mutex was released, there is a
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * possibility that HBA list has changed, so start
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * over from the top. Just processed controller
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * will be passed-over because of the SKIP flag.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf goto loop;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&sata_hba_inst->satahba_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Clear SKIP flag in all controllers */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf for (sata_hba_inst = sata_hba_list; sata_hba_inst != NULL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst = sata_hba_inst->satahba_next) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&sata_hba_inst->satahba_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst->satahba_event_flags &= ~SATA_EVNT_SKIP;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&sata_hba_inst->satahba_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&sata_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG1(SATA_DBG_EVENTS_DAEMON, NULL,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "SATA EVENT DAEMON suspending itself", NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#ifdef SATA_DEBUG
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((sata_func_enable & SATA_ENABLE_PROCESS_EVENTS) == 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_log(sata_hba_inst, CE_WARN,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "SATA EVENTS PROCESSING DISABLED\n");
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf thread_exit(); /* Daemon will not run again */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#endif
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&sata_event_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_event_thread_active = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&sata_event_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Go to sleep/suspend itself and wake up either because new event or
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * wait timeout. Exit if there is a termination request (driver
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * unload).
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf do {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf lbolt = ddi_get_lbolt();
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf lbolt += drv_usectohz(SATA_EVNT_DAEMON_SLEEP_TIME);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&sata_event_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (void) cv_timedwait(&sata_event_cv, &sata_event_mutex, lbolt);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_event_thread_active != 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&sata_event_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf continue;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Check if it is time to go away */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_event_thread_terminate == 1) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * It is up to the thread setting above flag to make
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * sure that this thread is not killed prematurely.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_event_thread_terminate = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_event_thread = NULL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&sata_event_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG1(SATA_DBG_EVENTS_DAEMON, NULL,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "SATA_EVENT_DAEMON_TERMINATING", NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf thread_exit(); { _NOTE(NOT_REACHED) }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&sata_event_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } while (!(sata_event_pending & SATA_EVNT_MAIN));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&sata_event_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_event_thread_active = 1;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&sata_event_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&sata_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_event_pending &= ~SATA_EVNT_MAIN;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&sata_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG1(SATA_DBG_EVENTS_DAEMON, NULL,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "SATA EVENT DAEMON READY TO PROCESS EVENT", NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf goto loop;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Specific HBA instance event processing.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * NOTE: At the moment, device event processing is limited to hard disks
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * only.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * cports only are supported - no pmports.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_process_controller_events(sata_hba_inst_t *sata_hba_inst)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int ncport;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf uint32_t event_flags;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_address_t *saddr;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG1(SATA_DBG_EVENTS_CNTRL, sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "Processing controller %d event(s)",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ddi_get_instance(SATA_DIP(sata_hba_inst)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&sata_hba_inst->satahba_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst->satahba_event_flags &= ~SATA_EVNT_MAIN;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf event_flags = sata_hba_inst->satahba_event_flags;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&sata_hba_inst->satahba_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Process controller power change first
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * HERE
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (event_flags & SATA_EVNT_PWR_LEVEL_CHANGED)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_process_cntrl_pwr_level_change(sata_hba_inst);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Search through ports/devices to identify affected port/device.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * We may have to process events for more than one port/device.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf for (ncport = 0; ncport < SATA_NUM_CPORTS(sata_hba_inst); ncport++) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&(SATA_CPORT_MUTEX(sata_hba_inst, ncport)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf event_flags = (SATA_CPORT_INFO(sata_hba_inst, ncport))->
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport_event_flags;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Check if port was locked by IOCTL processing */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (event_flags & SATA_APCTL_LOCK_PORT_BUSY) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * We ignore port events because port is busy
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * with AP control processing. Set again
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * controller and main event flag, so that
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * events may be processed by the next daemon
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * run.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst, ncport)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&sata_hba_inst->satahba_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst->satahba_event_flags |= SATA_EVNT_MAIN;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&sata_hba_inst->satahba_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&sata_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_event_pending |= SATA_EVNT_MAIN;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&sata_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG1(SATA_DBG_EVENTS_PROCPST, sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "Event processing postponed until "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "AP control processing completes",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Check other ports */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf continue;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Set BSY flag so that AP control would not
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * interfere with events processing for
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * this port.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (SATA_CPORT_INFO(sata_hba_inst, ncport))->
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport_event_flags |= SATA_EVNT_LOCK_PORT_BUSY;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst, ncport)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf saddr = &(SATA_CPORT_INFO(sata_hba_inst, ncport))->cport_addr;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((event_flags &
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (SATA_EVNT_PORT_EVENTS | SATA_EVNT_DRIVE_EVENTS)) != 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Got port event.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * We need some hierarchy of event processing as they
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * are affecting each other:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * 1. port failed
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * 2. device detached/attached
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * 3. link events - link events may trigger device
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * detached or device attached events in some
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * circumstances.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * 4. port power level changed
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (event_flags & SATA_EVNT_PORT_FAILED) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_process_port_failed_event(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf saddr);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (event_flags & SATA_EVNT_DEVICE_DETACHED) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_process_device_detached(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf saddr);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (event_flags & SATA_EVNT_DEVICE_ATTACHED) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_process_device_attached(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf saddr);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (event_flags &
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (SATA_EVNT_LINK_ESTABLISHED |
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_EVNT_LINK_LOST)) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_process_port_link_events(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf saddr);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (event_flags & SATA_EVNT_PWR_LEVEL_CHANGED) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_process_port_pwr_change(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf saddr);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (SATA_CPORT_DEV_TYPE(sata_hba_inst, ncport) !=
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_DTYPE_NONE) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* May have device event */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_process_device_reset(sata_hba_inst, saddr);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&(SATA_CPORT_MUTEX(sata_hba_inst, ncport)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Release PORT_BUSY flag */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (SATA_CPORT_INFO(sata_hba_inst, ncport))->
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport_event_flags &= ~SATA_EVNT_LOCK_PORT_BUSY;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst, ncport)));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } /* End of loop through the controller SATA ports */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Process HBA power level change reported by HBA driver.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Not implemented at this time - event is ignored.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_process_cntrl_pwr_level_change(sata_hba_inst_t *sata_hba_inst)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG1(SATA_DBG_EVENTS_PROC, sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "Processing controller power level change", NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Ignoring it for now */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&sata_hba_inst->satahba_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst->satahba_event_flags &= ~SATA_EVNT_PWR_LEVEL_CHANGED;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&sata_hba_inst->satahba_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Process port power level change reported by HBA driver.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Not implemented at this time - event is ignored.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_process_port_pwr_change(sata_hba_inst_t *sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_address_t *saddr)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_cport_info_t *cportinfo;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG1(SATA_DBG_EVENTS_PROC, sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "Processing port power level change", NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo = SATA_CPORT_INFO(sata_hba_inst, saddr->cport);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Reset event flag */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo->cport_event_flags &= ~SATA_EVNT_PWR_LEVEL_CHANGED;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Process port failure reported by HBA driver.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * cports support only - no pmports.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_process_port_failed_event(sata_hba_inst_t *sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_address_t *saddr)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_cport_info_t *cportinfo;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo = SATA_CPORT_INFO(sata_hba_inst, saddr->cport);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Reset event flag first */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo->cport_event_flags &= ~SATA_EVNT_PORT_FAILED;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* If the port is in SHUTDOWN or FAILED state, ignore this event. */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((cportinfo->cport_state &
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (SATA_PSTATE_SHUTDOWN | SATA_PSTATE_FAILED)) == 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Fail the port */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo->cport_state = SATA_PSTATE_FAILED;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_log(sata_hba_inst, CE_WARN, "port %d failed", saddr->cport);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Device Reset Event processing.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * The seqeunce is managed by 3 stage flags:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * - reset event reported,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * - reset event being processed,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * - request to clear device reset state.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_process_device_reset(sata_hba_inst_t *sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_address_t *saddr)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_drive_info_t old_sdinfo; /* local copy of the drive info */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_drive_info_t *sdinfo;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_cport_info_t *cportinfo;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device_t sata_device;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int rval;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* We only care about host sata cport for now */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo = SATA_CPORT_INFO(sata_hba_inst, saddr->cport);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* If the port is in SHUTDOWN or FAILED state, ignore reset event. */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((cportinfo->cport_state &
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (SATA_PSTATE_SHUTDOWN | SATA_PSTATE_FAILED)) != 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((SATA_CPORT_DEV_TYPE(sata_hba_inst, saddr->cport) &
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_VALID_DEV_TYPE) == 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo = SATA_CPORT_DRV_INFO(sata_hba_inst, saddr->cport);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sdinfo == NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((sdinfo->satadrv_event_flags & SATA_EVNT_DEVICE_RESET) == 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Nothing to do */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG1(SATA_DBG_EVENTS_PROC, sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "Processing port %d device reset", saddr->cport);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sdinfo->satadrv_event_flags & SATA_EVNT_INPROC_DEVICE_RESET) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Something is weird - new device reset event */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG1(SATA_DBG_EVENTS_PROC, sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "Overlapping device reset events!", NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Just leave */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Clear event flag */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_event_flags &= ~SATA_EVNT_DEVICE_RESET;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* It seems that we always need to check the port state first */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_rev = SATA_DEVICE_REV;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_addr = *saddr;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * We have to exit mutex, because the HBA probe port function may
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * block on its own mutex.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rval = (*SATA_PROBE_PORT_FUNC(sata_hba_inst))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (SATA_DIP(sata_hba_inst), &sata_device);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_update_port_info(sata_hba_inst, &sata_device);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (rval != SATA_SUCCESS) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Something went wrong? Fail the port */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo->cport_state = SATA_PSTATE_FAILED;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_LOG_D((sata_hba_inst, CE_WARN, "Port %d probing failed",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf saddr->cport));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((sata_device.satadev_scr.sstatus &
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_PORT_DEVLINK_UP_MASK) !=
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_PORT_DEVLINK_UP ||
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_type == SATA_DTYPE_NONE) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * No device to process, anymore. Some other event processing
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * would or have already performed port info cleanup.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * To be safe (HBA may need it), request clearing device
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * reset condition.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_event_flags = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_event_flags |= SATA_EVNT_CLEAR_DEVICE_RESET;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Mark device reset processing as active */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_event_flags |= SATA_EVNT_INPROC_DEVICE_RESET;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf old_sdinfo = *sdinfo; /* local copy of the drive info */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw if (sata_set_drive_features(sata_hba_inst, &old_sdinfo, 1) ==
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_FAILURE) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Restoring drive setting failed.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Probe the port first, to check if the port state has changed
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_rev = SATA_DEVICE_REV;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_addr = *saddr;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_addr.qual = SATA_ADDR_CPORT;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* probe port */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rval = (*SATA_PROBE_PORT_FUNC(sata_hba_inst))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (SATA_DIP(sata_hba_inst), &sata_device);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (rval == SATA_SUCCESS &&
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (sata_device.satadev_state &
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (SATA_PSTATE_SHUTDOWN | SATA_PSTATE_FAILED)) == 0 &&
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (sata_device.satadev_scr.sstatus &
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_PORT_DEVLINK_UP_MASK) == SATA_PORT_DEVLINK_UP &&
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (sata_device.satadev_type & SATA_DTYPE_ATADISK) != 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * We may retry this a bit later - reinstate reset
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * condition
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((cportinfo->cport_dev_type &
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_VALID_DEV_TYPE) != 0 &&
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_CPORTINFO_DRV_INFO(cportinfo) != NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo = SATA_CPORTINFO_DRV_INFO(cportinfo);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_event_flags |=
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_EVNT_DEVICE_RESET;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_event_flags &=
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ~SATA_EVNT_INPROC_DEVICE_RESET;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&SATA_CPORT_INFO(sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf saddr->cport)->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&sata_hba_inst->satahba_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst->satahba_event_flags |=
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_EVNT_MAIN;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&sata_hba_inst->satahba_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * No point of retrying - some other event processing
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * would or already did port info cleanup.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * To be safe (HBA may need it),
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * request clearing device reset condition.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_event_flags = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_event_flags |=
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_EVNT_CLEAR_DEVICE_RESET;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Raise the flag indicating that the next sata command could
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * be sent with SATA_CLEAR_DEV_RESET_STATE flag, if no new device
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * reset is reported.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((cportinfo->cport_dev_type & SATA_VALID_DEV_TYPE) != 0 &&
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_CPORTINFO_DRV_INFO(cportinfo) != NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo = SATA_CPORTINFO_DRV_INFO(cportinfo);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_event_flags &= ~SATA_EVNT_INPROC_DEVICE_RESET;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_event_flags |= SATA_EVNT_CLEAR_DEVICE_RESET;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Port Link Events processing.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Every link established event may involve device reset (due to
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * COMRESET signal, equivalent of the hard reset) so arbitrarily
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * set device reset event for an attached device (if any).
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * If the port is in SHUTDOWN or FAILED state, ignore link events.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * The link established event processing varies, depending on the state
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * of the target node, HBA hotplugging capabilities, state of the port.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * If the link is not active, the link established event is ignored.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * If HBA cannot detect device attachment and there is no target node,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * the link established event triggers device attach event processing.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Else, link established event triggers device reset event processing.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * The link lost event processing varies, depending on a HBA hotplugging
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * capability and the state of the port (link active or not active).
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * If the link is active, the lost link event is ignored.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * If HBA cannot detect device removal, the lost link event triggers
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * device detached event processing after link lost timeout.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Else, the event is ignored.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * NOTE: Only cports are processed for now, i.e. no port multiplier ports
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_process_port_link_events(sata_hba_inst_t *sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_address_t *saddr)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device_t sata_device;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_cport_info_t *cportinfo;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_drive_info_t *sdinfo;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int event_flags;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int rval;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG1(SATA_DBG_EVENTS_PROC, sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "Processing port %d link event(s)", saddr->cport);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo = SATA_CPORT_INFO(sata_hba_inst, saddr->cport);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf event_flags = cportinfo->cport_event_flags;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Reset event flags first */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo->cport_event_flags &=
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ~(SATA_EVNT_LINK_ESTABLISHED | SATA_EVNT_LINK_LOST);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* If the port is in SHUTDOWN or FAILED state, ignore link events. */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((cportinfo->cport_state &
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (SATA_PSTATE_SHUTDOWN | SATA_PSTATE_FAILED)) != 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * For the sanity sake get current port state.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Set device address only. Other sata_device fields should be
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * set by HBA driver.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_rev = SATA_DEVICE_REV;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_addr = *saddr;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * We have to exit mutex, because the HBA probe port function may
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * block on its own mutex.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rval = (*SATA_PROBE_PORT_FUNC(sata_hba_inst))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (SATA_DIP(sata_hba_inst), &sata_device);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_update_port_info(sata_hba_inst, &sata_device);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (rval != SATA_SUCCESS) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Something went wrong? Fail the port */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo->cport_state = SATA_PSTATE_FAILED;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_LOG_D((sata_hba_inst, CE_WARN, "Port %d probing failed",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf saddr->cport));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * We may want to release device info structure, but
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * it is not necessary.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* port probed successfully */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo->cport_state |= SATA_STATE_PROBED | SATA_STATE_READY;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (event_flags & SATA_EVNT_LINK_ESTABLISHED) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((sata_device.satadev_scr.sstatus &
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_PORT_DEVLINK_UP_MASK) != SATA_PORT_DEVLINK_UP) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Ignore event */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG1(SATA_DBG_EVENTS_PROC, sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "Ignoring port %d link established event - "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "link down",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf saddr->cport);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf goto linklost;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG1(SATA_DBG_EVENTS_PROC, sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "Processing port %d link established event",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf saddr->cport);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * For the sanity sake check if a device is attached - check
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * return state of a port probing.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_device.satadev_type != SATA_DTYPE_NONE &&
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_type != SATA_DTYPE_PMULT) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * HBA port probe indicated that there is a device
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * attached. Check if the framework had device info
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * structure attached for this device.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (cportinfo->cport_dev_type != SATA_DTYPE_NONE) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ASSERT(SATA_CPORTINFO_DRV_INFO(cportinfo) !=
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo = SATA_CPORTINFO_DRV_INFO(cportinfo);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((sdinfo->satadrv_type &
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_VALID_DEV_TYPE) != 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Dev info structure is present.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * If dev_type is set to known type in
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * the framework's drive info struct
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * then the device existed before and
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * the link was probably lost
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * momentarily - in such case
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * we may want to check device
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * identity.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Identity check is not supported now.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Link established event
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * triggers device reset event.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (SATA_CPORTINFO_DRV_INFO(cportinfo))->
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf satadrv_event_flags |=
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_EVNT_DEVICE_RESET;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else if (cportinfo->cport_dev_type ==
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_DTYPE_NONE) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * We got new device attached! If HBA does not
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * generate device attached events, trigger it
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * here.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (!(SATA_FEATURES(sata_hba_inst) &
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_CTLF_HOTPLUG)) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo->cport_event_flags |=
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_EVNT_DEVICE_ATTACHED;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Reset link lost timeout */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo->cport_link_lost_time = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlflinklost:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (event_flags & SATA_EVNT_LINK_LOST) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((sata_device.satadev_scr.sstatus &
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_PORT_DEVLINK_UP_MASK) == SATA_PORT_DEVLINK_UP) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Ignore event */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG1(SATA_DBG_EVENTS_PROC, sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "Ignoring port %d link lost event - link is up",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf saddr->cport);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf goto done;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#ifdef SATA_DEBUG
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (cportinfo->cport_link_lost_time == 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG1(SATA_DBG_EVENTS_PROC, sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "Processing port %d link lost event",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf saddr->cport);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf#endif
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * When HBA cannot generate device attached/detached events,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * we need to track link lost time and eventually generate
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * device detach event.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (!(SATA_FEATURES(sata_hba_inst) & SATA_CTLF_HOTPLUG)) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* We are tracking link lost time */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (cportinfo->cport_link_lost_time == 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* save current time (lbolt value) */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo->cport_link_lost_time =
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ddi_get_lbolt();
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* just keep link lost event */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo->cport_event_flags |=
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_EVNT_LINK_LOST;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf clock_t cur_time = ddi_get_lbolt();
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((cur_time -
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo->cport_link_lost_time) >=
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf drv_usectohz(
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_EVNT_LINK_LOST_TIMEOUT)) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* trigger device detach event */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo->cport_event_flags |=
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_EVNT_DEVICE_DETACHED;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo->cport_link_lost_time = 0;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG1(SATA_DBG_EVENTS,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "Triggering port %d "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "device detached event",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf saddr->cport);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* keep link lost event */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo->cport_event_flags |=
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_EVNT_LINK_LOST;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * We could change port state to disable/delay access to
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * the attached device until the link is recovered.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfdone:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf event_flags = cportinfo->cport_event_flags;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (event_flags != 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&sata_hba_inst->satahba_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_hba_inst->satahba_event_flags |= SATA_EVNT_MAIN;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&sata_hba_inst->satahba_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&sata_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_event_pending |= SATA_EVNT_MAIN;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&sata_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Device Detached Event processing.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Port is probed to find if a device is really gone. If so,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * the device info structure is detached from the SATA port info structure
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * and released.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Port status is updated.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * NOTE: Process cports event only, no port multiplier ports.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_process_device_detached(sata_hba_inst_t *sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_address_t *saddr)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_cport_info_t *cportinfo;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_drive_info_t *sdevinfo;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device_t sata_device;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf dev_info_t *tdip;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int rval;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG1(SATA_DBG_EVENTS_PROC, sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "Processing port %d device detached", saddr->cport);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo = SATA_CPORT_INFO(sata_hba_inst, saddr->cport);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Clear event flag */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo->cport_event_flags &= ~SATA_EVNT_DEVICE_DETACHED;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* If the port is in SHUTDOWN or FAILED state, ignore detach event. */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((cportinfo->cport_state &
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (SATA_PSTATE_SHUTDOWN | SATA_PSTATE_FAILED)) != 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* For sanity, re-probe the port */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_rev = SATA_DEVICE_REV;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_addr = *saddr;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * We have to exit mutex, because the HBA probe port function may
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * block on its own mutex.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rval = (*SATA_PROBE_PORT_FUNC(sata_hba_inst))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (SATA_DIP(sata_hba_inst), &sata_device);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_update_port_info(sata_hba_inst, &sata_device);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (rval != SATA_SUCCESS) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Something went wrong? Fail the port */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo->cport_state = SATA_PSTATE_FAILED;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_LOG_D((sata_hba_inst, CE_WARN, "Port %d probing failed",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf saddr->cport));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * We may want to release device info structure, but
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * it is not necessary.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } else {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* port probed successfully */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo->cport_state |= SATA_STATE_PROBED | SATA_STATE_READY;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Check if a device is still attached. For sanity, check also
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * link status - if no link, there is no device.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((sata_device.satadev_scr.sstatus & SATA_PORT_DEVLINK_UP_MASK) ==
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_PORT_DEVLINK_UP && sata_device.satadev_type !=
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_DTYPE_NONE) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Device is still attached - ignore detach event.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG1(SATA_DBG_EVENTS_PROC, sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "Ignoring detach - device still attached to port %d",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_addr.cport);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * We need to detach and release device info structure here
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (SATA_CPORTINFO_DRV_INFO(cportinfo) != NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdevinfo = SATA_CPORTINFO_DRV_INFO(cportinfo);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_CPORTINFO_DRV_INFO(cportinfo) = NULL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (void) kmem_free((void *)sdevinfo,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sizeof (sata_drive_info_t));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo->cport_dev_type = SATA_DTYPE_NONE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Device cannot be reached anymore, even if the target node may be
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * still present.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_log(sata_hba_inst, CE_WARN, "SATA device detached at port %d",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_addr.cport);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Try to offline a device and remove target node if it still exists
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf tdip = sata_get_target_dip(SATA_DIP(sata_hba_inst), saddr->cport);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (tdip != NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * target node exist - unconfigure device first, then remove
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * the node
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (ndi_devi_offline(tdip, NDI_UNCONFIG) != NDI_SUCCESS) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * PROBLEM - no device, but target node remained
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * This happens when the file was open or node was
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * waiting for resources.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_LOG_D((sata_hba_inst, CE_WARN,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_process_device_detached: "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "Failed to unconfigure removed device."));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (ndi_devi_offline(tdip, NDI_DEVI_REMOVE) != NDI_SUCCESS) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * PROBLEM - no device, but target node remained
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * This happens when the file was open or node was
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * waiting for resources.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_LOG_D((sata_hba_inst, CE_WARN,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_process_device_detached: "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "Failed to remove target node for "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "removed device."));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw /*
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw * Generate sysevent - EC_DR / ESC_DR_AP_STATE_CHANGE
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw * with the hint: SE_HINT_REMOVE
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw */
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw sata_gen_sysevent(sata_hba_inst, saddr, SE_HINT_REMOVE);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Device Attached Event processing.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Port state is checked to verify that a device is really attached. If so,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * the device info structure is created and attached to the SATA port info
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * structure.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * This function cannot be called in interrupt context (it may sleep).
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * NOTE: Process cports event only, no port multiplier ports.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsata_process_device_attached(sata_hba_inst_t *sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_address_t *saddr)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_cport_info_t *cportinfo;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_drive_info_t *sdevinfo;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device_t sata_device;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf dev_info_t *tdip;
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw int rval;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG1(SATA_DBG_EVENTS_PROC, sata_hba_inst,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "Processing port %d device attached", saddr->cport);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo = SATA_CPORT_INFO(sata_hba_inst, saddr->cport);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Clear event flag first */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo->cport_event_flags &= ~SATA_EVNT_DEVICE_ATTACHED;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* If the port is in SHUTDOWN or FAILED state, ignore event. */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((cportinfo->cport_state &
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (SATA_PSTATE_SHUTDOWN | SATA_PSTATE_FAILED)) != 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * If the sata_drive_info structure is found attached to the port info,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * something went wrong in the event reporting and processing sequence.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * To recover, arbitrarily release device info structure and issue
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * a warning.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (SATA_CPORTINFO_DRV_INFO(cportinfo) != NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdevinfo = SATA_CPORTINFO_DRV_INFO(cportinfo);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_CPORTINFO_DRV_INFO(cportinfo) = NULL;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (void) kmem_free((void *)sdevinfo,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sizeof (sata_drive_info_t));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_LOG_D((sata_hba_inst, CE_WARN,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "Arbitrarily detaching old device info."));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cportinfo->cport_dev_type = SATA_DTYPE_NONE;
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw /* For sanity, re-probe the port */
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw sata_device.satadev_rev = SATA_DEVICE_REV;
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw sata_device.satadev_addr = *saddr;
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw /*
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw * We have to exit mutex, because the HBA probe port function may
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw * block on its own mutex.
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw */
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->cport_mutex);
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw rval = (*SATA_PROBE_PORT_FUNC(sata_hba_inst))
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw (SATA_DIP(sata_hba_inst), &sata_device);
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw mutex_enter(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->cport_mutex);
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw sata_update_port_info(sata_hba_inst, &sata_device);
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw if (rval != SATA_SUCCESS) {
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw /* Something went wrong? Fail the port */
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw cportinfo->cport_state = SATA_PSTATE_FAILED;
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw cport_mutex);
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw SATA_LOG_D((sata_hba_inst, CE_WARN, "Port %d probing failed",
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw saddr->cport));
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw return;
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw } else {
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw /* port probed successfully */
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw cportinfo->cport_state |= SATA_STATE_PROBED | SATA_STATE_READY;
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw }
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw /*
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw * Check if a device is still attached. For sanity, check also
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw * link status - if no link, there is no device.
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw */
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw if ((sata_device.satadev_scr.sstatus & SATA_PORT_DEVLINK_UP_MASK) !=
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw SATA_PORT_DEVLINK_UP || sata_device.satadev_type ==
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw SATA_DTYPE_NONE) {
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw /*
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw * No device - ignore attach event.
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw */
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw cport_mutex);
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw SATADBG1(SATA_DBG_EVENTS_PROC, sata_hba_inst,
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw "Ignoring attach - no device connected to port %d",
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw sata_device.satadev_addr.cport);
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw return;
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw }
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->cport_mutex);
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw /*
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw * Generate sysevent - EC_DR / ESC_DR_AP_STATE_CHANGE
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw * with the hint: SE_HINT_INSERT
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw */
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw sata_gen_sysevent(sata_hba_inst, saddr, SE_HINT_INSERT);
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Make sure that there is no target node for that device.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * If so, release it. It should not happen, unless we had problem
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * removing the node when device was detached.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf tdip = sata_get_target_dip(SATA_DIP(sata_hba_inst), saddr->cport);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (tdip != NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_LOG_D((sata_hba_inst, CE_WARN,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_process_device_attached: "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "old device target node exists!!!"));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * target node exist - unconfigure device first, then remove
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * the node
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (ndi_devi_offline(tdip, NDI_UNCONFIG) != NDI_SUCCESS) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * PROBLEM - no device, but target node remained
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * This happens when the file was open or node was
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * waiting for resources.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_LOG_D((sata_hba_inst, CE_WARN,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_process_device_attached: "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "Failed to unconfigure old target node!"));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Following call will retry node offlining and removing it */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (ndi_devi_offline(tdip, NDI_DEVI_REMOVE) != NDI_SUCCESS) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* PROBLEM - no device, but target node remained */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_LOG_D((sata_hba_inst, CE_WARN,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "sata_process_device_attached: "
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "Failed to remove old target node!"));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * It is not clear, what should be done here.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * For now, we will not attach a new device
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw * Reprobing port will take care of the creation of the device info
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw * structure and determination of the device type.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_device.satadev_addr = *saddr;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (void) sata_reprobe_port(sata_hba_inst, &sata_device);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * If device was successfully attached, an explicit
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * 'configure' command is needed to configure it.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_enter(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((cportinfo->cport_state & SATA_STATE_READY) &&
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw cportinfo->cport_dev_type != SATA_DTYPE_NONE) {
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw sata_log(sata_hba_inst, CE_WARN,
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw "SATA device attached at port %d", saddr->cport);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw if (SATA_CPORTINFO_DRV_INFO(cportinfo) != NULL) {
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw sata_drive_info_t new_sdinfo;
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw /* Log device info data */
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw new_sdinfo = *(SATA_CPORTINFO_DRV_INFO(cportinfo));
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw sata_show_drive_info(sata_hba_inst, &new_sdinfo);
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, saddr->cport)->cport_mutex);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw * sata_set_drive_featues function compares current device features setting
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw * with the saved device features settings and, if there is a difference,
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw * it restores device features setting to the previously saved state.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Device Identify data has to be current.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * At the moment only read ahead and write cache settings are considered.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * This function cannot be called in the interrupt context (it may sleep).
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw * The input argument sdinfo should point to the drive info structure
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw * to be updated after features are set.
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Returns TRUE if successful or there was nothing to do.
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw * Returns FALSE if device features cound not be set .
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Note: This function may fail the port, making it inaccessible.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Explicit port disconnect/connect or physical device
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * detach/attach is required to re-evaluate it's state afterwards
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic int
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelwsata_set_drive_features(sata_hba_inst_t *sata_hba_inst,
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw sata_drive_info_t *sdinfo, int restore)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf{
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf int rval = SATA_SUCCESS;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sata_drive_info_t new_sdinfo;
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw char *finfo = "sata_set_drive_features: cannot";
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw char *finfox;
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw int cache_op;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf bzero(&new_sdinfo, sizeof (sata_drive_info_t));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf new_sdinfo.satadrv_addr = sdinfo->satadrv_addr;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf new_sdinfo.satadrv_type = sdinfo->satadrv_type;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_fetch_device_identify_data(sata_hba_inst, &new_sdinfo) != 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Cannot get device identification - retry later
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_LOG_D((sata_hba_inst, CE_WARN,
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw "%s fetch device identify data\n", finfo));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (SATA_FAILURE);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Arbitrarily set UDMA mode */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_set_udma_mode(sata_hba_inst, &new_sdinfo) != SATA_SUCCESS) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_LOG_D((sata_hba_inst, CE_WARN,
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw "%s set UDMA mode\n", finfo));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (SATA_FAILURE);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (!(new_sdinfo.satadrv_id.ai_cmdset82 & SATA_LOOK_AHEAD) &&
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf !(new_sdinfo.satadrv_id.ai_cmdset82 & SATA_WRITE_CACHE)) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* None of the features is supported - do nothing */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG1(SATA_DBG_EVENTS_PROC, sata_hba_inst,
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw "settable features not supported\n", NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (SATA_SUCCESS);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (((new_sdinfo.satadrv_id.ai_features85 & SATA_LOOK_AHEAD) &&
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (sdinfo->satadrv_settings & SATA_DEV_READ_AHEAD)) &&
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf ((new_sdinfo.satadrv_id.ai_features85 & SATA_WRITE_CACHE) &&
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (sdinfo->satadrv_settings & SATA_DEV_WRITE_CACHE))) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Nothing to do */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATADBG1(SATA_DBG_EVENTS_PROC, sata_hba_inst,
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw "no device features to set\n", NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (SATA_SUCCESS);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw finfox = (restore != 0) ? " restore device features" :
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw " initialize device features\n";
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (!((new_sdinfo.satadrv_id.ai_features85 & SATA_LOOK_AHEAD) &&
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (sdinfo->satadrv_settings & SATA_DEV_READ_AHEAD))) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sdinfo->satadrv_settings & SATA_DEV_READ_AHEAD)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Enable read ahead / read cache */
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw cache_op = SATAC_SF_ENABLE_READ_AHEAD;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf else
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Disable read ahead / read cache */
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw cache_op = SATAC_SF_DISABLE_READ_AHEAD;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw /* Try to set read cache mode */
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw if (sata_set_cache_mode(sata_hba_inst, &new_sdinfo,
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw cache_op) != SATA_SUCCESS) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Pkt execution failed */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rval = SATA_FAILURE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (!((new_sdinfo.satadrv_id.ai_features85 & SATA_WRITE_CACHE) &&
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (sdinfo->satadrv_settings & SATA_DEV_WRITE_CACHE))) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sdinfo->satadrv_settings & SATA_DEV_WRITE_CACHE)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Enable write cache */
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw cache_op = SATAC_SF_ENABLE_WRITE_CACHE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf else
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Disable write cache */
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw cache_op = SATAC_SF_DISABLE_WRITE_CACHE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw /* Try to set write cache mode */
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw if (sata_set_cache_mode(sata_hba_inst, &new_sdinfo,
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw cache_op) != SATA_SUCCESS) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Pkt execution failed */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rval = SATA_FAILURE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw if (rval == SATA_FAILURE)
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw SATA_LOG_D((sata_hba_inst, CE_WARN,
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw "%s %s", finfo, finfox));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * We need to fetch Device Identify data again
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (sata_fetch_device_identify_data(sata_hba_inst, &new_sdinfo) != 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /*
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Cannot get device identification - retry later
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf SATA_LOG_D((sata_hba_inst, CE_WARN,
7a1efdfee8cbdecea34d3d866bbfb46e39b06e0apawelw "%s cannot re-fetch device identify data\n"));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rval = SATA_FAILURE;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf }
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Copy device sata info. */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf sdinfo->satadrv_id = new_sdinfo.satadrv_id;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (rval);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw
f76ee27a7c2e4dbe22aec6ce187c04e980f90349pawelw
c03acfcad7780db4ddf763511a82026680b3b2c1ls/*
c03acfcad7780db4ddf763511a82026680b3b2c1ls *
c03acfcad7780db4ddf763511a82026680b3b2c1ls * Returns 1 if threshold exceeded, 0 if threshold no exceeded, -1 if
c03acfcad7780db4ddf763511a82026680b3b2c1ls * unable to determine.
c03acfcad7780db4ddf763511a82026680b3b2c1ls *
c03acfcad7780db4ddf763511a82026680b3b2c1ls * Cannot be called in an interrupt context.
c03acfcad7780db4ddf763511a82026680b3b2c1ls *
c03acfcad7780db4ddf763511a82026680b3b2c1ls * Called by sata_build_lsense_page_2f()
c03acfcad7780db4ddf763511a82026680b3b2c1ls */
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1lsstatic int
c03acfcad7780db4ddf763511a82026680b3b2c1lssata_fetch_smart_return_status(sata_hba_inst_t *sata_hba_inst,
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_drive_info_t *sdinfo)
c03acfcad7780db4ddf763511a82026680b3b2c1ls{
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_pkt_t *spkt;
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_cmd_t *scmd;
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_pkt_txlate_t *spx;
c03acfcad7780db4ddf763511a82026680b3b2c1ls int rval;
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls spx = kmem_zalloc(sizeof (sata_pkt_txlate_t), KM_SLEEP);
c03acfcad7780db4ddf763511a82026680b3b2c1ls spx->txlt_sata_hba_inst = sata_hba_inst;
c03acfcad7780db4ddf763511a82026680b3b2c1ls spx->txlt_scsi_pkt = NULL; /* No scsi pkt involved */
c03acfcad7780db4ddf763511a82026680b3b2c1ls spkt = sata_pkt_alloc(spx, SLEEP_FUNC);
c03acfcad7780db4ddf763511a82026680b3b2c1ls if (spkt == NULL) {
c03acfcad7780db4ddf763511a82026680b3b2c1ls kmem_free(spx, sizeof (sata_pkt_txlate_t));
c03acfcad7780db4ddf763511a82026680b3b2c1ls return (-1);
c03acfcad7780db4ddf763511a82026680b3b2c1ls }
c03acfcad7780db4ddf763511a82026680b3b2c1ls /* address is needed now */
c03acfcad7780db4ddf763511a82026680b3b2c1ls spkt->satapkt_device.satadev_addr = sdinfo->satadrv_addr;
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls /* Fill sata_pkt */
c03acfcad7780db4ddf763511a82026680b3b2c1ls spkt->satapkt_device.satadev_addr = sdinfo->satadrv_addr;
c03acfcad7780db4ddf763511a82026680b3b2c1ls spkt->satapkt_op_mode = SATA_OPMODE_SYNCH | SATA_OPMODE_INTERRUPTS;
c03acfcad7780db4ddf763511a82026680b3b2c1ls /* Synchronous mode, no callback */
c03acfcad7780db4ddf763511a82026680b3b2c1ls spkt->satapkt_comp = NULL;
c03acfcad7780db4ddf763511a82026680b3b2c1ls /* Timeout 30s */
c03acfcad7780db4ddf763511a82026680b3b2c1ls spkt->satapkt_time = sata_default_pkt_time;
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd = &spkt->satapkt_cmd;
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_flags.sata_special_regs = B_TRUE;
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_flags.sata_data_direction = SATA_DIR_NODATA_XFER;
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls /* Set up which registers need to be returned */
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_flags.sata_copy_out_lba_mid_lsb = B_TRUE;
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_flags.sata_copy_out_lba_high_lsb = B_TRUE;
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls /* Build SMART_RETURN_STATUS cmd in the sata_pkt */
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_addr_type = 0; /* N/A */
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_sec_count_lsb = 0; /* N/A */
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_lba_low_lsb = 0; /* N/A */
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_lba_mid_lsb = SMART_MAGIC_VAL_1;
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_lba_high_lsb = SMART_MAGIC_VAL_2;
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_features_reg = SATA_SMART_RETURN_STATUS;
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_device_reg = 0; /* Always device 0 */
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_cmd_reg = SATAC_SMART;
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls /* Send pkt to SATA HBA driver */
c03acfcad7780db4ddf763511a82026680b3b2c1ls if ((*SATA_START_FUNC(sata_hba_inst))(SATA_DIP(sata_hba_inst), spkt) !=
c03acfcad7780db4ddf763511a82026680b3b2c1ls SATA_TRAN_ACCEPTED ||
c03acfcad7780db4ddf763511a82026680b3b2c1ls spkt->satapkt_reason != SATA_PKT_COMPLETED) {
c03acfcad7780db4ddf763511a82026680b3b2c1ls /*
c03acfcad7780db4ddf763511a82026680b3b2c1ls * Whoops, no SMART RETURN STATUS
c03acfcad7780db4ddf763511a82026680b3b2c1ls */
c03acfcad7780db4ddf763511a82026680b3b2c1ls rval = -1;
c03acfcad7780db4ddf763511a82026680b3b2c1ls } else {
c03acfcad7780db4ddf763511a82026680b3b2c1ls if (scmd->satacmd_error_reg & SATA_ERROR_ABORT) {
c03acfcad7780db4ddf763511a82026680b3b2c1ls rval = -1;
c03acfcad7780db4ddf763511a82026680b3b2c1ls goto fail;
c03acfcad7780db4ddf763511a82026680b3b2c1ls }
c03acfcad7780db4ddf763511a82026680b3b2c1ls if (scmd->satacmd_status_reg & SATA_STATUS_ERR) {
c03acfcad7780db4ddf763511a82026680b3b2c1ls rval = -1;
c03acfcad7780db4ddf763511a82026680b3b2c1ls goto fail;
c03acfcad7780db4ddf763511a82026680b3b2c1ls }
c03acfcad7780db4ddf763511a82026680b3b2c1ls if ((scmd->satacmd_lba_mid_lsb == SMART_MAGIC_VAL_1) &&
c03acfcad7780db4ddf763511a82026680b3b2c1ls (scmd->satacmd_lba_high_lsb == SMART_MAGIC_VAL_2))
c03acfcad7780db4ddf763511a82026680b3b2c1ls rval = 0;
c03acfcad7780db4ddf763511a82026680b3b2c1ls else if ((scmd->satacmd_lba_mid_lsb == SMART_MAGIC_VAL_3) &&
c03acfcad7780db4ddf763511a82026680b3b2c1ls (scmd->satacmd_lba_high_lsb == SMART_MAGIC_VAL_4))
c03acfcad7780db4ddf763511a82026680b3b2c1ls rval = 1;
c03acfcad7780db4ddf763511a82026680b3b2c1ls else {
c03acfcad7780db4ddf763511a82026680b3b2c1ls rval = -1;
c03acfcad7780db4ddf763511a82026680b3b2c1ls goto fail;
c03acfcad7780db4ddf763511a82026680b3b2c1ls }
c03acfcad7780db4ddf763511a82026680b3b2c1ls }
c03acfcad7780db4ddf763511a82026680b3b2c1lsfail:
c03acfcad7780db4ddf763511a82026680b3b2c1ls /* Free allocated resources */
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_pkt_free(spx);
c03acfcad7780db4ddf763511a82026680b3b2c1ls kmem_free(spx, sizeof (sata_pkt_txlate_t));
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls return (rval);
c03acfcad7780db4ddf763511a82026680b3b2c1ls}
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls/*
c03acfcad7780db4ddf763511a82026680b3b2c1ls *
c03acfcad7780db4ddf763511a82026680b3b2c1ls * Returns 0 if succeeded, -1 otherwise
c03acfcad7780db4ddf763511a82026680b3b2c1ls *
c03acfcad7780db4ddf763511a82026680b3b2c1ls * Cannot be called in an interrupt context.
c03acfcad7780db4ddf763511a82026680b3b2c1ls *
c03acfcad7780db4ddf763511a82026680b3b2c1ls */
c03acfcad7780db4ddf763511a82026680b3b2c1lsstatic int
c03acfcad7780db4ddf763511a82026680b3b2c1lssata_fetch_smart_data(
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_hba_inst_t *sata_hba_inst,
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_drive_info_t *sdinfo,
c03acfcad7780db4ddf763511a82026680b3b2c1ls struct smart_data *smart_data)
c03acfcad7780db4ddf763511a82026680b3b2c1ls{
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_pkt_t *spkt;
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_cmd_t *scmd;
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_pkt_txlate_t *spx;
c03acfcad7780db4ddf763511a82026680b3b2c1ls int rval;
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls#if ! defined(lint)
c03acfcad7780db4ddf763511a82026680b3b2c1ls ASSERT(sizeof (struct smart_data) == 512);
c03acfcad7780db4ddf763511a82026680b3b2c1ls#endif
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls spx = kmem_zalloc(sizeof (sata_pkt_txlate_t), KM_SLEEP);
c03acfcad7780db4ddf763511a82026680b3b2c1ls spx->txlt_sata_hba_inst = sata_hba_inst;
c03acfcad7780db4ddf763511a82026680b3b2c1ls spx->txlt_scsi_pkt = NULL; /* No scsi pkt involved */
c03acfcad7780db4ddf763511a82026680b3b2c1ls spkt = sata_pkt_alloc(spx, SLEEP_FUNC);
c03acfcad7780db4ddf763511a82026680b3b2c1ls if (spkt == NULL) {
c03acfcad7780db4ddf763511a82026680b3b2c1ls kmem_free(spx, sizeof (sata_pkt_txlate_t));
c03acfcad7780db4ddf763511a82026680b3b2c1ls return (-1);
c03acfcad7780db4ddf763511a82026680b3b2c1ls }
c03acfcad7780db4ddf763511a82026680b3b2c1ls /* address is needed now */
c03acfcad7780db4ddf763511a82026680b3b2c1ls spkt->satapkt_device.satadev_addr = sdinfo->satadrv_addr;
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls /* Fill sata_pkt */
c03acfcad7780db4ddf763511a82026680b3b2c1ls spkt->satapkt_device.satadev_addr = sdinfo->satadrv_addr;
c03acfcad7780db4ddf763511a82026680b3b2c1ls spkt->satapkt_op_mode = SATA_OPMODE_SYNCH | SATA_OPMODE_INTERRUPTS;
c03acfcad7780db4ddf763511a82026680b3b2c1ls /* Synchronous mode, no callback */
c03acfcad7780db4ddf763511a82026680b3b2c1ls spkt->satapkt_comp = NULL;
c03acfcad7780db4ddf763511a82026680b3b2c1ls /* Timeout 30s */
c03acfcad7780db4ddf763511a82026680b3b2c1ls spkt->satapkt_time = sata_default_pkt_time;
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd = &spkt->satapkt_cmd;
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_flags.sata_data_direction = SATA_DIR_READ;
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls /*
c03acfcad7780db4ddf763511a82026680b3b2c1ls * Allocate buffer for SMART data
c03acfcad7780db4ddf763511a82026680b3b2c1ls */
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_bp = sata_alloc_local_buffer(spx,
c03acfcad7780db4ddf763511a82026680b3b2c1ls sizeof (struct smart_data));
c03acfcad7780db4ddf763511a82026680b3b2c1ls if (scmd->satacmd_bp == NULL) {
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_pkt_free(spx);
c03acfcad7780db4ddf763511a82026680b3b2c1ls kmem_free(spx, sizeof (sata_pkt_txlate_t));
c03acfcad7780db4ddf763511a82026680b3b2c1ls SATA_LOG_D((sata_hba_inst, CE_WARN,
c03acfcad7780db4ddf763511a82026680b3b2c1ls "sata_fetch_smart_data: "
c03acfcad7780db4ddf763511a82026680b3b2c1ls "cannot allocate buffer"));
c03acfcad7780db4ddf763511a82026680b3b2c1ls return (-1);
c03acfcad7780db4ddf763511a82026680b3b2c1ls }
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls /* Build SMART_READ_DATA cmd in the sata_pkt */
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_addr_type = 0; /* N/A */
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_sec_count_lsb = 0; /* N/A */
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_lba_low_lsb = 0; /* N/A */
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_lba_mid_lsb = SMART_MAGIC_VAL_1;
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_lba_high_lsb = SMART_MAGIC_VAL_2;
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_features_reg = SATA_SMART_READ_DATA;
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_device_reg = 0; /* Always device 0 */
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_cmd_reg = SATAC_SMART;
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls /* Send pkt to SATA HBA driver */
c03acfcad7780db4ddf763511a82026680b3b2c1ls if ((*SATA_START_FUNC(sata_hba_inst))(SATA_DIP(sata_hba_inst), spkt) !=
c03acfcad7780db4ddf763511a82026680b3b2c1ls SATA_TRAN_ACCEPTED ||
c03acfcad7780db4ddf763511a82026680b3b2c1ls spkt->satapkt_reason != SATA_PKT_COMPLETED) {
c03acfcad7780db4ddf763511a82026680b3b2c1ls /*
c03acfcad7780db4ddf763511a82026680b3b2c1ls * Whoops, no SMART DATA available
c03acfcad7780db4ddf763511a82026680b3b2c1ls */
c03acfcad7780db4ddf763511a82026680b3b2c1ls rval = -1;
c03acfcad7780db4ddf763511a82026680b3b2c1ls goto fail;
c03acfcad7780db4ddf763511a82026680b3b2c1ls } else {
c03acfcad7780db4ddf763511a82026680b3b2c1ls rval = ddi_dma_sync(spx->txlt_buf_dma_handle, 0, 0,
c03acfcad7780db4ddf763511a82026680b3b2c1ls DDI_DMA_SYNC_FORKERNEL);
c03acfcad7780db4ddf763511a82026680b3b2c1ls if (rval != DDI_SUCCESS) {
c03acfcad7780db4ddf763511a82026680b3b2c1ls SATA_LOG_D((spx->txlt_sata_hba_inst, CE_WARN,
c03acfcad7780db4ddf763511a82026680b3b2c1ls "sata_fetch_smart_data: "
c03acfcad7780db4ddf763511a82026680b3b2c1ls "sync pkt failed"));
c03acfcad7780db4ddf763511a82026680b3b2c1ls rval = -1;
c03acfcad7780db4ddf763511a82026680b3b2c1ls goto fail;
c03acfcad7780db4ddf763511a82026680b3b2c1ls }
c03acfcad7780db4ddf763511a82026680b3b2c1ls bcopy(scmd->satacmd_bp->b_un.b_addr, (uint8_t *)smart_data,
c03acfcad7780db4ddf763511a82026680b3b2c1ls sizeof (struct smart_data));
c03acfcad7780db4ddf763511a82026680b3b2c1ls }
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1lsfail:
c03acfcad7780db4ddf763511a82026680b3b2c1ls /* Free allocated resources */
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_free_local_buffer(spx);
c03acfcad7780db4ddf763511a82026680b3b2c1ls spx->txlt_sata_pkt->satapkt_cmd.satacmd_bp = NULL;
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_pkt_free(spx);
c03acfcad7780db4ddf763511a82026680b3b2c1ls kmem_free(spx, sizeof (sata_pkt_txlate_t));
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls return (rval);
c03acfcad7780db4ddf763511a82026680b3b2c1ls}
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls/*
c03acfcad7780db4ddf763511a82026680b3b2c1ls * Used by LOG SENSE page 0x10
c03acfcad7780db4ddf763511a82026680b3b2c1ls *
c03acfcad7780db4ddf763511a82026680b3b2c1ls * return 0 for success, -1 otherwise
c03acfcad7780db4ddf763511a82026680b3b2c1ls *
c03acfcad7780db4ddf763511a82026680b3b2c1ls */
c03acfcad7780db4ddf763511a82026680b3b2c1lsstatic int
c03acfcad7780db4ddf763511a82026680b3b2c1lssata_ext_smart_selftest_read_log(
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_hba_inst_t *sata_hba_inst,
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_drive_info_t *sdinfo,
c03acfcad7780db4ddf763511a82026680b3b2c1ls struct smart_ext_selftest_log *ext_selftest_log,
c03acfcad7780db4ddf763511a82026680b3b2c1ls uint16_t block_num)
c03acfcad7780db4ddf763511a82026680b3b2c1ls{
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_pkt_txlate_t *spx;
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_pkt_t *spkt;
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_cmd_t *scmd;
c03acfcad7780db4ddf763511a82026680b3b2c1ls int rval;
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls#if ! defined(lint)
c03acfcad7780db4ddf763511a82026680b3b2c1ls ASSERT(sizeof (struct smart_ext_selftest_log) == 512);
c03acfcad7780db4ddf763511a82026680b3b2c1ls#endif
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls spx = kmem_zalloc(sizeof (sata_pkt_txlate_t), KM_SLEEP);
c03acfcad7780db4ddf763511a82026680b3b2c1ls spx->txlt_sata_hba_inst = sata_hba_inst;
c03acfcad7780db4ddf763511a82026680b3b2c1ls spx->txlt_scsi_pkt = NULL; /* No scsi pkt involved */
c03acfcad7780db4ddf763511a82026680b3b2c1ls spkt = sata_pkt_alloc(spx, SLEEP_FUNC);
c03acfcad7780db4ddf763511a82026680b3b2c1ls if (spkt == NULL) {
c03acfcad7780db4ddf763511a82026680b3b2c1ls kmem_free(spx, sizeof (sata_pkt_txlate_t));
c03acfcad7780db4ddf763511a82026680b3b2c1ls return (-1);
c03acfcad7780db4ddf763511a82026680b3b2c1ls }
c03acfcad7780db4ddf763511a82026680b3b2c1ls /* address is needed now */
c03acfcad7780db4ddf763511a82026680b3b2c1ls spkt->satapkt_device.satadev_addr = sdinfo->satadrv_addr;
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls /* Fill sata_pkt */
c03acfcad7780db4ddf763511a82026680b3b2c1ls spkt->satapkt_device.satadev_addr = sdinfo->satadrv_addr;
c03acfcad7780db4ddf763511a82026680b3b2c1ls spkt->satapkt_op_mode = SATA_OPMODE_SYNCH | SATA_OPMODE_INTERRUPTS;
c03acfcad7780db4ddf763511a82026680b3b2c1ls /* Synchronous mode, no callback */
c03acfcad7780db4ddf763511a82026680b3b2c1ls spkt->satapkt_comp = NULL;
c03acfcad7780db4ddf763511a82026680b3b2c1ls /* Timeout 30s */
c03acfcad7780db4ddf763511a82026680b3b2c1ls spkt->satapkt_time = sata_default_pkt_time;
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd = &spkt->satapkt_cmd;
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_flags.sata_data_direction = SATA_DIR_READ;
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls /*
c03acfcad7780db4ddf763511a82026680b3b2c1ls * Allocate buffer for SMART extended self-test log
c03acfcad7780db4ddf763511a82026680b3b2c1ls */
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_bp = sata_alloc_local_buffer(spx,
c03acfcad7780db4ddf763511a82026680b3b2c1ls sizeof (struct smart_ext_selftest_log));
c03acfcad7780db4ddf763511a82026680b3b2c1ls if (scmd->satacmd_bp == NULL) {
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_pkt_free(spx);
c03acfcad7780db4ddf763511a82026680b3b2c1ls kmem_free(spx, sizeof (sata_pkt_txlate_t));
c03acfcad7780db4ddf763511a82026680b3b2c1ls SATA_LOG_D((sata_hba_inst, CE_WARN,
c03acfcad7780db4ddf763511a82026680b3b2c1ls "sata_ext_smart_selftest_log: "
c03acfcad7780db4ddf763511a82026680b3b2c1ls "cannot allocate buffer"));
c03acfcad7780db4ddf763511a82026680b3b2c1ls return (-1);
c03acfcad7780db4ddf763511a82026680b3b2c1ls }
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls /* Build READ LOG EXT w/ extended self-test log cmd in the sata_pkt */
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_addr_type = ATA_ADDR_LBA48;
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_sec_count_lsb = 1; /* One sector of selftest log */
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_sec_count_msb = 0; /* One sector of selftest log */
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_lba_low_lsb = EXT_SMART_SELFTEST_LOG_PAGE;
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_lba_low_msb = 0;
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_lba_mid_lsb = block_num & 0xff;
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_lba_mid_msb = block_num >> 8;
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_device_reg = 0; /* Always device 0 */
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_cmd_reg = SATAC_READ_LOG_EXT;
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls /* Send pkt to SATA HBA driver */
c03acfcad7780db4ddf763511a82026680b3b2c1ls if ((*SATA_START_FUNC(sata_hba_inst))(SATA_DIP(sata_hba_inst), spkt) !=
c03acfcad7780db4ddf763511a82026680b3b2c1ls SATA_TRAN_ACCEPTED ||
c03acfcad7780db4ddf763511a82026680b3b2c1ls spkt->satapkt_reason != SATA_PKT_COMPLETED) {
c03acfcad7780db4ddf763511a82026680b3b2c1ls /*
c03acfcad7780db4ddf763511a82026680b3b2c1ls * Whoops, no SMART selftest log info available
c03acfcad7780db4ddf763511a82026680b3b2c1ls */
c03acfcad7780db4ddf763511a82026680b3b2c1ls rval = -1;
c03acfcad7780db4ddf763511a82026680b3b2c1ls goto fail;
c03acfcad7780db4ddf763511a82026680b3b2c1ls } else {
c03acfcad7780db4ddf763511a82026680b3b2c1ls rval = ddi_dma_sync(spx->txlt_buf_dma_handle, 0, 0,
c03acfcad7780db4ddf763511a82026680b3b2c1ls DDI_DMA_SYNC_FORKERNEL);
c03acfcad7780db4ddf763511a82026680b3b2c1ls if (rval != DDI_SUCCESS) {
c03acfcad7780db4ddf763511a82026680b3b2c1ls SATA_LOG_D((spx->txlt_sata_hba_inst, CE_WARN,
c03acfcad7780db4ddf763511a82026680b3b2c1ls "sata_ext_smart_selftest_log: "
c03acfcad7780db4ddf763511a82026680b3b2c1ls "sync pkt failed"));
c03acfcad7780db4ddf763511a82026680b3b2c1ls rval = -1;
c03acfcad7780db4ddf763511a82026680b3b2c1ls goto fail;
c03acfcad7780db4ddf763511a82026680b3b2c1ls }
c03acfcad7780db4ddf763511a82026680b3b2c1ls bcopy(scmd->satacmd_bp->b_un.b_addr,
c03acfcad7780db4ddf763511a82026680b3b2c1ls (uint8_t *)ext_selftest_log,
c03acfcad7780db4ddf763511a82026680b3b2c1ls sizeof (struct smart_ext_selftest_log));
c03acfcad7780db4ddf763511a82026680b3b2c1ls rval = 0;
c03acfcad7780db4ddf763511a82026680b3b2c1ls }
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1lsfail:
c03acfcad7780db4ddf763511a82026680b3b2c1ls /* Free allocated resources */
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_free_local_buffer(spx);
c03acfcad7780db4ddf763511a82026680b3b2c1ls spx->txlt_sata_pkt->satapkt_cmd.satacmd_bp = NULL;
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_pkt_free(spx);
c03acfcad7780db4ddf763511a82026680b3b2c1ls kmem_free(spx, sizeof (sata_pkt_txlate_t));
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls return (rval);
c03acfcad7780db4ddf763511a82026680b3b2c1ls}
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls/*
c03acfcad7780db4ddf763511a82026680b3b2c1ls * Returns 0 for success, -1 otherwise
c03acfcad7780db4ddf763511a82026680b3b2c1ls *
c03acfcad7780db4ddf763511a82026680b3b2c1ls * SMART self-test log data is returned in buffer pointed to by selftest_log
c03acfcad7780db4ddf763511a82026680b3b2c1ls */
c03acfcad7780db4ddf763511a82026680b3b2c1lsstatic int
c03acfcad7780db4ddf763511a82026680b3b2c1lssata_smart_selftest_log(
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_hba_inst_t *sata_hba_inst,
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_drive_info_t *sdinfo,
c03acfcad7780db4ddf763511a82026680b3b2c1ls struct smart_selftest_log *selftest_log)
c03acfcad7780db4ddf763511a82026680b3b2c1ls{
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_pkt_t *spkt;
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_cmd_t *scmd;
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_pkt_txlate_t *spx;
c03acfcad7780db4ddf763511a82026680b3b2c1ls int rval;
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls#if ! defined(lint)
c03acfcad7780db4ddf763511a82026680b3b2c1ls ASSERT(sizeof (struct smart_selftest_log) == 512);
c03acfcad7780db4ddf763511a82026680b3b2c1ls#endif
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls spx = kmem_zalloc(sizeof (sata_pkt_txlate_t), KM_SLEEP);
c03acfcad7780db4ddf763511a82026680b3b2c1ls spx->txlt_sata_hba_inst = sata_hba_inst;
c03acfcad7780db4ddf763511a82026680b3b2c1ls spx->txlt_scsi_pkt = NULL; /* No scsi pkt involved */
c03acfcad7780db4ddf763511a82026680b3b2c1ls spkt = sata_pkt_alloc(spx, SLEEP_FUNC);
c03acfcad7780db4ddf763511a82026680b3b2c1ls if (spkt == NULL) {
c03acfcad7780db4ddf763511a82026680b3b2c1ls kmem_free(spx, sizeof (sata_pkt_txlate_t));
c03acfcad7780db4ddf763511a82026680b3b2c1ls return (-1);
c03acfcad7780db4ddf763511a82026680b3b2c1ls }
c03acfcad7780db4ddf763511a82026680b3b2c1ls /* address is needed now */
c03acfcad7780db4ddf763511a82026680b3b2c1ls spkt->satapkt_device.satadev_addr = sdinfo->satadrv_addr;
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls /* Fill sata_pkt */
c03acfcad7780db4ddf763511a82026680b3b2c1ls spkt->satapkt_device.satadev_addr = sdinfo->satadrv_addr;
c03acfcad7780db4ddf763511a82026680b3b2c1ls spkt->satapkt_op_mode = SATA_OPMODE_SYNCH | SATA_OPMODE_INTERRUPTS;
c03acfcad7780db4ddf763511a82026680b3b2c1ls /* Synchronous mode, no callback */
c03acfcad7780db4ddf763511a82026680b3b2c1ls spkt->satapkt_comp = NULL;
c03acfcad7780db4ddf763511a82026680b3b2c1ls /* Timeout 30s */
c03acfcad7780db4ddf763511a82026680b3b2c1ls spkt->satapkt_time = sata_default_pkt_time;
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd = &spkt->satapkt_cmd;
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_flags.sata_data_direction = SATA_DIR_READ;
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls /*
c03acfcad7780db4ddf763511a82026680b3b2c1ls * Allocate buffer for Identify Data return data
c03acfcad7780db4ddf763511a82026680b3b2c1ls */
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_bp = sata_alloc_local_buffer(spx,
c03acfcad7780db4ddf763511a82026680b3b2c1ls sizeof (struct smart_selftest_log));
c03acfcad7780db4ddf763511a82026680b3b2c1ls if (scmd->satacmd_bp == NULL) {
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_pkt_free(spx);
c03acfcad7780db4ddf763511a82026680b3b2c1ls kmem_free(spx, sizeof (sata_pkt_txlate_t));
c03acfcad7780db4ddf763511a82026680b3b2c1ls SATA_LOG_D((sata_hba_inst, CE_WARN,
c03acfcad7780db4ddf763511a82026680b3b2c1ls "sata_smart_selftest_log: "
c03acfcad7780db4ddf763511a82026680b3b2c1ls "cannot allocate buffer"));
c03acfcad7780db4ddf763511a82026680b3b2c1ls return (-1);
c03acfcad7780db4ddf763511a82026680b3b2c1ls }
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls /* Build SMART_READ_DATA cmd in the sata_pkt */
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_addr_type = 0; /* N/A */
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_sec_count_lsb = 1; /* One sector of SMART log */
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_lba_low_lsb = SMART_SELFTEST_LOG_PAGE;
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_lba_mid_lsb = SMART_MAGIC_VAL_1;
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_lba_high_lsb = SMART_MAGIC_VAL_2;
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_features_reg = SATA_SMART_READ_LOG;
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_device_reg = 0; /* Always device 0 */
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_cmd_reg = SATAC_SMART;
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls /* Send pkt to SATA HBA driver */
c03acfcad7780db4ddf763511a82026680b3b2c1ls if ((*SATA_START_FUNC(sata_hba_inst))(SATA_DIP(sata_hba_inst), spkt) !=
c03acfcad7780db4ddf763511a82026680b3b2c1ls SATA_TRAN_ACCEPTED ||
c03acfcad7780db4ddf763511a82026680b3b2c1ls spkt->satapkt_reason != SATA_PKT_COMPLETED) {
c03acfcad7780db4ddf763511a82026680b3b2c1ls /*
c03acfcad7780db4ddf763511a82026680b3b2c1ls * Whoops, no SMART DATA available
c03acfcad7780db4ddf763511a82026680b3b2c1ls */
c03acfcad7780db4ddf763511a82026680b3b2c1ls rval = -1;
c03acfcad7780db4ddf763511a82026680b3b2c1ls goto fail;
c03acfcad7780db4ddf763511a82026680b3b2c1ls } else {
c03acfcad7780db4ddf763511a82026680b3b2c1ls rval = ddi_dma_sync(spx->txlt_buf_dma_handle, 0, 0,
c03acfcad7780db4ddf763511a82026680b3b2c1ls DDI_DMA_SYNC_FORKERNEL);
c03acfcad7780db4ddf763511a82026680b3b2c1ls if (rval != DDI_SUCCESS) {
c03acfcad7780db4ddf763511a82026680b3b2c1ls SATA_LOG_D((spx->txlt_sata_hba_inst, CE_WARN,
c03acfcad7780db4ddf763511a82026680b3b2c1ls "sata_smart_selftest_log: "
c03acfcad7780db4ddf763511a82026680b3b2c1ls "sync pkt failed"));
c03acfcad7780db4ddf763511a82026680b3b2c1ls rval = -1;
c03acfcad7780db4ddf763511a82026680b3b2c1ls goto fail;
c03acfcad7780db4ddf763511a82026680b3b2c1ls }
c03acfcad7780db4ddf763511a82026680b3b2c1ls bcopy(scmd->satacmd_bp->b_un.b_addr, (uint8_t *)selftest_log,
c03acfcad7780db4ddf763511a82026680b3b2c1ls sizeof (struct smart_selftest_log));
c03acfcad7780db4ddf763511a82026680b3b2c1ls rval = 0;
c03acfcad7780db4ddf763511a82026680b3b2c1ls }
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1lsfail:
c03acfcad7780db4ddf763511a82026680b3b2c1ls /* Free allocated resources */
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_free_local_buffer(spx);
c03acfcad7780db4ddf763511a82026680b3b2c1ls spx->txlt_sata_pkt->satapkt_cmd.satacmd_bp = NULL;
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_pkt_free(spx);
c03acfcad7780db4ddf763511a82026680b3b2c1ls kmem_free(spx, sizeof (sata_pkt_txlate_t));
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls return (rval);
c03acfcad7780db4ddf763511a82026680b3b2c1ls}
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls/*
c03acfcad7780db4ddf763511a82026680b3b2c1ls * Returns 0 for success, -1 otherwise
c03acfcad7780db4ddf763511a82026680b3b2c1ls *
c03acfcad7780db4ddf763511a82026680b3b2c1ls * SMART READ LOG data is returned in buffer pointed to by smart_log
c03acfcad7780db4ddf763511a82026680b3b2c1ls */
c03acfcad7780db4ddf763511a82026680b3b2c1lsstatic int
c03acfcad7780db4ddf763511a82026680b3b2c1lssata_smart_read_log(
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_hba_inst_t *sata_hba_inst,
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_drive_info_t *sdinfo,
c03acfcad7780db4ddf763511a82026680b3b2c1ls uint8_t *smart_log, /* where the data should be returned */
c03acfcad7780db4ddf763511a82026680b3b2c1ls uint8_t which_log, /* which log should be returned */
c03acfcad7780db4ddf763511a82026680b3b2c1ls uint8_t log_size) /* # of 512 bytes in log */
c03acfcad7780db4ddf763511a82026680b3b2c1ls{
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_pkt_t *spkt;
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_cmd_t *scmd;
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_pkt_txlate_t *spx;
c03acfcad7780db4ddf763511a82026680b3b2c1ls int rval;
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls spx = kmem_zalloc(sizeof (sata_pkt_txlate_t), KM_SLEEP);
c03acfcad7780db4ddf763511a82026680b3b2c1ls spx->txlt_sata_hba_inst = sata_hba_inst;
c03acfcad7780db4ddf763511a82026680b3b2c1ls spx->txlt_scsi_pkt = NULL; /* No scsi pkt involved */
c03acfcad7780db4ddf763511a82026680b3b2c1ls spkt = sata_pkt_alloc(spx, SLEEP_FUNC);
c03acfcad7780db4ddf763511a82026680b3b2c1ls if (spkt == NULL) {
c03acfcad7780db4ddf763511a82026680b3b2c1ls kmem_free(spx, sizeof (sata_pkt_txlate_t));
c03acfcad7780db4ddf763511a82026680b3b2c1ls return (-1);
c03acfcad7780db4ddf763511a82026680b3b2c1ls }
c03acfcad7780db4ddf763511a82026680b3b2c1ls /* address is needed now */
c03acfcad7780db4ddf763511a82026680b3b2c1ls spkt->satapkt_device.satadev_addr = sdinfo->satadrv_addr;
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls /* Fill sata_pkt */
c03acfcad7780db4ddf763511a82026680b3b2c1ls spkt->satapkt_device.satadev_addr = sdinfo->satadrv_addr;
c03acfcad7780db4ddf763511a82026680b3b2c1ls spkt->satapkt_op_mode = SATA_OPMODE_SYNCH | SATA_OPMODE_INTERRUPTS;
c03acfcad7780db4ddf763511a82026680b3b2c1ls /* Synchronous mode, no callback */
c03acfcad7780db4ddf763511a82026680b3b2c1ls spkt->satapkt_comp = NULL;
c03acfcad7780db4ddf763511a82026680b3b2c1ls /* Timeout 30s */
c03acfcad7780db4ddf763511a82026680b3b2c1ls spkt->satapkt_time = sata_default_pkt_time;
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd = &spkt->satapkt_cmd;
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_flags.sata_data_direction = SATA_DIR_READ;
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls /*
c03acfcad7780db4ddf763511a82026680b3b2c1ls * Allocate buffer for SMART READ LOG
c03acfcad7780db4ddf763511a82026680b3b2c1ls */
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_bp = sata_alloc_local_buffer(spx, log_size * 512);
c03acfcad7780db4ddf763511a82026680b3b2c1ls if (scmd->satacmd_bp == NULL) {
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_pkt_free(spx);
c03acfcad7780db4ddf763511a82026680b3b2c1ls kmem_free(spx, sizeof (sata_pkt_txlate_t));
c03acfcad7780db4ddf763511a82026680b3b2c1ls SATA_LOG_D((sata_hba_inst, CE_WARN,
c03acfcad7780db4ddf763511a82026680b3b2c1ls "sata_smart_read_log: " "cannot allocate buffer"));
c03acfcad7780db4ddf763511a82026680b3b2c1ls return (-1);
c03acfcad7780db4ddf763511a82026680b3b2c1ls }
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls /* Build SMART_READ_DATA cmd in the sata_pkt */
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_addr_type = 0; /* N/A */
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_sec_count_lsb = log_size; /* what the caller asked for */
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_lba_low_lsb = which_log; /* which log page */
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_lba_mid_lsb = SMART_MAGIC_VAL_1;
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_lba_high_lsb = SMART_MAGIC_VAL_2;
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_features_reg = SATA_SMART_READ_LOG;
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_device_reg = 0; /* Always device 0 */
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_cmd_reg = SATAC_SMART;
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls /* Send pkt to SATA HBA driver */
c03acfcad7780db4ddf763511a82026680b3b2c1ls if ((*SATA_START_FUNC(sata_hba_inst))(SATA_DIP(sata_hba_inst), spkt) !=
c03acfcad7780db4ddf763511a82026680b3b2c1ls SATA_TRAN_ACCEPTED ||
c03acfcad7780db4ddf763511a82026680b3b2c1ls spkt->satapkt_reason != SATA_PKT_COMPLETED) {
c03acfcad7780db4ddf763511a82026680b3b2c1ls /*
c03acfcad7780db4ddf763511a82026680b3b2c1ls * Whoops, no SMART DATA available
c03acfcad7780db4ddf763511a82026680b3b2c1ls */
c03acfcad7780db4ddf763511a82026680b3b2c1ls rval = -1;
c03acfcad7780db4ddf763511a82026680b3b2c1ls goto fail;
c03acfcad7780db4ddf763511a82026680b3b2c1ls } else {
c03acfcad7780db4ddf763511a82026680b3b2c1ls rval = ddi_dma_sync(spx->txlt_buf_dma_handle, 0, 0,
c03acfcad7780db4ddf763511a82026680b3b2c1ls DDI_DMA_SYNC_FORKERNEL);
c03acfcad7780db4ddf763511a82026680b3b2c1ls if (rval != DDI_SUCCESS) {
c03acfcad7780db4ddf763511a82026680b3b2c1ls SATA_LOG_D((spx->txlt_sata_hba_inst, CE_WARN,
c03acfcad7780db4ddf763511a82026680b3b2c1ls "sata_smart_read_log: " "sync pkt failed"));
c03acfcad7780db4ddf763511a82026680b3b2c1ls rval = -1;
c03acfcad7780db4ddf763511a82026680b3b2c1ls goto fail;
c03acfcad7780db4ddf763511a82026680b3b2c1ls }
c03acfcad7780db4ddf763511a82026680b3b2c1ls bcopy(scmd->satacmd_bp->b_un.b_addr, smart_log, log_size * 512);
c03acfcad7780db4ddf763511a82026680b3b2c1ls rval = 0;
c03acfcad7780db4ddf763511a82026680b3b2c1ls }
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1lsfail:
c03acfcad7780db4ddf763511a82026680b3b2c1ls /* Free allocated resources */
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_free_local_buffer(spx);
c03acfcad7780db4ddf763511a82026680b3b2c1ls spx->txlt_sata_pkt->satapkt_cmd.satacmd_bp = NULL;
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_pkt_free(spx);
c03acfcad7780db4ddf763511a82026680b3b2c1ls kmem_free(spx, sizeof (sata_pkt_txlate_t));
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls return (rval);
c03acfcad7780db4ddf763511a82026680b3b2c1ls}
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls/*
c03acfcad7780db4ddf763511a82026680b3b2c1ls * Used by LOG SENSE page 0x10
c03acfcad7780db4ddf763511a82026680b3b2c1ls *
c03acfcad7780db4ddf763511a82026680b3b2c1ls * return 0 for success, -1 otherwise
c03acfcad7780db4ddf763511a82026680b3b2c1ls *
c03acfcad7780db4ddf763511a82026680b3b2c1ls */
c03acfcad7780db4ddf763511a82026680b3b2c1lsstatic int
c03acfcad7780db4ddf763511a82026680b3b2c1lssata_read_log_ext_directory(
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_hba_inst_t *sata_hba_inst,
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_drive_info_t *sdinfo,
c03acfcad7780db4ddf763511a82026680b3b2c1ls struct read_log_ext_directory *logdir)
c03acfcad7780db4ddf763511a82026680b3b2c1ls{
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_pkt_txlate_t *spx;
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_pkt_t *spkt;
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_cmd_t *scmd;
c03acfcad7780db4ddf763511a82026680b3b2c1ls int rval;
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls#if ! defined(lint)
c03acfcad7780db4ddf763511a82026680b3b2c1ls ASSERT(sizeof (struct read_log_ext_directory) == 512);
c03acfcad7780db4ddf763511a82026680b3b2c1ls#endif
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls spx = kmem_zalloc(sizeof (sata_pkt_txlate_t), KM_SLEEP);
c03acfcad7780db4ddf763511a82026680b3b2c1ls spx->txlt_sata_hba_inst = sata_hba_inst;
c03acfcad7780db4ddf763511a82026680b3b2c1ls spx->txlt_scsi_pkt = NULL; /* No scsi pkt involved */
c03acfcad7780db4ddf763511a82026680b3b2c1ls spkt = sata_pkt_alloc(spx, SLEEP_FUNC);
c03acfcad7780db4ddf763511a82026680b3b2c1ls if (spkt == NULL) {
c03acfcad7780db4ddf763511a82026680b3b2c1ls kmem_free(spx, sizeof (sata_pkt_txlate_t));
c03acfcad7780db4ddf763511a82026680b3b2c1ls return (-1);
c03acfcad7780db4ddf763511a82026680b3b2c1ls }
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls /* Fill sata_pkt */
c03acfcad7780db4ddf763511a82026680b3b2c1ls spkt->satapkt_device.satadev_addr = sdinfo->satadrv_addr;
c03acfcad7780db4ddf763511a82026680b3b2c1ls spkt->satapkt_op_mode = SATA_OPMODE_SYNCH | SATA_OPMODE_INTERRUPTS;
c03acfcad7780db4ddf763511a82026680b3b2c1ls /* Synchronous mode, no callback */
c03acfcad7780db4ddf763511a82026680b3b2c1ls spkt->satapkt_comp = NULL;
c03acfcad7780db4ddf763511a82026680b3b2c1ls /* Timeout 30s */
c03acfcad7780db4ddf763511a82026680b3b2c1ls spkt->satapkt_time = sata_default_pkt_time;
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd = &spkt->satapkt_cmd;
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_flags.sata_data_direction = SATA_DIR_READ;
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls /*
c03acfcad7780db4ddf763511a82026680b3b2c1ls * Allocate buffer for SMART extended self-test log
c03acfcad7780db4ddf763511a82026680b3b2c1ls */
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_bp = sata_alloc_local_buffer(spx,
c03acfcad7780db4ddf763511a82026680b3b2c1ls sizeof (struct read_log_ext_directory));
c03acfcad7780db4ddf763511a82026680b3b2c1ls if (scmd->satacmd_bp == NULL) {
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_pkt_free(spx);
c03acfcad7780db4ddf763511a82026680b3b2c1ls kmem_free(spx, sizeof (sata_pkt_txlate_t));
c03acfcad7780db4ddf763511a82026680b3b2c1ls SATA_LOG_D((sata_hba_inst, CE_WARN,
c03acfcad7780db4ddf763511a82026680b3b2c1ls "sata_read_log_ext_directory: "
c03acfcad7780db4ddf763511a82026680b3b2c1ls "cannot allocate buffer"));
c03acfcad7780db4ddf763511a82026680b3b2c1ls return (-1);
c03acfcad7780db4ddf763511a82026680b3b2c1ls }
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls /* Build READ LOG EXT w/ extended self-test log cmd in the sata_pkt */
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_addr_type = ATA_ADDR_LBA48;
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_sec_count_lsb = 1; /* One sector of directory */
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_sec_count_msb = 0; /* One sector of directory */
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_lba_low_lsb = READ_LOG_EXT_LOG_DIRECTORY;
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_lba_low_msb = 0;
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_lba_mid_lsb = 0;
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_lba_mid_msb = 0;
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_device_reg = 0; /* Always device 0 */
c03acfcad7780db4ddf763511a82026680b3b2c1ls scmd->satacmd_cmd_reg = SATAC_READ_LOG_EXT;
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls /* Send pkt to SATA HBA driver */
c03acfcad7780db4ddf763511a82026680b3b2c1ls if ((*SATA_START_FUNC(sata_hba_inst))(SATA_DIP(sata_hba_inst), spkt) !=
c03acfcad7780db4ddf763511a82026680b3b2c1ls SATA_TRAN_ACCEPTED ||
c03acfcad7780db4ddf763511a82026680b3b2c1ls spkt->satapkt_reason != SATA_PKT_COMPLETED) {
c03acfcad7780db4ddf763511a82026680b3b2c1ls /*
c03acfcad7780db4ddf763511a82026680b3b2c1ls * Whoops, no SMART selftest log info available
c03acfcad7780db4ddf763511a82026680b3b2c1ls */
c03acfcad7780db4ddf763511a82026680b3b2c1ls rval = -1;
c03acfcad7780db4ddf763511a82026680b3b2c1ls goto fail;
c03acfcad7780db4ddf763511a82026680b3b2c1ls } else {
c03acfcad7780db4ddf763511a82026680b3b2c1ls rval = ddi_dma_sync(spx->txlt_buf_dma_handle, 0, 0,
c03acfcad7780db4ddf763511a82026680b3b2c1ls DDI_DMA_SYNC_FORKERNEL);
c03acfcad7780db4ddf763511a82026680b3b2c1ls if (rval != DDI_SUCCESS) {
c03acfcad7780db4ddf763511a82026680b3b2c1ls SATA_LOG_D((spx->txlt_sata_hba_inst, CE_WARN,
c03acfcad7780db4ddf763511a82026680b3b2c1ls "sata_read_log_ext_directory: "
c03acfcad7780db4ddf763511a82026680b3b2c1ls "sync pkt failed"));
c03acfcad7780db4ddf763511a82026680b3b2c1ls rval = -1;
c03acfcad7780db4ddf763511a82026680b3b2c1ls goto fail;
c03acfcad7780db4ddf763511a82026680b3b2c1ls }
c03acfcad7780db4ddf763511a82026680b3b2c1ls bcopy(scmd->satacmd_bp->b_un.b_addr, (uint8_t *)logdir,
c03acfcad7780db4ddf763511a82026680b3b2c1ls sizeof (struct read_log_ext_directory));
c03acfcad7780db4ddf763511a82026680b3b2c1ls rval = 0;
c03acfcad7780db4ddf763511a82026680b3b2c1ls }
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1lsfail:
c03acfcad7780db4ddf763511a82026680b3b2c1ls /* Free allocated resources */
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_free_local_buffer(spx);
c03acfcad7780db4ddf763511a82026680b3b2c1ls spx->txlt_sata_pkt->satapkt_cmd.satacmd_bp = NULL;
c03acfcad7780db4ddf763511a82026680b3b2c1ls sata_pkt_free(spx);
c03acfcad7780db4ddf763511a82026680b3b2c1ls kmem_free(spx, sizeof (sata_pkt_txlate_t));
c03acfcad7780db4ddf763511a82026680b3b2c1ls
c03acfcad7780db4ddf763511a82026680b3b2c1ls return (rval);
c03acfcad7780db4ddf763511a82026680b3b2c1ls}
c03acfcad7780db4ddf763511a82026680b3b2c1ls
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
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls/*
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls * sata_xlate_errors() is used to translate (S)ATA error
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls * information to SCSI information returned in the SCSI
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls * packet.
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls */
2c9565cfcd87a2045c2e4b76f31ac4e978903589lsstatic void
2c9565cfcd87a2045c2e4b76f31ac4e978903589lssata_xlate_errors(sata_pkt_txlate_t *spx)
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls{
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls struct scsi_pkt *scsipkt = spx->txlt_scsi_pkt;
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls struct scsi_extended_sense *sense;
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls scsipkt->pkt_reason = CMD_INCOMPLETE;
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls *scsipkt->pkt_scbp = STATUS_CHECK;
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls sense = sata_arq_sense(spx);
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls switch (spx->txlt_sata_pkt->satapkt_reason) {
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls case SATA_PKT_PORT_ERROR:
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls /*
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls * We have no device data. Assume no data transfered.
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls */
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls sense->es_key = KEY_HARDWARE_ERROR;
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls break;
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls case SATA_PKT_DEV_ERROR:
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls if (spx->txlt_sata_pkt->satapkt_cmd.satacmd_status_reg &
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls SATA_STATUS_ERR) {
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls /*
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls * determine dev error reason from error
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls * reg content
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls */
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls sata_decode_device_error(spx, sense);
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls break;
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls }
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls /* No extended sense key - no info available */
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls break;
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls case SATA_PKT_TIMEOUT:
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls /*
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls * scsipkt->pkt_reason = CMD_TIMEOUT; This causes problems.
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls */
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls scsipkt->pkt_reason = CMD_INCOMPLETE;
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls /* No extended sense key */
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls break;
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls case SATA_PKT_ABORTED:
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls scsipkt->pkt_reason = CMD_ABORTED;
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls /* No extended sense key */
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls break;
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls case SATA_PKT_RESET:
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls /*
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls * pkt aborted either by an explicit reset request from
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls * a host, or due to error recovery
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls */
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls scsipkt->pkt_reason = CMD_RESET;
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls break;
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls default:
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls scsipkt->pkt_reason = CMD_TRAN_ERR;
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls break;
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls }
2c9565cfcd87a2045c2e4b76f31ac4e978903589ls}