pmcs_proto.h revision 978d7443a924cda8208d6a10e72be89383bc7bec
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/*
* This file provides prototype function definitions.
*/
#ifndef _PMCS_PROTO_H
#define _PMCS_PROTO_H
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
PMCS_PRT_DEBUG = 0,
PMCS_PRT_DEBUG1,
PMCS_PRT_DEBUG2,
PMCS_PRT_DEBUG3,
PMCS_PRT_DEBUG_CONFIG,
PMCS_PRT_DEBUG_IPORT,
PMCS_PRT_DEBUG_MAP,
PMCS_PRT_DEBUG_UNDERFLOW,
PMCS_PRT_DEBUG_SCSI_STATUS,
PMCS_PRT_DEBUG_PHY_LOCKING,
PMCS_PRT_DEBUG_DEV_STATE,
PMCS_PRT_DEBUG_DEVEL,
PMCS_PRT_INFO,
PMCS_PRT_WARN,
PMCS_PRT_ERR
} pmcs_prt_level_t;
#define pmcs_prt(pwp, level, phy, tgt, fmt...) { \
int lvl = level; \
if (((pwp->debug_mask & (1 << lvl)) != 0) || \
(lvl > PMCS_PRT_DEBUG_DEVEL)) { \
pmcs_prt_impl(pwp, lvl, phy, tgt, fmt); \
} \
}
/*PRINTFLIKE5*/
void
pmcs_prt_impl(pmcs_hw_t *, pmcs_prt_level_t, pmcs_phy_t *, pmcs_xscsi_t *,
const char *, ...) __KPRINTFLIKE(5);
boolean_t pmcs_assign_device(pmcs_hw_t *, pmcs_xscsi_t *);
void pmcs_remove_device(pmcs_hw_t *, pmcs_phy_t *);
void pmcs_handle_dead_phys(pmcs_hw_t *);
int pmcs_acquire_scratch(pmcs_hw_t *, boolean_t);
void pmcs_release_scratch(pmcs_hw_t *);
/* get a work structure */
pmcwork_t *pmcs_gwork(pmcs_hw_t *, uint32_t, pmcs_phy_t *);
/* put a work structure */
void pmcs_pwork(pmcs_hw_t *, struct pmcwork *);
/* given a tag, find a work structure */
pmcwork_t *pmcs_tag2wp(pmcs_hw_t *, uint32_t, boolean_t);
/*
* Abort function
*/
int pmcs_abort(pmcs_hw_t *, pmcs_phy_t *, uint32_t, int, int);
/*
* SSP Task Management Function
*/
int pmcs_ssp_tmf(pmcs_hw_t *, pmcs_phy_t *, uint8_t, uint32_t, uint64_t,
uint32_t *);
/*
* Abort NCQ function
*/
int pmcs_sata_abort_ncq(pmcs_hw_t *, pmcs_phy_t *);
/*
* Interrupt Functions
*/
void pmcs_general_intr(pmcs_hw_t *);
void pmcs_iodone_intr(pmcs_hw_t *);
void pmcs_event_intr(pmcs_hw_t *);
void pmcs_timed_out(pmcs_hw_t *, uint32_t, const char *);
/*
* Abort handler
*/
int pmcs_abort_handler(pmcs_hw_t *);
/*
* Deregister all expander connected devices
*/
void pmcs_deregister_devices(pmcs_hw_t *, pmcs_phy_t *);
int pmcs_register_device(pmcs_hw_t *, pmcs_phy_t *);
void pmcs_deregister_device(pmcs_hw_t *, pmcs_phy_t *);
/*
* endian transform a data structure
*/
void pmcs_endian_transform(pmcs_hw_t *, void *, void *, const uint8_t *);
/* get the connection rate string */
const char *pmcs_get_rate(unsigned int);
/* get the device type string */
const char *pmcs_get_typename(pmcs_dtype_t pmcs_dtype);
/* get the SAS Task Management function name */
const char *pmcs_tmf2str(int);
/* get the PMC status string */
const char *pmcs_status_str(uint32_t);
/*
* WWN to Byte Array and vice versa conversion
*/
uint64_t pmcs_barray2wwn(uint8_t[8]);
void pmcs_wwn2barray(uint64_t, uint8_t[8]);
/*
* Print f/w version
*/
void pmcs_report_fwversion(pmcs_hw_t *);
/*
* Build a device name.
*/
void pmcs_phy_name(pmcs_hw_t *, pmcs_phy_t *, char *, size_t);
/*
* Find a PHY by wwn
*/
pmcs_phy_t *pmcs_find_phy_by_wwn(pmcs_hw_t *, uint64_t);
/*
* Find a PHY by sas_address
*/
pmcs_phy_t *pmcs_find_phy_by_sas_address(pmcs_hw_t *, pmcs_iport_t *,
pmcs_phy_t *, char *);
/*
* Print out a FIS
*/
void pmcs_fis_dump(pmcs_hw_t *, fis_t);
/*
* Print an IOMB
*/
void pmcs_print_entry(pmcs_hw_t *, int, char *, void *);
void pmcs_spinup_release(pmcs_hw_t *, pmcs_phy_t *phyp);
/*
* Handler for events - can be called from interrupt level or from worker thread
*/
void pmcs_ack_events(pmcs_hw_t *);
/*
* This function does some initial setup and hardware validation
*/
int pmcs_setup(pmcs_hw_t *);
/*
* These functions start and stop the MPI (message passing interface)
*/
int pmcs_start_mpi(pmcs_hw_t *);
int pmcs_stop_mpi(pmcs_hw_t *);
/*
* This function checks firmware revisions against required revisions
* and attempts to flash new firmware (if possible).
*/
int pmcs_firmware_update(pmcs_hw_t *);
/*
* This function runs ECHO commands to test both interrupts and queues
*/
int pmcs_echo_test(pmcs_hw_t *);
/*
* These functions start, reset, and stop the physical chip PHYs
*/
int pmcs_start_phy(pmcs_hw_t *, int, int, int);
int pmcs_start_phys(pmcs_hw_t *);
void pmcs_stop_phy(pmcs_hw_t *, int);
void pmcs_stop_phys(pmcs_hw_t *);
/*
* These functions setup/teardown iport tgtmap
*/
int pmcs_iport_tgtmap_create(pmcs_iport_t *);
int pmcs_iport_tgtmap_destroy(pmcs_iport_t *);
/*
* Utility and wrapper functions for SAS_DIAG_EXECUTE
*/
int pmcs_sas_diag_execute(pmcs_hw_t *, uint32_t, uint32_t, uint8_t);
int pmcs_get_diag_report(pmcs_hw_t *, uint32_t, uint8_t);
int pmcs_clear_diag_counters(pmcs_hw_t *, uint8_t);
/*
* Register Dump (including "internal" registers)
*/
void pmcs_register_dump(pmcs_hw_t *);
void pmcs_iqp_trace(pmcs_hw_t *, uint32_t);
void pmcs_register_dump_int(pmcs_hw_t *);
int pmcs_dump_binary(pmcs_hw_t *, uint32_t *, uint32_t,
uint32_t, caddr_t, uint32_t);
int pmcs_dump_feregs(pmcs_hw_t *, uint32_t *, uint8_t,
caddr_t, uint32_t);
/*
* This function perform a soft reset.
* Hard reset is platform specific.
*/
int pmcs_soft_reset(pmcs_hw_t *, boolean_t);
/*
* This is a hot reset which will attempt reconfiguration after reset.
*/
int pmcs_hot_reset(pmcs_hw_t *);
/*
* Some more reset functions
*/
int pmcs_reset_dev(pmcs_hw_t *, pmcs_phy_t *, uint64_t);
int pmcs_reset_phy(pmcs_hw_t *, pmcs_phy_t *, uint8_t);
/*
* These functions do topology configuration changes
*/
void pmcs_discover(pmcs_hw_t *);
void pmcs_set_changed(pmcs_hw_t *, pmcs_phy_t *, boolean_t, int);
void pmcs_kill_changed(pmcs_hw_t *, pmcs_phy_t *, int);
void pmcs_clear_phy(pmcs_hw_t *, pmcs_phy_t *);
int pmcs_kill_device(pmcs_hw_t *, pmcs_phy_t *);
/*
* Firmware flash function
*/
int pmcs_fw_flash(pmcs_hw_t *, pmcs_fw_hdr_t *, uint32_t);
/*
* Set a new value for the interrupt coalescing timer. If it's being set
* to zero (disabling), then re-enable auto clear if necessary. If it's
* being changed from zero, turn off auto clear if it was on.
*/
typedef enum {
DECREASE_TIMER = 0,
INCREASE_TIMER
} pmcs_coal_timer_adj_t;
void pmcs_check_intr_coal(void *arg);
void pmcs_set_intr_coal_timer(pmcs_hw_t *pwp, pmcs_coal_timer_adj_t adj);
/*
* Misc supporting routines
*/
void pmcs_check_iomb_status(pmcs_hw_t *pwp, uint32_t *iomb);
void pmcs_clear_xp(pmcs_hw_t *, pmcs_xscsi_t *);
void pmcs_create_one_phy_stats(pmcs_iport_t *, pmcs_phy_t *);
int pmcs_run_sata_cmd(pmcs_hw_t *, pmcs_phy_t *, fis_t, uint32_t,
uint32_t, uint32_t);
int pmcs_sata_identify(pmcs_hw_t *, pmcs_phy_t *);
void pmcs_sata_work(pmcs_hw_t *);
boolean_t pmcs_dma_setup(pmcs_hw_t *pwp, ddi_dma_attr_t *dma_attr,
ddi_acc_handle_t *acch, ddi_dma_handle_t *dmah, size_t length,
caddr_t *kvap, uint64_t *dma_addr);
void pmcs_fm_ereport(pmcs_hw_t *pwp, char *detail);
int pmcs_check_dma_handle(ddi_dma_handle_t handle);
int pmcs_check_acc_handle(ddi_acc_handle_t handle);
int pmcs_check_acc_dma_handle(pmcs_hw_t *pwp);
int pmcs_get_nvmd(pmcs_hw_t *pwp, pmcs_nvmd_type_t nvmd_type, uint8_t nvmd,
uint32_t offset, char *buf, uint32_t size_left);
boolean_t pmcs_set_nvmd(pmcs_hw_t *pwp, pmcs_nvmd_type_t nvmd_type,
uint8_t *buf, size_t len);
void pmcs_complete_work_impl(pmcs_hw_t *pwp, pmcwork_t *pwrk, uint32_t *iomb,
size_t amt);
void pmcs_flush_target_queues(pmcs_hw_t *, pmcs_xscsi_t *, uint8_t);
void pmcs_flush_nonio_cmds(pmcs_hw_t *);
boolean_t pmcs_iport_has_targets(pmcs_hw_t *, pmcs_iport_t *);
void pmcs_free_dma_chunklist(pmcs_hw_t *);
void pmcs_dev_state_recovery(pmcs_hw_t *, pmcs_phy_t *);
void pmcs_deregister_device_work(pmcs_hw_t *, pmcs_phy_t *);
int pmcs_send_err_recovery_cmd(pmcs_hw_t *, uint8_t, pmcs_phy_t *,
pmcs_xscsi_t *);
void pmcs_start_ssp_event_recovery(pmcs_hw_t *pwp, pmcwork_t *pwrk,
uint32_t *iomb, size_t amt);
void pmcs_ssp_event_recovery(pmcs_hw_t *);
pmcs_iport_t *pmcs_get_iport_by_wwn(pmcs_hw_t *pwp, uint64_t wwn);
pmcs_phy_t *pmcs_promote_next_phy(pmcs_phy_t *pptr);
void pmcs_rele_iport(pmcs_iport_t *iport);
int pmcs_iport_configure_phys(pmcs_iport_t *iport);
void pmcs_iport_teardown_phys(pmcs_iport_t *iport);
void pmcs_lock_phy(pmcs_phy_t *);
void pmcs_unlock_phy(pmcs_phy_t *);
void pmcs_destroy_target(pmcs_xscsi_t *);
void pmcs_phymap_activate(void *, char *, void **);
void pmcs_phymap_deactivate(void *, char *, void *);
void pmcs_add_phy_to_iport(pmcs_iport_t *, pmcs_phy_t *);
void pmcs_remove_phy_from_iport(pmcs_iport_t *, pmcs_phy_t *);
void pmcs_free_all_phys(pmcs_hw_t *, pmcs_phy_t *);
void pmcs_free_phys(pmcs_hw_t *, pmcs_phy_t *);
int pmcs_phy_constructor(void *, void *, int);
void pmcs_phy_destructor(void *, void *);
void pmcs_inc_phy_ref_count(pmcs_phy_t *);
void pmcs_dec_phy_ref_count(pmcs_phy_t *);
/* Worker thread */
void pmcs_worker(void *);
pmcs_phy_t *pmcs_get_root_phy(pmcs_phy_t *);
pmcs_xscsi_t *pmcs_get_target(pmcs_iport_t *, char *, boolean_t);
void pmcs_fatal_handler(pmcs_hw_t *);
/*
* Schedule device state recovery for this device immediately
*/
void pmcs_start_dev_state_recovery(pmcs_xscsi_t *, pmcs_phy_t *);
/*
* Functions to serialize SMP requests
*/
void pmcs_smp_acquire(pmcs_iport_t *iport);
void pmcs_smp_release(pmcs_iport_t *iport);
/*
* Update attached-port-pm and target-port-pm properties on a PHY
*/
void pmcs_update_phy_pm_props(pmcs_phy_t *, uint64_t, uint64_t, boolean_t);
/*
* Determine whether it's worth retrying enumeration
*/
void pmcs_status_disposition(pmcs_phy_t *, uint32_t);
/*
* Write out firmware event log (if configured to do so) if it's filled up
*/
void pmcs_gather_fwlog(pmcs_hw_t *);
#ifdef __cplusplus
}
#endif
#endif /* _PMCS_PROTO_H */