1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. 23 */ 24 /* 25 * This file provides prototype function definitions. 26 */ 27 #ifndef _PMCS_PROTO_H 28 #define _PMCS_PROTO_H 29 #ifdef __cplusplus 30 extern "C" { 31 #endif 32 33 34 typedef enum { 35 PMCS_PRT_DEBUG = 0, 36 PMCS_PRT_DEBUG1, 37 PMCS_PRT_DEBUG2, 38 PMCS_PRT_DEBUG3, 39 PMCS_PRT_DEBUG_CONFIG, 40 PMCS_PRT_DEBUG_IPORT, 41 PMCS_PRT_DEBUG_MAP, 42 PMCS_PRT_DEBUG_UNDERFLOW, 43 PMCS_PRT_DEBUG_SCSI_STATUS, 44 PMCS_PRT_DEBUG_PHY_LOCKING, 45 PMCS_PRT_DEBUG_DEV_STATE, 46 PMCS_PRT_DEBUG_DEVEL, 47 PMCS_PRT_INFO, 48 PMCS_PRT_WARN, 49 PMCS_PRT_ERR 50 } pmcs_prt_level_t; 51 52 #define pmcs_prt(pwp, level, phy, tgt, fmt...) { \ 53 int lvl = level; \ 54 if (((pwp->debug_mask & (1 << lvl)) != 0) || \ 55 (lvl > PMCS_PRT_DEBUG_DEVEL)) { \ 56 pmcs_prt_impl(pwp, lvl, phy, tgt, fmt); \ 57 } \ 58 } 59 60 /*PRINTFLIKE5*/ 61 void 62 pmcs_prt_impl(pmcs_hw_t *, pmcs_prt_level_t, pmcs_phy_t *, pmcs_xscsi_t *, 63 const char *, ...) __KPRINTFLIKE(5); 64 65 boolean_t pmcs_assign_device(pmcs_hw_t *, pmcs_xscsi_t *); 66 void pmcs_remove_device(pmcs_hw_t *, pmcs_phy_t *); 67 void pmcs_handle_dead_phys(pmcs_hw_t *); 68 69 int pmcs_acquire_scratch(pmcs_hw_t *, boolean_t); 70 void pmcs_release_scratch(pmcs_hw_t *); 71 72 /* get a work structure */ 73 pmcwork_t *pmcs_gwork(pmcs_hw_t *, uint32_t, pmcs_phy_t *); 74 75 /* put a work structure */ 76 void pmcs_pwork(pmcs_hw_t *, struct pmcwork *); 77 78 /* given a tag, find a work structure */ 79 pmcwork_t *pmcs_tag2wp(pmcs_hw_t *, uint32_t, boolean_t); 80 81 /* 82 * Abort function 83 */ 84 int pmcs_abort(pmcs_hw_t *, pmcs_phy_t *, uint32_t, int, int); 85 86 /* 87 * SSP Task Management Function 88 */ 89 int pmcs_ssp_tmf(pmcs_hw_t *, pmcs_phy_t *, uint8_t, uint32_t, uint64_t, 90 uint32_t *); 91 92 /* 93 * Abort NCQ function 94 */ 95 int pmcs_sata_abort_ncq(pmcs_hw_t *, pmcs_phy_t *); 96 97 /* 98 * Interrupt Functions 99 */ 100 void pmcs_general_intr(pmcs_hw_t *); 101 void pmcs_iodone_intr(pmcs_hw_t *); 102 void pmcs_event_intr(pmcs_hw_t *); 103 void pmcs_timed_out(pmcs_hw_t *, uint32_t, const char *); 104 105 /* 106 * Abort handler 107 */ 108 int pmcs_abort_handler(pmcs_hw_t *); 109 110 /* 111 * Deregister all expander connected devices 112 */ 113 void pmcs_deregister_devices(pmcs_hw_t *, pmcs_phy_t *); 114 int pmcs_register_device(pmcs_hw_t *, pmcs_phy_t *); 115 void pmcs_deregister_device(pmcs_hw_t *, pmcs_phy_t *); 116 117 /* 118 * endian transform a data structure 119 */ 120 void pmcs_endian_transform(pmcs_hw_t *, void *, void *, const uint8_t *); 121 122 /* get the connection rate string */ 123 const char *pmcs_get_rate(unsigned int); 124 125 /* get the device type string */ 126 const char *pmcs_get_typename(pmcs_dtype_t pmcs_dtype); 127 128 /* get the SAS Task Management function name */ 129 const char *pmcs_tmf2str(int); 130 131 /* get the PMC status string */ 132 const char *pmcs_status_str(uint32_t); 133 134 /* 135 * WWN to Byte Array and vice versa conversion 136 */ 137 uint64_t pmcs_barray2wwn(uint8_t[8]); 138 void pmcs_wwn2barray(uint64_t, uint8_t[8]); 139 140 /* 141 * Print f/w version 142 */ 143 void pmcs_report_fwversion(pmcs_hw_t *); 144 145 /* 146 * Build a device name. 147 */ 148 void pmcs_phy_name(pmcs_hw_t *, pmcs_phy_t *, char *, size_t); 149 150 /* 151 * Find a PHY by wwn 152 */ 153 pmcs_phy_t *pmcs_find_phy_by_wwn(pmcs_hw_t *, uint64_t); 154 155 /* 156 * Find a PHY by sas_address 157 */ 158 pmcs_phy_t *pmcs_find_phy_by_sas_address(pmcs_hw_t *, pmcs_iport_t *, 159 pmcs_phy_t *, char *); 160 161 /* 162 * Print out a FIS 163 */ 164 void pmcs_fis_dump(pmcs_hw_t *, fis_t); 165 166 /* 167 * Print an IOMB 168 */ 169 void pmcs_print_entry(pmcs_hw_t *, int, char *, void *); 170 171 void pmcs_spinup_release(pmcs_hw_t *, pmcs_phy_t *phyp); 172 173 /* 174 * Handler for events - can be called from interrupt level or from worker thread 175 */ 176 void pmcs_ack_events(pmcs_hw_t *); 177 178 /* 179 * This function does some initial setup and hardware validation 180 */ 181 int pmcs_setup(pmcs_hw_t *); 182 183 /* 184 * These functions start and stop the MPI (message passing interface) 185 */ 186 int pmcs_start_mpi(pmcs_hw_t *); 187 int pmcs_stop_mpi(pmcs_hw_t *); 188 189 /* 190 * This function checks firmware revisions against required revisions 191 * and attempts to flash new firmware (if possible). 192 */ 193 int pmcs_firmware_update(pmcs_hw_t *); 194 195 /* 196 * This function runs ECHO commands to test both interrupts and queues 197 */ 198 int pmcs_echo_test(pmcs_hw_t *); 199 200 /* 201 * These functions start, reset, and stop the physical chip PHYs 202 */ 203 int pmcs_start_phy(pmcs_hw_t *, int, int, int); 204 int pmcs_start_phys(pmcs_hw_t *); 205 void pmcs_stop_phy(pmcs_hw_t *, int); 206 void pmcs_stop_phys(pmcs_hw_t *); 207 208 /* 209 * These functions setup/teardown iport tgtmap 210 */ 211 int pmcs_iport_tgtmap_create(pmcs_iport_t *); 212 int pmcs_iport_tgtmap_destroy(pmcs_iport_t *); 213 214 /* 215 * Utility and wrapper functions for SAS_DIAG_EXECUTE 216 */ 217 int pmcs_sas_diag_execute(pmcs_hw_t *, uint32_t, uint32_t, uint8_t); 218 int pmcs_get_diag_report(pmcs_hw_t *, uint32_t, uint8_t); 219 int pmcs_clear_diag_counters(pmcs_hw_t *, uint8_t); 220 221 /* 222 * Register Dump (including "internal" registers) 223 */ 224 void pmcs_register_dump(pmcs_hw_t *); 225 void pmcs_iqp_trace(pmcs_hw_t *, uint32_t); 226 void pmcs_register_dump_int(pmcs_hw_t *); 227 int pmcs_dump_binary(pmcs_hw_t *, uint32_t *, uint32_t, 228 uint32_t, caddr_t, uint32_t); 229 int pmcs_dump_feregs(pmcs_hw_t *, uint32_t *, uint8_t, 230 caddr_t, uint32_t); 231 232 /* 233 * This function perform a soft reset. 234 * Hard reset is platform specific. 235 */ 236 int pmcs_soft_reset(pmcs_hw_t *, boolean_t); 237 238 /* 239 * This is a hot reset which will attempt reconfiguration after reset. 240 */ 241 int pmcs_hot_reset(pmcs_hw_t *); 242 243 /* 244 * Some more reset functions 245 */ 246 int pmcs_reset_dev(pmcs_hw_t *, pmcs_phy_t *, uint64_t); 247 int pmcs_reset_phy(pmcs_hw_t *, pmcs_phy_t *, uint8_t); 248 249 /* 250 * These functions do topology configuration changes 251 */ 252 void pmcs_discover(pmcs_hw_t *); 253 void pmcs_set_changed(pmcs_hw_t *, pmcs_phy_t *, boolean_t, int); 254 void pmcs_kill_changed(pmcs_hw_t *, pmcs_phy_t *, int); 255 void pmcs_clear_phy(pmcs_hw_t *, pmcs_phy_t *); 256 int pmcs_kill_device(pmcs_hw_t *, pmcs_phy_t *); 257 258 /* 259 * Firmware flash function 260 */ 261 int pmcs_fw_flash(pmcs_hw_t *, pmcs_fw_hdr_t *, uint32_t); 262 263 /* 264 * Set a new value for the interrupt coalescing timer. If it's being set 265 * to zero (disabling), then re-enable auto clear if necessary. If it's 266 * being changed from zero, turn off auto clear if it was on. 267 */ 268 typedef enum { 269 DECREASE_TIMER = 0, 270 INCREASE_TIMER 271 } pmcs_coal_timer_adj_t; 272 273 void pmcs_check_intr_coal(void *arg); 274 void pmcs_set_intr_coal_timer(pmcs_hw_t *pwp, pmcs_coal_timer_adj_t adj); 275 276 /* 277 * Misc supporting routines 278 */ 279 void pmcs_check_iomb_status(pmcs_hw_t *pwp, uint32_t *iomb); 280 void pmcs_clear_xp(pmcs_hw_t *, pmcs_xscsi_t *); 281 void pmcs_create_one_phy_stats(pmcs_iport_t *, pmcs_phy_t *); 282 int pmcs_run_sata_cmd(pmcs_hw_t *, pmcs_phy_t *, fis_t, uint32_t, 283 uint32_t, uint32_t); 284 int pmcs_sata_identify(pmcs_hw_t *, pmcs_phy_t *); 285 void pmcs_sata_work(pmcs_hw_t *); 286 boolean_t pmcs_dma_setup(pmcs_hw_t *pwp, ddi_dma_attr_t *dma_attr, 287 ddi_acc_handle_t *acch, ddi_dma_handle_t *dmah, size_t length, 288 caddr_t *kvap, uint64_t *dma_addr); 289 void pmcs_fm_ereport(pmcs_hw_t *pwp, char *detail); 290 int pmcs_check_dma_handle(ddi_dma_handle_t handle); 291 int pmcs_check_acc_handle(ddi_acc_handle_t handle); 292 int pmcs_check_acc_dma_handle(pmcs_hw_t *pwp); 293 int pmcs_get_nvmd(pmcs_hw_t *pwp, pmcs_nvmd_type_t nvmd_type, uint8_t nvmd, 294 uint32_t offset, char *buf, uint32_t size_left); 295 boolean_t pmcs_set_nvmd(pmcs_hw_t *pwp, pmcs_nvmd_type_t nvmd_type, 296 uint8_t *buf, size_t len); 297 void pmcs_complete_work_impl(pmcs_hw_t *pwp, pmcwork_t *pwrk, uint32_t *iomb, 298 size_t amt); 299 void pmcs_flush_target_queues(pmcs_hw_t *, pmcs_xscsi_t *, uint8_t); 300 boolean_t pmcs_iport_has_targets(pmcs_hw_t *, pmcs_iport_t *); 301 void pmcs_free_dma_chunklist(pmcs_hw_t *); 302 void pmcs_dev_state_recovery(pmcs_hw_t *, pmcs_phy_t *); 303 void pmcs_deregister_device_work(pmcs_hw_t *, pmcs_phy_t *); 304 int pmcs_send_err_recovery_cmd(pmcs_hw_t *, uint8_t, pmcs_phy_t *, 305 pmcs_xscsi_t *); 306 void pmcs_start_ssp_event_recovery(pmcs_hw_t *pwp, pmcwork_t *pwrk, 307 uint32_t *iomb, size_t amt); 308 void pmcs_ssp_event_recovery(pmcs_hw_t *); 309 310 pmcs_iport_t *pmcs_get_iport_by_wwn(pmcs_hw_t *pwp, uint64_t wwn); 311 pmcs_phy_t *pmcs_promote_next_phy(pmcs_phy_t *pptr); 312 void pmcs_hold_iport(pmcs_iport_t *iport); 313 void pmcs_rele_iport(pmcs_iport_t *iport); 314 int pmcs_iport_configure_phys(pmcs_iport_t *iport); 315 void pmcs_iport_teardown_phys(pmcs_iport_t *iport); 316 317 void pmcs_lock_phy(pmcs_phy_t *); 318 void pmcs_unlock_phy(pmcs_phy_t *); 319 320 void pmcs_destroy_target(pmcs_xscsi_t *); 321 void pmcs_phymap_activate(void *, char *, void **); 322 void pmcs_phymap_deactivate(void *, char *, void *); 323 void pmcs_add_phy_to_iport(pmcs_iport_t *, pmcs_phy_t *); 324 void pmcs_remove_phy_from_iport(pmcs_iport_t *, pmcs_phy_t *); 325 void pmcs_free_all_phys(pmcs_hw_t *, pmcs_phy_t *); 326 void pmcs_free_phys(pmcs_hw_t *, pmcs_phy_t *); 327 328 int pmcs_phy_constructor(void *, void *, int); 329 void pmcs_phy_destructor(void *, void *); 330 331 void pmcs_inc_phy_ref_count(pmcs_phy_t *); 332 void pmcs_dec_phy_ref_count(pmcs_phy_t *); 333 334 /* Worker thread */ 335 void pmcs_worker(void *); 336 337 pmcs_phy_t *pmcs_get_root_phy(pmcs_phy_t *); 338 pmcs_xscsi_t *pmcs_get_target(pmcs_iport_t *, char *, boolean_t); 339 340 void pmcs_fatal_handler(pmcs_hw_t *); 341 342 /* 343 * Schedule device state recovery for this device immediately 344 */ 345 void pmcs_start_dev_state_recovery(pmcs_xscsi_t *, pmcs_phy_t *); 346 347 /* 348 * Functions to serialize SMP requests 349 */ 350 void pmcs_smp_acquire(pmcs_iport_t *iport); 351 void pmcs_smp_release(pmcs_iport_t *iport); 352 353 /* 354 * Update attached-port-pm and target-port-pm properties on a PHY 355 */ 356 void pmcs_update_phy_pm_props(pmcs_phy_t *, uint64_t, uint64_t, boolean_t); 357 358 /* 359 * Determine whether it's worth retrying enumeration 360 */ 361 void pmcs_status_disposition(pmcs_phy_t *, uint32_t); 362 363 /* 364 * Write out firmware event log (if configured to do so) if it's filled up 365 */ 366 void pmcs_gather_fwlog(pmcs_hw_t *); 367 368 #ifdef __cplusplus 369 } 370 #endif 371 #endif /* _PMCS_PROTO_H */ 372