sata.c revision 415e5120fdbacf132d1845300d92a6cd74eed2fa
fa9e4066f08beec538e775443c5be79dd423fcabahrens * CDDL HEADER START
fa9e4066f08beec538e775443c5be79dd423fcabahrens * The contents of this file are subject to the terms of the
f65e61c04bc28ffd6bda04619c84330b420450b5ahrens * Common Development and Distribution License (the "License").
f65e61c04bc28ffd6bda04619c84330b420450b5ahrens * You may not use this file except in compliance with the License.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
fa9e4066f08beec538e775443c5be79dd423fcabahrens * See the License for the specific language governing permissions
fa9e4066f08beec538e775443c5be79dd423fcabahrens * and limitations under the License.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * When distributing Covered Code, include this CDDL HEADER in each
fa9e4066f08beec538e775443c5be79dd423fcabahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * If applicable, add the following below this CDDL HEADER, with the
fa9e4066f08beec538e775443c5be79dd423fcabahrens * fields enclosed by brackets "[]" replaced with your own identifying
fa9e4066f08beec538e775443c5be79dd423fcabahrens * information: Portions Copyright [yyyy] [name of copyright owner]
fa9e4066f08beec538e775443c5be79dd423fcabahrens * CDDL HEADER END
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Use is subject to license terms.
fa9e4066f08beec538e775443c5be79dd423fcabahrens#pragma ident "%Z%%M% %I% %E% SMI"
fa9e4066f08beec538e775443c5be79dd423fcabahrens * SATA Framework
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Generic SATA Host Adapter Implementation
fa9e4066f08beec538e775443c5be79dd423fcabahrens * NOTE: THIS VERSION DOES NOT SUPPORT ATAPI DEVICES,
fa9e4066f08beec538e775443c5be79dd423fcabahrens * although there is some code related to these devices.
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* Debug flags - defined in sata.h */
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Flags enabling selected SATA HBA framework functionality
f65e61c04bc28ffd6bda04619c84330b420450b5ahrens SATA_ENABLE_PROCESS_EVENTS | SATA_ENABLE_QUEUING | SATA_ENABLE_NCQ;
fa9e4066f08beec538e775443c5be79dd423fcabahrens * SATA cb_ops functions
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int sata_hba_open(dev_t *, int, int, cred_t *);
455d5089097abbf7ee4538a03c4df823497b6e68ahrensstatic int sata_hba_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
f65e61c04bc28ffd6bda04619c84330b420450b5ahrens * SCSA required entry points
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int sata_scsi_tgt_init(dev_info_t *, dev_info_t *,
fa9e4066f08beec538e775443c5be79dd423fcabahrens int (*callback)(void));
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void sata_scsi_tgt_free(dev_info_t *, dev_info_t *,
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int sata_scsi_start(struct scsi_address *, struct scsi_pkt *);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int sata_scsi_abort(struct scsi_address *, struct scsi_pkt *);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int sata_scsi_reset(struct scsi_address *, int);
f65e61c04bc28ffd6bda04619c84330b420450b5ahrensstatic int sata_scsi_getcap(struct scsi_address *, char *, int);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int sata_scsi_setcap(struct scsi_address *, char *, int, int);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic struct scsi_pkt *sata_scsi_init_pkt(struct scsi_address *,
fa9e4066f08beec538e775443c5be79dd423fcabahrens struct scsi_pkt *, struct buf *, int, int, int, int, int (*)(caddr_t),
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void sata_scsi_destroy_pkt(struct scsi_address *, struct scsi_pkt *);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic void sata_scsi_dmafree(struct scsi_address *, struct scsi_pkt *);
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwickstatic void sata_scsi_sync_pkt(struct scsi_address *, struct scsi_pkt *);
f65e61c04bc28ffd6bda04619c84330b420450b5ahrens * Local functions
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int sata_validate_sata_hba_tran(dev_info_t *, sata_hba_tran_t *);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrockstatic int sata_reprobe_port(sata_hba_inst_t *, sata_device_t *, int);
47cb52daa729f19e298c85a84e8df069365c5232Jeff Bonwickstatic int sata_add_device(dev_info_t *, sata_hba_inst_t *, int cport,
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic dev_info_t *sata_create_target_node(dev_info_t *, sata_hba_inst_t *,
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int sata_validate_scsi_address(sata_hba_inst_t *,
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int sata_validate_sata_address(sata_hba_inst_t *, int, int, int);
de8267e0f723ed2c38ea9def92d465f69a300f56timhstatic sata_pkt_t *sata_pkt_alloc(sata_pkt_txlate_t *, int (*)(caddr_t));
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int sata_dma_buf_setup(sata_pkt_txlate_t *, int, int (*)(caddr_t),
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int sata_probe_device(sata_hba_inst_t *, sata_device_t *);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic sata_drive_info_t *sata_get_device_info(sata_hba_inst_t *,
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int sata_identify_device(sata_hba_inst_t *, sata_drive_info_t *);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic struct buf *sata_alloc_local_buffer(sata_pkt_txlate_t *, int);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void sata_free_local_buffer(sata_pkt_txlate_t *);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic uint64_t sata_check_capacity(sata_drive_info_t *);
fa9e4066f08beec538e775443c5be79dd423fcabahrensvoid sata_adjust_dma_attr(sata_drive_info_t *, ddi_dma_attr_t *,
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int sata_fetch_device_identify_data(sata_hba_inst_t *,
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void sata_update_port_info(sata_hba_inst_t *, sata_device_t *);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void sata_update_port_scr(sata_port_scr_t *, sata_device_t *);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int sata_set_udma_mode(sata_hba_inst_t *, sata_drive_info_t *);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int sata_set_cache_mode(sata_hba_inst_t *, sata_drive_info_t *, int);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void sata_init_write_cache_mode(sata_drive_info_t *sdinfo);
66328dd3ff7c6b3566c06478698593e061733076ahrensstatic int sata_initialize_device(sata_hba_inst_t *, sata_drive_info_t *);
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* Event processing functions */
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void sata_event_daemon(void *);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void sata_event_thread_control(int);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void sata_process_controller_events(sata_hba_inst_t *sata_hba_inst);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void sata_process_device_reset(sata_hba_inst_t *, sata_address_t *);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrockstatic void sata_process_port_failed_event(sata_hba_inst_t *,
f65e61c04bc28ffd6bda04619c84330b420450b5ahrensstatic void sata_process_port_link_events(sata_hba_inst_t *,
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void sata_process_device_detached(sata_hba_inst_t *, sata_address_t *);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void sata_process_device_attached(sata_hba_inst_t *, sata_address_t *);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void sata_process_port_pwr_change(sata_hba_inst_t *, sata_address_t *);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void sata_process_cntrl_pwr_level_change(sata_hba_inst_t *);
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* Local functions for ioctl */
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int32_t sata_get_port_num(sata_hba_inst_t *, struct devctl_iocdata *);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void sata_cfgadm_state(sata_hba_inst_t *, int32_t,
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic dev_info_t *sata_get_target_dip(dev_info_t *, int32_t);
f65e61c04bc28ffd6bda04619c84330b420450b5ahrens/* Local translation functions */
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int sata_txlt_test_unit_ready(sata_pkt_txlate_t *);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int sata_txlt_start_stop_unit(sata_pkt_txlate_t *);
66328dd3ff7c6b3566c06478698593e061733076ahrensstatic int sata_txlt_read_capacity(sata_pkt_txlate_t *);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int sata_txlt_request_sense(sata_pkt_txlate_t *);
47cb52daa729f19e298c85a84e8df069365c5232Jeff Bonwickstatic int sata_txlt_log_sense(sata_pkt_txlate_t *);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrockstatic int sata_txlt_log_select(sata_pkt_txlate_t *);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int sata_txlt_mode_select(sata_pkt_txlate_t *);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int sata_txlt_synchronize_cache(sata_pkt_txlate_t *);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrockstatic int sata_txlt_nodata_cmd_immediate(sata_pkt_txlate_t *);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int sata_hba_start(sata_pkt_txlate_t *, int *);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int sata_txlt_invalid_command(sata_pkt_txlate_t *);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrockstatic int sata_txlt_lba_out_of_range(sata_pkt_txlate_t *);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrockstatic void sata_txlt_nodata_cmd_completion(sata_pkt_t *);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic struct scsi_extended_sense *sata_immediate_error_response(
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic struct scsi_extended_sense *sata_arq_sense(sata_pkt_txlate_t *);
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* Local functions */
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrockstatic void sata_identdev_to_inquiry(sata_hba_inst_t *, sata_drive_info_t *,
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int sata_build_msense_page_1(sata_drive_info_t *, int, uint8_t *);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int sata_build_msense_page_8(sata_drive_info_t *, int, uint8_t *);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int sata_build_msense_page_1a(sata_drive_info_t *, int, uint8_t *);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int sata_build_msense_page_1c(sata_drive_info_t *, int, uint8_t *);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int sata_mode_select_page_8(sata_pkt_txlate_t *,
fa9e4066f08beec538e775443c5be79dd423fcabahrens struct mode_cache_scsi3 *, int, int *, int *, int *);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrockstatic int sata_mode_select_page_1c(sata_pkt_txlate_t *,
f65e61c04bc28ffd6bda04619c84330b420450b5ahrens struct mode_info_excpt_page *, int, int *, int *, int *);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int sata_build_lsense_page_0(sata_drive_info_t *, uint8_t *);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int sata_build_lsense_page_10(sata_drive_info_t *, uint8_t *,
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int sata_build_lsense_page_2f(sata_drive_info_t *, uint8_t *,
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int sata_build_lsense_page_30(sata_drive_info_t *, uint8_t *,
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void sata_save_drive_settings(sata_drive_info_t *);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void sata_show_drive_info(sata_hba_inst_t *, sata_drive_info_t *);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void sata_log(sata_hba_inst_t *, uint_t, char *fmt, ...);
66328dd3ff7c6b3566c06478698593e061733076ahrensstatic int sata_fetch_smart_return_status(sata_hba_inst_t *,
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int sata_fetch_smart_data(sata_hba_inst_t *, sata_drive_info_t *,
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrockstatic int sata_smart_selftest_log(sata_hba_inst_t *,
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int sata_ext_smart_selftest_read_log(sata_hba_inst_t *,
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock sata_drive_info_t *, struct smart_ext_selftest_log *, uint16_t);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrockstatic int sata_smart_read_log(sata_hba_inst_t *, sata_drive_info_t *,
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrockstatic int sata_read_log_ext_directory(sata_hba_inst_t *, sata_drive_info_t *,
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void sata_gen_sysevent(sata_hba_inst_t *, sata_address_t *, int);
fa9e4066f08beec538e775443c5be79dd423fcabahrens * SATA Framework will ignore SATA HBA driver cb_ops structure and
f65e61c04bc28ffd6bda04619c84330b420450b5ahrens * register following one with SCSA framework.
f65e61c04bc28ffd6bda04619c84330b420450b5ahrens * Open & close are provided, so scsi framework will not use its own
47cb52daa729f19e298c85a84e8df069365c5232Jeff Bonwick 0, /* streamtab */
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Default sata pkt timeout. Used when a target driver scsi_pkt time is zero,
fa9e4066f08beec538e775443c5be79dd423fcabahrens * i.e. when scsi_pkt has not timeout specified.
f65e61c04bc28ffd6bda04619c84330b420450b5ahrensstatic int sata_default_pkt_time = 60; /* 60 seconds */
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * Intermediate buffer device access attributes - they are required,
47cb52daa729f19e298c85a84e8df069365c5232Jeff Bonwick * but not necessarily used.
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * Mutexes protecting structures in multithreaded operations.
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * Because events are relatively rare, a single global mutex protecting
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * data structures should be sufficient. To increase performance, add
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * separate mutex per each sata port and use global mutex only to protect
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * common data structures.
47cb52daa729f19e298c85a84e8df069365c5232Jeff Bonwickstatic kmutex_t sata_mutex; /* protects sata_hba_list */
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* Default write cache setting */
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Linked list of HBA instances
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Pointer to per-instance SATA HBA soft structure is stored in sata_hba_tran
fa9e4066f08beec538e775443c5be79dd423fcabahrens * structure and in sata soft state.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Event daemon related variables
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick * NCQ specific data
f65e61c04bc28ffd6bda04619c84330b420450b5ahrens/* Warlock directives */
fa9e4066f08beec538e775443c5be79dd423fcabahrens_NOTE(SCHEME_PROTECTS_DATA("No Mutex Needed", scsi_hba_tran))
fa9e4066f08beec538e775443c5be79dd423fcabahrens_NOTE(SCHEME_PROTECTS_DATA("No Mutex Needed", scsi_device))
fa9e4066f08beec538e775443c5be79dd423fcabahrens_NOTE(SCHEME_PROTECTS_DATA("No Mutex Needed", dev_ops))
fa9e4066f08beec538e775443c5be79dd423fcabahrens_NOTE(SCHEME_PROTECTS_DATA("No Mutex Needed", scsi_extended_sense))
fa9e4066f08beec538e775443c5be79dd423fcabahrens_NOTE(SCHEME_PROTECTS_DATA("No Mutex Needed", scsi_arq_status))
fa9e4066f08beec538e775443c5be79dd423fcabahrens_NOTE(SCHEME_PROTECTS_DATA("No Mutex Needed", ddi_dma_attr))
fa9e4066f08beec538e775443c5be79dd423fcabahrens_NOTE(SCHEME_PROTECTS_DATA("No Mutex Needed", ddi_dma_cookie_t))
f65e61c04bc28ffd6bda04619c84330b420450b5ahrens_NOTE(SCHEME_PROTECTS_DATA("No Mutex Needed", devctl_ap_state))
fa9e4066f08beec538e775443c5be79dd423fcabahrens_NOTE(MUTEX_PROTECTS_DATA(sata_mutex, sata_hba_inst::satahba_next))
66328dd3ff7c6b3566c06478698593e061733076ahrens_NOTE(MUTEX_PROTECTS_DATA(sata_mutex, sata_hba_inst::satahba_prev))
fa9e4066f08beec538e775443c5be79dd423fcabahrens_NOTE(SCHEME_PROTECTS_DATA("No Mutex Needed", sata_hba_inst::satahba_tran))
fa9e4066f08beec538e775443c5be79dd423fcabahrens_NOTE(SCHEME_PROTECTS_DATA("No Mutex Needed", sata_hba_inst::satahba_dip))
fa9e4066f08beec538e775443c5be79dd423fcabahrens_NOTE(SCHEME_PROTECTS_DATA("Scheme", sata_hba_inst::satahba_attached))
fa9e4066f08beec538e775443c5be79dd423fcabahrens_NOTE(DATA_READABLE_WITHOUT_LOCK(sata_hba_inst::satahba_dev_port))
fa9e4066f08beec538e775443c5be79dd423fcabahrens_NOTE(MUTEX_PROTECTS_DATA(sata_hba_inst::satahba_mutex,
fa9e4066f08beec538e775443c5be79dd423fcabahrens_NOTE(MUTEX_PROTECTS_DATA(sata_cport_info::cport_mutex, \
fa9e4066f08beec538e775443c5be79dd423fcabahrens_NOTE(DATA_READABLE_WITHOUT_LOCK(sata_cport_info::cport_devp))
fa9e4066f08beec538e775443c5be79dd423fcabahrens_NOTE(SCHEME_PROTECTS_DATA("Scheme", sata_cport_info::cport_addr))
fa9e4066f08beec538e775443c5be79dd423fcabahrens_NOTE(MUTEX_PROTECTS_DATA(sata_cport_info::cport_mutex, \
66328dd3ff7c6b3566c06478698593e061733076ahrens_NOTE(DATA_READABLE_WITHOUT_LOCK(sata_cport_info::cport_dev_type))
66328dd3ff7c6b3566c06478698593e061733076ahrens_NOTE(MUTEX_PROTECTS_DATA(sata_cport_info::cport_mutex, \
fa9e4066f08beec538e775443c5be79dd423fcabahrens_NOTE(DATA_READABLE_WITHOUT_LOCK(sata_cport_info::cport_state))
66328dd3ff7c6b3566c06478698593e061733076ahrens_NOTE(DATA_READABLE_WITHOUT_LOCK(sata_pmport_info::pmport_dev_type))
66328dd3ff7c6b3566c06478698593e061733076ahrens_NOTE(DATA_READABLE_WITHOUT_LOCK(sata_pmport_info::pmport_sata_drive))
66328dd3ff7c6b3566c06478698593e061733076ahrens_NOTE(DATA_READABLE_WITHOUT_LOCK(sata_pmult_info::pmult_dev_port))
fa9e4066f08beec538e775443c5be79dd423fcabahrens_NOTE(DATA_READABLE_WITHOUT_LOCK(sata_pmult_info::pmult_num_dev_ports))
fa9e4066f08beec538e775443c5be79dd423fcabahrens_NOTE(SCHEME_PROTECTS_DATA("No Mutex Needed", mbuf_count))
66328dd3ff7c6b3566c06478698593e061733076ahrens_NOTE(SCHEME_PROTECTS_DATA("No Mutex Needed", mbuffail_count))
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* End of warlock directives */
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* ************** loadable module configuration functions ************** */
fa9e4066f08beec538e775443c5be79dd423fcabahrens mutex_init(&sata_event_mutex, NULL, MUTEX_DRIVER, NULL);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock mutex_init(&sata_log_mutex, NULL, MUTEX_DRIVER, NULL);
47cb52daa729f19e298c85a84e8df069365c5232Jeff Bonwick cv_init(&sata_event_cv, NULL, CV_DRIVER, NULL);
fa9e4066f08beec538e775443c5be79dd423fcabahrens cmn_err(CE_WARN, "sata: _init: mod_install failed\n");
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* ********************* SATA HBA entry points ********************* */
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Called by SATA HBA from _init().
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Registers HBA driver instance/sata framework pair with scsi framework, by
fa9e4066f08beec538e775443c5be79dd423fcabahrens * calling scsi_hba_init().
fa9e4066f08beec538e775443c5be79dd423fcabahrens * SATA HBA driver cb_ops are ignored - SATA HBA framework cb_ops are used
fa9e4066f08beec538e775443c5be79dd423fcabahrens * instead. SATA HBA framework cb_ops pointer overwrites SATA HBA driver
fa9e4066f08beec538e775443c5be79dd423fcabahrens * cb_ops pointer in SATA HBA driver dev_ops structure.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * SATA HBA framework cb_ops supplies cb_open cb_close and cb_ioctl vectors.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Return status of the scsi_hba_init() is returned to a calling SATA HBA
fa9e4066f08beec538e775443c5be79dd423fcabahrens "sata_hba_init: name %s \n",
fa9e4066f08beec538e775443c5be79dd423fcabahrens ((struct modldrv *)(modlp->ml_linkage[0]))->drv_linkinfo);
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Fill-up cb_ops and dev_ops when necessary
fa9e4066f08beec538e775443c5be79dd423fcabahrens hba_ops = ((struct modldrv *)(modlp->ml_linkage[0]))->drv_dev_ops;
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Provide pointer to SATA dev_ops
66328dd3ff7c6b3566c06478698593e061733076ahrens * Register SATA HBA with SCSI framework
f65e61c04bc28ffd6bda04619c84330b420450b5ahrens return (0);
f65e61c04bc28ffd6bda04619c84330b420450b5ahrens/* HBA attach stages */
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * Called from SATA HBA driver's attach routine to attach an instance of
fa9e4066f08beec538e775443c5be79dd423fcabahrens * For DDI_ATTACH command:
fa9e4066f08beec538e775443c5be79dd423fcabahrens * sata_hba_inst structure is allocated here and initialized with pointers to
fa9e4066f08beec538e775443c5be79dd423fcabahrens * SATA framework implementation of required scsi tran functions.
f65e61c04bc28ffd6bda04619c84330b420450b5ahrens * The scsi_tran's tran_hba_private field is used by SATA Framework to point
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * to the soft structure (sata_hba_inst) allocated by SATA framework for
fa9e4066f08beec538e775443c5be79dd423fcabahrens * SATA HBA instance related data.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * The scsi_tran's tran_hba_private field is used by SATA framework to
fa9e4066f08beec538e775443c5be79dd423fcabahrens * store a pointer to per-HBA-instance of sata_hba_inst structure.
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * The sata_hba_inst structure is cross-linked to scsi tran structure.
47cb52daa729f19e298c85a84e8df069365c5232Jeff Bonwick * Among other info, a pointer to sata_hba_tran structure is stored in
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * sata_hba_inst. The sata_hba_inst structures for different HBA instances are
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * linked together into the list, pointed to by sata_hba_list.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * On the first HBA instance attach the sata event thread is initialized.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Attachment points are created for all SATA ports of the HBA being attached.
f65e61c04bc28ffd6bda04619c84330b420450b5ahrens * All HBA instance's SATA ports are probed and type of plugged devices is
f65e61c04bc28ffd6bda04619c84330b420450b5ahrens * determined. For each device of a supported type, a target node is created.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * DDI_SUCCESS is returned when attachment process is successful,
fa9e4066f08beec538e775443c5be79dd423fcabahrens * DDI_FAILURE is returned otherwise.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * For DDI_RESUME command:
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Not implemented at this time (postponed until phase 2 of the development).
fa9e4066f08beec538e775443c5be79dd423fcabahrenssata_hba_attach(dev_info_t *dip, sata_hba_tran_t *sata_tran,
66328dd3ff7c6b3566c06478698593e061733076ahrens "sata_hba_attach: node %s (%s%d)\n",
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Postponed until phase 2 of the development
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock /* cmd == DDI_ATTACH */
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (sata_validate_sata_hba_tran(dip, sata_tran) != SATA_SUCCESS) {
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock "sata_hba_attach: invalid sata_hba_tran"));
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * Allocate and initialize SCSI tran structure.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * SATA copy of tran_bus_config is provided to create port nodes.
fa9e4066f08beec538e775443c5be79dd423fcabahrens scsi_tran = scsi_hba_tran_alloc(dip, SCSI_HBA_CANSLEEP);
f65e61c04bc28ffd6bda04619c84330b420450b5ahrens * Allocate soft structure for SATA HBA instance.
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * There is a separate softstate for each HBA instance.
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock sata_hba_inst = kmem_zalloc(sizeof (struct sata_hba_inst), KM_SLEEP);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock ASSERT(sata_hba_inst != NULL); /* this should not fail */
fa9e4066f08beec538e775443c5be79dd423fcabahrens mutex_init(&sata_hba_inst->satahba_mutex, NULL, MUTEX_DRIVER, NULL);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * scsi_trans's tran_hba_private is used by SATA Framework to point to
fa9e4066f08beec538e775443c5be79dd423fcabahrens * soft structure allocated by SATA framework for
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * SATA HBA instance related data.
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (scsi_hba_attach_setup(dip, sata_tran->sata_tran_hba_dma_attr,
fa9e4066f08beec538e775443c5be79dd423fcabahrens cmn_err(CE_WARN, "?SATA: %s%d hba scsi attach failed",
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (!ddi_prop_exists(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "sata")) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens "failed to create hba sata prop"));
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Save pointers in hba instance soft state.
66328dd3ff7c6b3566c06478698593e061733076ahrens * Create a task queue to handle emulated commands completion
66328dd3ff7c6b3566c06478698593e061733076ahrens * Use node name, dash, instance number as the queue name.
66328dd3ff7c6b3566c06478698593e061733076ahrens (void) strlcat(taskq_name, DEVI(dip)->devi_node_name,
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock sata_hba_inst->satahba_taskq = taskq_create(taskq_name, 1,
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock minclsyspri, 1, sata_tran->sata_tran_hba_num_cports,
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Create events thread if not created yet.
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * Link this hba instance into the list.
66328dd3ff7c6b3566c06478698593e061733076ahrens * Create SATA HBA devctl minor node for sata_hba_open, close, ioctl
fa9e4066f08beec538e775443c5be79dd423fcabahrens * SATA HBA driver should not use its own open/close entry points.
66328dd3ff7c6b3566c06478698593e061733076ahrens * Make sure that instance number doesn't overflow
fa9e4066f08beec538e775443c5be79dd423fcabahrens * when forming minor numbers.
66328dd3ff7c6b3566c06478698593e061733076ahrens ASSERT(ddi_get_instance(dip) <= (L_MAXMIN >> INST_MINOR_SHIFT));
fa9e4066f08beec538e775443c5be79dd423fcabahrens "cannot create devctl minor node");
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Set-up kstats here, if necessary.
66328dd3ff7c6b3566c06478698593e061733076ahrens * (postponed until phase 2 of the development).
66328dd3ff7c6b3566c06478698593e061733076ahrens * Probe controller ports. This operation will describe a current
66328dd3ff7c6b3566c06478698593e061733076ahrens * controller/port/multipliers/device configuration and will create
66328dd3ff7c6b3566c06478698593e061733076ahrens * attachment points.
66328dd3ff7c6b3566c06478698593e061733076ahrens * We may end-up with just a controller with no devices attached.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * For the ports with a supported device attached, device target nodes
fa9e4066f08beec538e775443c5be79dd423fcabahrens * are created and devices are initialized.
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (hba_attach_state & HBA_ATTACH_STAGE_SCSI_ATTACHED)
92241e0b80813d0b83c08e730a29b9d1831794fcTom Erickson if (hba_attach_state & HBA_ATTACH_STAGE_SATA_HBA_INST) {
92241e0b80813d0b83c08e730a29b9d1831794fcTom Erickson sizeof (struct sata_hba_inst));
fa9e4066f08beec538e775443c5be79dd423fcabahrens sata_log(NULL, CE_WARN, "?SATA: %s%d hba attach failed",
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Called by SATA HBA from to detach an instance of the driver.
66328dd3ff7c6b3566c06478698593e061733076ahrens * For DDI_DETACH command:
66328dd3ff7c6b3566c06478698593e061733076ahrens * Free local structures allocated for SATA HBA instance during
fa9e4066f08beec538e775443c5be79dd423fcabahrens * sata_hba_attach processing.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Returns DDI_SUCCESS when HBA was detached, DDI_FAILURE otherwise.
92241e0b80813d0b83c08e730a29b9d1831794fcTom Erickson * For DDI_SUSPEND command:
92241e0b80813d0b83c08e730a29b9d1831794fcTom Erickson * Not implemented at this time (postponed until phase 2 of the development)
92241e0b80813d0b83c08e730a29b9d1831794fcTom Erickson * Returnd DDI_SUCCESS.
92241e0b80813d0b83c08e730a29b9d1831794fcTom Erickson * When the last HBA instance is detached, the event daemon is terminated.
92241e0b80813d0b83c08e730a29b9d1831794fcTom Erickson * NOTE: cport support only, no port multiplier support.
92241e0b80813d0b83c08e730a29b9d1831794fcTom Ericksonsata_hba_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
fa9e4066f08beec538e775443c5be79dd423fcabahrens SATADBG3(SATA_DBG_HBA_IF, NULL, "sata_hba_detach: node %s (%s%d)\n",
fa9e4066f08beec538e775443c5be79dd423fcabahrens ddi_node_name(dip), ddi_driver_name(dip), ddi_get_instance(dip));
fa9e4066f08beec538e775443c5be79dd423fcabahrens if ((scsi_hba_tran = ddi_get_driver_private(dip)) == NULL)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Free all target nodes - at this point
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * devices should be at least offlined
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * otherwise scsi_hba_detach() should not be called.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw for (ncport = 0; ncport < SATA_NUM_CPORTS(sata_hba_inst);
fa9e4066f08beec538e775443c5be79dd423fcabahrens "sata_hba_detach: "
fa9e4066f08beec538e775443c5be79dd423fcabahrens "Target node not "
fa9e4066f08beec538e775443c5be79dd423fcabahrens "removed !"));
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Disable sata event daemon processing for this HBA
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * Remove event daemon thread, if it is last HBA instance.
66328dd3ff7c6b3566c06478698593e061733076ahrens /* Remove this HBA instance from the HBA list */
ad860c82b2a8ffe69f42630da73ded0c92a7a36ebonwick * At this point there should be no target nodes attached.
ad860c82b2a8ffe69f42630da73ded0c92a7a36ebonwick * Detach and destroy device and port info structures.
fa9e4066f08beec538e775443c5be79dd423fcabahrens for (ncport = 0; ncport < SATA_NUM_CPORTS(sata_hba_inst);
92241e0b80813d0b83c08e730a29b9d1831794fcTom Erickson /* Release device structure */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* Release cport info */
fa9e4066f08beec538e775443c5be79dd423fcabahrens scsi_hba_tran_free(sata_hba_inst->satahba_scsi_tran);
fa9e4066f08beec538e775443c5be79dd423fcabahrens sizeof (struct sata_hba_inst));
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Postponed until phase 2
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Called by an HBA drive from _fini() routine.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Unregisters SATA HBA instance/SATA framework pair from the scsi framework.
66328dd3ff7c6b3566c06478698593e061733076ahrens "sata_hba_fini: name %s\n",
fa9e4066f08beec538e775443c5be79dd423fcabahrens ((struct modldrv *)(modlp->ml_linkage[0]))->drv_linkinfo);
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Default open and close routine for sata_hba framework.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Open devctl node.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * 0 if node was open successfully, error code otherwise.
fa9e4066f08beec538e775443c5be79dd423fcabahrenssata_hba_open(dev_t *devp, int flags, int otyp, cred_t *credp)
fa9e4066f08beec538e775443c5be79dd423fcabahrens SATADBG1(SATA_DBG_IOCTL_IF, NULL, "sata_hba_open: entered", NULL);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock if ((scsi_hba_tran = ddi_get_driver_private(dip)) == NULL)
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (sata_hba_inst == NULL || sata_hba_inst->satahba_attached == 0)
e7437265dc2a4920c197ed4337665539d358b22cahrens if (sata_hba_inst->satahba_open_flag == SATA_DEVCTL_EXOPENED) {
e7437265dc2a4920c197ed4337665539d358b22cahrens * Close devctl node.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * 0 if node was closed successfully, error code otherwise.
fa9e4066f08beec538e775443c5be79dd423fcabahrenssata_hba_close(dev_t dev, int flag, int otyp, cred_t *credp)
088f389458728c464569a5506b58070254fa4f7dahrens SATADBG1(SATA_DBG_IOCTL_IF, NULL, "sata_hba_close: entered", NULL);
088f389458728c464569a5506b58070254fa4f7dahrens if ((scsi_hba_tran = ddi_get_driver_private(dip)) == NULL)
088f389458728c464569a5506b58070254fa4f7dahrens if (sata_hba_inst == NULL || sata_hba_inst->satahba_attached == 0)
3f9d6ad73e45c6823b409f93b0c8d4f62861d2d5Lin Ling return (0);
3f9d6ad73e45c6823b409f93b0c8d4f62861d2d5Lin Ling * Standard IOCTL commands for SATA hotplugging.
3f9d6ad73e45c6823b409f93b0c8d4f62861d2d5Lin Ling * Implemented DEVCTL_AP commands:
3f9d6ad73e45c6823b409f93b0c8d4f62861d2d5Lin Ling * DEVCTL_AP_CONNECT
3f9d6ad73e45c6823b409f93b0c8d4f62861d2d5Lin Ling * DEVCTL_AP_DISCONNECT
3f9d6ad73e45c6823b409f93b0c8d4f62861d2d5Lin Ling * DEVCTL_AP_CONFIGURE
3f9d6ad73e45c6823b409f93b0c8d4f62861d2d5Lin Ling * DEVCTL_UNCONFIGURE
3f9d6ad73e45c6823b409f93b0c8d4f62861d2d5Lin Ling * DEVCTL_AP_CONTROL
3f9d6ad73e45c6823b409f93b0c8d4f62861d2d5Lin Ling * Commands passed to default ndi ioctl handler:
3f9d6ad73e45c6823b409f93b0c8d4f62861d2d5Lin Ling * DEVCTL_DEVICE_GETSTATE
3f9d6ad73e45c6823b409f93b0c8d4f62861d2d5Lin Ling * DEVCTL_DEVICE_ONLINE
3f9d6ad73e45c6823b409f93b0c8d4f62861d2d5Lin Ling * DEVCTL_DEVICE_OFFLINE
3f9d6ad73e45c6823b409f93b0c8d4f62861d2d5Lin Ling * DEVCTL_DEVICE_REMOVE
3f9d6ad73e45c6823b409f93b0c8d4f62861d2d5Lin Ling * DEVCTL_DEVICE_INSERT
3f9d6ad73e45c6823b409f93b0c8d4f62861d2d5Lin Ling * DEVCTL_BUS_GETSTATE
3f9d6ad73e45c6823b409f93b0c8d4f62861d2d5Lin Ling * All other cmds are passed to HBA if it provide ioctl handler, or failed
3f9d6ad73e45c6823b409f93b0c8d4f62861d2d5Lin Ling * 0 if successful,
3f9d6ad73e45c6823b409f93b0c8d4f62861d2d5Lin Ling * error code if operation failed.
3f9d6ad73e45c6823b409f93b0c8d4f62861d2d5Lin Ling * NOTE: Port Multiplier is not supported.
3f9d6ad73e45c6823b409f93b0c8d4f62861d2d5Lin Lingsata_hba_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp,
088f389458728c464569a5506b58070254fa4f7dahrens if ((scsi_hba_tran = ddi_get_driver_private(dip)) == NULL)
3f9d6ad73e45c6823b409f93b0c8d4f62861d2d5Lin Ling * There may be more cases that we want to pass to default
3f9d6ad73e45c6823b409f93b0c8d4f62861d2d5Lin Ling * handler rather then fail them.
3f9d6ad73e45c6823b409f93b0c8d4f62861d2d5Lin Ling /* read devctl ioctl data */
9966ca11f4a1481acce85f690fa59e4084050627Matthew Ahrens if (ndi_dc_allochdl((void *)arg, &dcp) != NDI_SUCCESS)
3f9d6ad73e45c6823b409f93b0c8d4f62861d2d5Lin Ling if ((comp_port = sata_get_port_num(sata_hba_inst, dcp)) ==
9966ca11f4a1481acce85f690fa59e4084050627Matthew Ahrens /* Only cport is considered now, i.e. SATA_ADDR_CPORT */
9966ca11f4a1481acce85f690fa59e4084050627Matthew Ahrens if (sata_validate_sata_address(sata_hba_inst, cport, pmport,
9966ca11f4a1481acce85f690fa59e4084050627Matthew Ahrens cportinfo = SATA_CPORT_INFO(sata_hba_inst, cport);
9966ca11f4a1481acce85f690fa59e4084050627Matthew Ahrens mutex_enter(&SATA_CPORT_INFO(sata_hba_inst, cport)->
9966ca11f4a1481acce85f690fa59e4084050627Matthew Ahrens if (cportinfo->cport_event_flags & SATA_EVNT_LOCK_PORT_BUSY) {
9966ca11f4a1481acce85f690fa59e4084050627Matthew Ahrens * Cannot process ioctl request now. Come back later.
9966ca11f4a1481acce85f690fa59e4084050627Matthew Ahrens mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, cport)->
3f9d6ad73e45c6823b409f93b0c8d4f62861d2d5Lin Ling /* Block event processing for this port */
3f9d6ad73e45c6823b409f93b0c8d4f62861d2d5Lin Ling cportinfo->cport_event_flags |= SATA_APCTL_LOCK_PORT_BUSY;
3f9d6ad73e45c6823b409f93b0c8d4f62861d2d5Lin Ling mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, cport)->cport_mutex);
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Normally, cfgadm sata plugin will try to offline
fa9e4066f08beec538e775443c5be79dd423fcabahrens * (unconfigure) device before this request. Nevertheless,
fa9e4066f08beec538e775443c5be79dd423fcabahrens * if a device is still configured, we need to
fa9e4066f08beec538e775443c5be79dd423fcabahrens * attempt to offline and unconfigure device first, and we will
fa9e4066f08beec538e775443c5be79dd423fcabahrens * deactivate the port regardless of the unconfigure
fa9e4066f08beec538e775443c5be79dd423fcabahrens * operation results.
66328dd3ff7c6b3566c06478698593e061733076ahrens * DEVCTL_AP_DISCONNECT invokes
66328dd3ff7c6b3566c06478698593e061733076ahrens * sata_hba_inst->satahba_tran->
66328dd3ff7c6b3566c06478698593e061733076ahrens * sata_tran_hotplug_ops->sata_tran_port_deactivate().
87e5029a3226958edab1512d6182bc74d8d80c9aahrens * If successful, the device structure (if any) attached
87e5029a3226958edab1512d6182bc74d8d80c9aahrens * to a port is removed and state of the port marked
87e5029a3226958edab1512d6182bc74d8d80c9aahrens * appropriately.
87e5029a3226958edab1512d6182bc74d8d80c9aahrens * Failure of the port_deactivate may keep port in
87e5029a3226958edab1512d6182bc74d8d80c9aahrens * the active state, or may fail the port.
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock /* Check the current state of the port */
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock mutex_enter(&SATA_CPORT_INFO(sata_hba_inst, cport)->
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Sanity check */
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (SATA_PORT_DEACTIVATE_FUNC(sata_hba_inst) == NULL) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* No physical port deactivation supported. */
fa9e4066f08beec538e775443c5be79dd423fcabahrens * set port's dev_state to not ready - this will disable
fa9e4066f08beec538e775443c5be79dd423fcabahrens * an access to an attached device.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * If a target node exists, try to offline
fa9e4066f08beec538e775443c5be79dd423fcabahrens * a device and remove target node.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* target node exist */
fa9e4066f08beec538e775443c5be79dd423fcabahrens * A target node remained
fa9e4066f08beec538e775443c5be79dd423fcabahrens * attached. This happens when
fa9e4066f08beec538e775443c5be79dd423fcabahrens * the file was open or a node
fa9e4066f08beec538e775443c5be79dd423fcabahrens * was waiting for resources.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Cannot do anything about it.
fa9e4066f08beec538e775443c5be79dd423fcabahrens "sata_hba_ioctl: "
fa9e4066f08beec538e775443c5be79dd423fcabahrens "disconnect: cannot "
fa9e4066f08beec538e775443c5be79dd423fcabahrens "remove target node!!!"));
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Remove and release sata_drive_info
fa9e4066f08beec538e775443c5be79dd423fcabahrens * structure.
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia * Note: PMult info requires different handling.
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia * Put PMult handling code here, when PMult is
92241e0b80813d0b83c08e730a29b9d1831794fcTom Erickson mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, cport)->cport_mutex);
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia /* Just ask HBA driver to deactivate port */
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia sata_device.satadev_addr.qual = SATA_ADDR_DCPORT;
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia rval = (*SATA_PORT_DEACTIVATE_FUNC(sata_hba_inst))
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia * Generate sysevent - EC_DR / ESC_DR_AP_STATE_CHANGE
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia * without the hint.
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia mutex_enter(&SATA_CPORT_INFO(sata_hba_inst, cport)->
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia sata_update_port_info(sata_hba_inst, &sata_device);
f65e61c04bc28ffd6bda04619c84330b420450b5ahrens * Port deactivation failure - do not
f65e61c04bc28ffd6bda04619c84330b420450b5ahrens * change port state unless the state
8248818d5849649ef734d62da097e90222a23763nd * returned by HBA indicates a port failure.
8248818d5849649ef734d62da097e90222a23763nd * Deactivation succeded. From now on the framework
8248818d5849649ef734d62da097e90222a23763nd * will not know what is happening to the device, until
8248818d5849649ef734d62da097e90222a23763nd * the port is activated again.
8248818d5849649ef734d62da097e90222a23763nd mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, cport)->cport_mutex);
8248818d5849649ef734d62da097e90222a23763nd * The unconfigure operation uses generic nexus operation to
8248818d5849649ef734d62da097e90222a23763nd * offline a device. It leaves a target device node attached.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * and obviously sata_drive_info attached as well, because
fa9e4066f08beec538e775443c5be79dd423fcabahrens * from the hardware point of view nothing has changed.
f65e61c04bc28ffd6bda04619c84330b420450b5ahrens if ((tdip = sata_get_target_dip(dip, comp_port)) != NULL) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens "sata_hba_ioctl: unconfigure: "
f65e61c04bc28ffd6bda04619c84330b420450b5ahrens "failed to unconfigure "
fa9e4066f08beec538e775443c5be79dd423fcabahrens * The target node devi_state should be marked with
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * DEVI_DEVICE_OFFLINE by ndi_devi_offline().
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * This would be the indication for cfgadm that
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * the AP node occupant state is 'unconfigured'.
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * This would indicate a failure on the part of cfgadm
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * to detect correct state of the node prior to this
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * call - one cannot unconfigure non-existing device.
fa9e4066f08beec538e775443c5be79dd423fcabahrens "sata_hba_ioctl: unconfigure: "
3d6926289465757c3da780cea696825b0d730283Sanjeev Bagewadi "attempt to unconfigure non-existing device "
3d6926289465757c3da780cea696825b0d730283Sanjeev Bagewadi * The sata cfgadm pluging will invoke this operation only if
3d6926289465757c3da780cea696825b0d730283Sanjeev Bagewadi * port was found in the disconnect state (failed state
3d6926289465757c3da780cea696825b0d730283Sanjeev Bagewadi * is also treated as the disconnected state).
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi * DEVCTL_AP_CONNECT would invoke
3d6926289465757c3da780cea696825b0d730283Sanjeev Bagewadi * sata_hba_inst->satahba_tran->
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi * sata_tran_hotplug_ops->sata_tran_port_activate().
3d6926289465757c3da780cea696825b0d730283Sanjeev Bagewadi * If successful and a device is found attached to the port,
3d6926289465757c3da780cea696825b0d730283Sanjeev Bagewadi * the initialization sequence is executed to attach
3d6926289465757c3da780cea696825b0d730283Sanjeev Bagewadi * a device structure to a port structure. The device is not
3d6926289465757c3da780cea696825b0d730283Sanjeev Bagewadi * set in configured state (system-wise) by this operation.
3d6926289465757c3da780cea696825b0d730283Sanjeev Bagewadi * The state of the port and a device would be set
3d6926289465757c3da780cea696825b0d730283Sanjeev Bagewadi * appropriately.
3d6926289465757c3da780cea696825b0d730283Sanjeev Bagewadi * Note, that activating the port may generate link events,
3d6926289465757c3da780cea696825b0d730283Sanjeev Bagewadi * so is is important that following processing and the
3d6926289465757c3da780cea696825b0d730283Sanjeev Bagewadi * event processing does not interfere with each other!
3d6926289465757c3da780cea696825b0d730283Sanjeev Bagewadi * This operation may remove port failed state and will
12a2833a0260ba374a4e6d8225376193e908784aSanjeev Bagewadi * try to make port active and in good standing.
3d6926289465757c3da780cea696825b0d730283Sanjeev Bagewadi /* We only care about host sata cport for now */
3d6926289465757c3da780cea696825b0d730283Sanjeev Bagewadi if (SATA_PORT_ACTIVATE_FUNC(sata_hba_inst) != NULL) {
3d6926289465757c3da780cea696825b0d730283Sanjeev Bagewadi /* Just let HBA driver to activate port */
3d6926289465757c3da780cea696825b0d730283Sanjeev Bagewadi if ((*SATA_PORT_ACTIVATE_FUNC(sata_hba_inst))
3d6926289465757c3da780cea696825b0d730283Sanjeev Bagewadi * Port activation failure.
3d6926289465757c3da780cea696825b0d730283Sanjeev Bagewadi mutex_enter(&SATA_CPORT_INFO(sata_hba_inst,
3d6926289465757c3da780cea696825b0d730283Sanjeev Bagewadi "sata_hba_ioctl: connect: "
3d6926289465757c3da780cea696825b0d730283Sanjeev Bagewadi "failed to activate SATA cport %d",
cport));
case DEVCTL_AP_CONFIGURE:
&sata_device);
cport));
cport);
cport));
case DEVCTL_AP_GETSTATE:
case DEVCTL_AP_CONTROL:
#ifdef _MULTI_DATAMODEL
mode) != 0) {
return (EFAULT);
return (EINVAL);
return (EINVAL);
return (EBUSY);
case SATA_CFGA_RESET_PORT:
&sata_device);
case SATA_CFGA_RESET_DEVICE:
&sata_device);
&sata_device);
* port disconnect/connect and re-probing is
case SATA_CFGA_RESET_ALL:
int tcport;
for (tcport = 0;
tcport++) {
SATA_EVNT_LOCK_PORT_BUSY) != 0) {
if (rv == 0) {
for (tcport = 0;
tcport++) {
for (tcport = 0;
tcport++) {
return (rv);
&sata_device);
NULL);
NDI_UNCONFIG) !=
NDI_SUCCESS) {
NDI_DEVI_REMOVE) !=
NDI_SUCCESS) {
cport));
NULL;
sizeof (sata_drive_info_t));
cport));
case SATA_CFGA_PORT_ACTIVATE:
&sata_device);
cport));
case SATA_CFGA_PORT_SELF_TEST:
&sata_device);
NULL) {
case SATA_CFGA_GET_AP_TYPE:
const char *ap_type;
case SATA_DTYPE_NONE:
case SATA_DTYPE_ATADISK:
case SATA_DTYPE_ATAPICD:
case SATA_DTYPE_PMULT:
case SATA_DTYPE_UNKNOWN:
case SATA_CFGA_GET_MODEL_INFO:
&sata_device);
char ap_info[
&sata_device);
char ap_info[
&sata_device);
if (rval != 0) {
if (dcp) {
return (rv);
#ifndef __lock_lint
&sata_device) != 0)
return (DDI_FAILURE);
return (DDI_FAILURE);
return (DDI_FAILURE);
return (DDI_SUCCESS);
return (DDI_SUCCESS);
int rval;
return (rval);
#ifndef __lock_lint
&sata_device) != 0)
static struct scsi_pkt *
int rval;
return (NULL);
return (NULL);
return (pkt);
* Packet was preallocated/initialized by previous call
return (pkt);
switch (rval) {
case DDI_DMA_NORESOURCES:
case DDI_DMA_NOMAPPING:
case DDI_DMA_BADATTR:
case DDI_DMA_TOOBIG:
return (NULL);
return (pkt);
int cport;
int rval;
return (TRAN_FATAL_ERROR);
return (rval);
case SCMD_INQUIRY:
case SCMD_TEST_UNIT_READY:
case SCMD_START_STOP:
case SCMD_READ_CAPACITY:
case SCMD_REQUEST_SENSE:
case SCMD_LOG_SENSE_G1:
case SCMD_LOG_SELECT_G1:
case SCMD_MODE_SENSE:
case SCMD_MODE_SENSE_G1:
case SCMD_MODE_SELECT:
case SCMD_MODE_SELECT_G1:
case SCMD_SYNCHRONIZE_CACHE:
case SCMD_READ:
case SCMD_READ_G1:
case SCMD_READ_G4:
case SCMD_READ_G5:
case SCMD_WRITE:
case SCMD_WRITE_G1:
case SCMD_WRITE_G4:
case SCMD_WRITE_G5:
case SCMD_SEEK:
return (rval);
SATA_SUCCESS) {
int val;
} else if (val == 0 &&
int rval;
NULL) {
case SCSI_CAP_ARQ:
case SCSI_CAP_SECTOR_SIZE:
#if defined(_UNTAGGED_QING_SUPPORTED)
case SCSI_CAP_UNTAGGED_QING:
case SCSI_CAP_TAGGED_QING:
case SCSI_CAP_DMA_MAX:
&adj_dma_attr);
return (rval);
* All supported capabilities are fixed/unchangeable.
#ifndef __lock_lint
int rval;
case SCSI_CAP_ARQ:
case SCSI_CAP_SECTOR_SIZE:
case SCSI_CAP_TAGGED_QING:
case SCSI_CAP_DMA_MAX:
#if defined(_UNTAGGED_QING_SUPPORTED)
case SCSI_CAP_UNTAGGED_QING:
return (rval);
#ifndef __lock_lint
#ifndef __lock_lint
int rval;
int direction;
return (TRAN_BADPKT);
return (TRAN_FATAL_ERROR);
!ddi_in_panic()) {
return (TRAN_BUSY);
return (TRAN_ACCEPT);
#ifdef _LITTLE_ENDIAN
TQ_SLEEP) == 0)
return (TRAN_BUSY);
return (TRAN_ACCEPT);
int rval;
return (rval);
TQ_SLEEP) == 0)
return (TRAN_BUSY);
return (TRAN_ACCEPT);
int count;
uint8_t *p;
int rval;
return (rval);
goto done;
unsigned int bufsize;
sizeof (struct scsi_inquiry));
case INQUIRY_SUP_VPD_PAGE:
case INQUIRY_USN_PAGE:
#ifdef _LITTLE_ENDIAN
goto done;
done:
TQ_SLEEP) == 0)
return (TRAN_BUSY);
return (TRAN_ACCEPT);
int rval;
return (rval);
sizeof (struct scsi_extended_sense));
TQ_SLEEP) == 0)
return (TRAN_BUSY);
return (TRAN_ACCEPT);
int power_state;
int rval;
return (rval);
switch (power_state) {
case SATA_PWRMODE_ACTIVE:
case SATA_PWRMODE_IDLE:
TQ_SLEEP) == 0)
return (TRAN_BUSY);
return (TRAN_ACCEPT);
int rval;
int synch;
return (rval);
TQ_SLEEP) == 0)
return (TRAN_BUSY);
return (TRAN_ACCEPT);
return (rval);
if (synch) {
return (TRAN_ACCEPT);
int rval;
return (rval);
TQ_SLEEP) == 0)
return (TRAN_BUSY);
return (TRAN_ACCEPT);
int rval;
return (rval);
len = 0;
bdlen = 0;
#ifndef __lock_lint
case MODEPAGE_RW_ERRRECOV:
case MODEPAGE_CACHING:
goto done;
case MODEPAGE_INFO_EXCPT:
goto err;
case MODEPAGE_POWER_COND:
case MODEPAGE_ALLPAGES:
err:
goto done;
done:
TQ_SLEEP) == 0)
return (TRAN_BUSY);
return (TRAN_ACCEPT);
int dmod = 0;
return (rval);
goto done;
while (pllen > 0) {
case MODEPAGE_CACHING:
goto done;
case MODEPAGE_INFO_EXCPT:
goto done;
done:
if (dmod != 0) {
int rv;
&new_sdinfo);
if (rv == 0) {
TQ_SLEEP) == 0)
return (TRAN_BUSY);
return (rval);
int rval;
return (rval);
switch (pc) {
case PC_CUMULATIVE_VALUES:
goto done;
switch (page_code) {
goto done;
len = 0;
switch (page_code) {
goto done;
goto done;
goto done;
goto done;
goto done;
goto no_header;
goto done;
done:
TQ_SLEEP) == 0)
return (TRAN_BUSY);
return (TRAN_ACCEPT);
int rval;
int synch;
return (rval);
case SCMD_READ:
case SCMD_READ_G1:
case SCMD_READ_G5:
case SCMD_READ_G4:
#ifndef __lock_lint
SATA_DEV_F_NCQ) &&
SATA_CTLF_NCQ)) {
SATA_DEV_F_TCQ) &&
SATA_CTLF_QCMD)) {
if (using_queuing) {
return (rval);
if (synch) {
return (TRAN_ACCEPT);
int rval;
int synch;
return (rval);
case SCMD_WRITE:
case SCMD_WRITE_G1:
case SCMD_WRITE_G5:
case SCMD_WRITE_G4:
#ifndef __lock_lint
SATA_DEV_F_NCQ) &&
SATA_CTLF_NCQ)) {
SATA_DEV_F_TCQ) &&
SATA_CTLF_QCMD)) {
if (using_queuing) {
return (rval);
if (synch) {
return (TRAN_ACCEPT);
int rval;
int synch;
return (rval);
* scmd->satacmd_flags.sata_data_direction default -
case SCMD_READ:
case SCMD_READ_G1:
case SCMD_READ_G5:
case SCMD_READ_G4:
case SCMD_WRITE:
case SCMD_WRITE_G1:
case SCMD_WRITE_G5:
case SCMD_WRITE_G4:
return (rval);
if (synch) {
return (TRAN_ACCEPT);
int rval;
int synch;
return (rval);
return (rval);
if (synch) {
return (TRAN_ACCEPT);
switch (stat) {
case SATA_TRAN_ACCEPTED:
case SATA_TRAN_QUEUE_FULL:
case SATA_TRAN_PORT_ERROR:
* Communication/link with device or general port error
case SATA_TRAN_BUSY:
cmd);
cmd);
TQ_SLEEP) == 0)
return (TRAN_BUSY);
return (TRAN_ACCEPT);
* Extract error LBA from sata_pkt.satapkt_cmd register fields
*lba = 0;
static struct scsi_extended_sense *
return (sense);
int rval;
case SATA_PKT_PORT_ERROR:
case SATA_PKT_DEV_ERROR:
case SATAC_READ_DMA:
case SATAC_READ_DMA_EXT:
case SATAC_READ_DMA_QUEUED:
case SATAC_READ_FPDMA_QUEUED:
case SATAC_WRITE_DMA:
case SATAC_WRITE_DMA_EXT:
case SATAC_WRITE_DMA_QUEUED:
case SATAC_WRITE_FPDMA_QUEUED:
case SATA_PKT_TIMEOUT:
case SATA_PKT_ABORTED:
case SATA_PKT_RESET:
case SATA_PKT_PORT_ERROR:
case SATA_PKT_DEV_ERROR:
case SATA_PKT_TIMEOUT:
case SATA_PKT_ABORTED:
case SATA_PKT_RESET:
#ifndef __lock_lint
return (PAGELENGTH_DAD_MODE_CACHE_SCSI3 +
sizeof (struct mode_page));
#ifndef __lock_lint
*dmod = 0;
return (SATA_FAILURE);
return (SATA_SUCCESS);
wce = 0;
return (SATA_SUCCESS);
if (dra == 0)
return (SATA_FAILURE);
return (SATA_FAILURE);
goto failure;
return (SATA_SUCCESS);
return (SATA_FAILURE);
int parmlen,
int *pagelen,
int *rval,
int *dmod)
*dmod = 0;
return (SATA_FAILURE);
return (SATA_FAILURE);
return (SATA_SUCCESS);
return (SATA_FAILURE);
return (SATA_SUCCESS);
return (SATA_FAILURE);
int rval;
ext_selftest_log, 0);
if (rval == 0) {
int count;
if (index == 0)
goto out;
if (block_num != 0) {
if (rval != 0)
goto out;
entry =
++count) {
--entry;
--index;
sizeof (empty)) == 0)
goto out;
goto out;
if (only_one_block &&
goto out;
switch (status) {
add_sense_code_qual = 0;
if (status != 0) {
if (index < 0) {
if (block_num > 0) {
--block_num;
struct read_log_ext_directory
rval =
&logdir);
goto out;
goto out;
--block_num;
(block_num == 0);
if (rval != 0)
goto out;
index =
out:
sizeof (struct smart_ext_selftest_log));
KM_SLEEP);
if (rval == 0) {
int index;
int count;
if (index == 0)
goto done;
++count) {
goto done;
switch (status) {
if (status != 0) {
if (index < 0) {
index =
done:
int rval;
/* Now get the SMART status w.r.t. threshold exceeded */
switch (rval) {
#if defined(SATA_DEBUG)
temp = 0;
int rval;
return (sizeof (struct smart_data));
return (SATA_FAILURE);
return (SATA_FAILURE);
return (SATA_SUCCESS);
#ifdef SATA_DEBUG
if (sata_hba_list) {
if (sata_hba_list_tail) {
int rval;
DDI_SUCCESS) {
ncport);
KM_SLEEP);
SATA_SUCCESS) {
goto reprobe_cport;
KM_SLEEP);
NULL);
for (npmport = 0;
npmport++) {
0) != DDI_SUCCESS) {
&sata_device);
sizeof (sata_drive_info_t),
KM_SLEEP);
goto reprobe_pmport;
int pmport)
int rval;
return (SATA_FAILURE);
return (SATA_SUCCESS);
return (SATA_SUCCESS);
return (SATA_SUCCESS);
return (SATA_FAILURE);
return (SATA_SUCCESS);
return (SATA_SUCCESS);
return (SATA_SUCCESS);
static dev_info_t *
int rval;
int ncompatible;
int target;
target));
return (NULL);
#ifdef SATA_DEBUG
target);
for (i = 0; i < ncompatible; i++) {
return (NULL);
goto fail;
goto fail;
goto fail;
(void *)cdip));
goto fail;
return (cdip);
return (NULL);
fail:
return (NULL);
int flag)
int prev_device_settings = 0;
int rval;
return (SATA_FAILURE);
return (SATA_SUCCESS);
return (SATA_SUCCESS);
return (SATA_SUCCESS);
return (SATA_SUCCESS);
return (rval);
if (retry) {
goto retry_probe;
return (rval);
else if (sata_write_cache == 0)
goto invalid_address;
goto invalid_address;
goto invalid_address;
goto out;
goto out;
goto out;
SATA_VALID_DEV_TYPE) == 0) {
goto out;
goto out;
NULL ||
goto out;
pmport);
goto out;
goto out;
out:
return (rval);
static dev_info_t *
#ifndef __lock_lint
return (NULL);
return (dip);
int rval;
return (SATA_FAILURE);
goto failure;
if (rval == 0) {
return (SATA_FAILURE);
return (SATA_SUCCESS);
return (SATA_FAILURE);
static sata_drive_info_t *
return (NULL);
return (NULL);
return (NULL);
return (NULL);
return (NULL);
return (NULL);
return (NULL);
int rval;
goto fail_unknown;
SATA_ATAPI_TYPE) &&
goto fail_unknown;
goto fail_unknown;
return (rval);
int valid_version;
#ifdef SATA_DEBUG
valid_version = i;
#ifdef __i386
static uint64_t
return (capacity);
static struct buf *
return (bp);
static sata_pkt_t *
int kmsflag;
return (NULL);
return (spkt);
* If a device is being probed/initialized, there are
int rval;
rval));
return (rval);
&cookie,
&bufsz,
(void) ddi_dma_free_handle(
#ifdef SATA_DEBUG
return (rval);
#ifdef SATA_DEBUG
mbuf_count++;
NULL,
switch (rval) {
case DDI_DMA_PARTIAL_MAP:
(void) ddi_dma_unbind_handle(
(void) ddi_dma_free_handle(
return (DDI_FAILURE);
case DDI_DMA_MAPPED:
return (rval);
&cookie,
return (DDI_SUCCESS);
sizeof (ddi_dma_cookie_t));
sizeof (ddi_dma_cookie_t) *
if ((cur_txfer_len +
return (DDI_SUCCESS);
int rval;
goto fail;
sizeof (sata_id_t));
rval = 0;
fail:
return (rval);
int i, mode;
return (SATA_FAILURE);
if (i < mode) {
goto failure;
return (result);
int cache_op)
char *infop;
goto failure;
switch (cache_op) {
return (rval);
static int32_t
port));
return (port);
static dev_info_t *
int ncport;
int circ;
return (cdip);
int port_state;
case SATA_DTYPE_NONE:
case SATA_DTYPE_UNKNOWN:
case SATA_DTYPE_ATAPINONCD:
case SATA_DTYPE_ATADISK:
case SATA_DTYPE_ATAPICD:
int circ;
static int sata_event_thread_terminating = 0;
static int sata_event_thread_starting = 0;
#ifdef SATA_DEBUG
(void (*)())sata_event_daemon,
#ifdef SATA_DEBUG
pathname[0] = 0;
if (sata_debug_flags == 0)
char *lcp;
static char *err_msg_evnt_1 =
static char *err_msg_evnt_2 =
int linkevent;
goto event_info;
pstats =
pstats =
if (linkevent) {
linkevent = 0;
goto event_info;
if (sata_event_thread_active == 0)
#ifndef __lock_lint
loop:
SATA_EVNT_SKIP) != 0) {
goto loop;
#ifdef SATA_DEBUG
if (sata_event_thread_active != 0) {
goto loop;
int ncport;
NULL);
if ((event_flags &
saddr);
saddr);
saddr);
if (event_flags &
saddr);
saddr);
int rval;
SATA_VALID_DEV_TYPE) == 0) {
SATA_FAILURE) {
SATA_VALID_DEV_TYPE) != 0 &&
int rval;
goto linklost;
NULL);
SATA_VALID_DEV_TYPE) != 0) {
goto done;
#ifdef SATA_DEBUG
if ((cur_time -
done:
if (event_flags != 0) {
int rval;
sizeof (sata_drive_info_t));
int rval;
sizeof (sata_drive_info_t));
if ((cur_time -
&new_sdinfo);
if (event_flags != 0) {
* Explicit port disconnect/connect or physical device
char *finfox;
int cache_op;
return (SATA_FAILURE);
return (SATA_FAILURE);
return (SATA_SUCCESS);
return (SATA_SUCCESS);
return (rval);
int rval;
goto fail;
goto fail;
rval = 0;
goto fail;
fail:
return (rval);
int rval;
#if ! defined(lint)
sizeof (struct smart_data));
goto fail;
sizeof (struct smart_data));
fail:
return (rval);
int rval;
#if ! defined(lint)
sizeof (struct smart_ext_selftest_log));
goto fail;
sizeof (struct smart_ext_selftest_log));
rval = 0;
fail:
return (rval);
int rval;
#if ! defined(lint)
sizeof (struct smart_selftest_log));
goto fail;
sizeof (struct smart_selftest_log));
rval = 0;
fail:
return (rval);
int rval;
goto fail;
rval = 0;
fail:
return (rval);
int rval;
#if ! defined(lint)
sizeof (struct read_log_ext_directory));
goto fail;
sizeof (struct read_log_ext_directory));
rval = 0;
fail:
return (rval);
int hint)
int err;
if (err != 0) {
if (err != 0) {
if (err != 0) {
case SATA_PKT_PORT_ERROR:
case SATA_PKT_DEV_ERROR:
case SATA_PKT_TIMEOUT:
case SATA_PKT_ABORTED:
case SATA_PKT_RESET: