1265236Sken/*- 2265236Sken * Copyright (c) 2009 Yahoo! Inc. 3283990Sslm * Copyright (c) 2011-2015 LSI Corp. 4283990Sslm * Copyright (c) 2013-2015 Avago Technologies 5265236Sken * All rights reserved. 6265236Sken * 7265236Sken * Redistribution and use in source and binary forms, with or without 8265236Sken * modification, are permitted provided that the following conditions 9265236Sken * are met: 10265236Sken * 1. Redistributions of source code must retain the above copyright 11265236Sken * notice, this list of conditions and the following disclaimer. 12265236Sken * 2. Redistributions in binary form must reproduce the above copyright 13265236Sken * notice, this list of conditions and the following disclaimer in the 14265236Sken * documentation and/or other materials provided with the distribution. 15265236Sken * 16265236Sken * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17265236Sken * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18265236Sken * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19265236Sken * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20265236Sken * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21265236Sken * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22265236Sken * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23265236Sken * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24265236Sken * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25265236Sken * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26265236Sken * SUCH DAMAGE. 27265236Sken * 28283990Sslm * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD 29283990Sslm * 30265236Sken * $FreeBSD: releng/10.3/sys/dev/mpr/mprvar.h 283990 2015-06-04 16:27:18Z slm $ 31265236Sken */ 32265236Sken 33265236Sken#ifndef _MPRVAR_H 34265236Sken#define _MPRVAR_H 35265236Sken 36283990Sslm#define MPR_DRIVER_VERSION "09.255.01.00-fbsd" 37265236Sken 38265236Sken#define MPR_DB_MAX_WAIT 2500 39265236Sken 40265236Sken#define MPR_REQ_FRAMES 1024 41265236Sken#define MPR_EVT_REPLY_FRAMES 32 42265236Sken#define MPR_REPLY_FRAMES MPR_REQ_FRAMES 43265236Sken#define MPR_CHAIN_FRAMES 2048 44265236Sken#define MPR_SENSE_LEN SSD_FULL_SIZE 45265236Sken#define MPR_MSI_COUNT 1 46265236Sken#define MPR_SGE64_SIZE 12 47265236Sken#define MPR_SGE32_SIZE 8 48265236Sken#define MPR_SGC_SIZE 8 49265236Sken 50265236Sken#define MPR_FUNCTRACE(sc) \ 51265236Sken mpr_dprint((sc), MPR_TRACE, "%s\n", __func__) 52265236Sken 53283990Sslm#define CAN_SLEEP 1 54283990Sslm#define NO_SLEEP 0 55265236Sken 56265236Sken#define MPR_PERIODIC_DELAY 1 /* 1 second heartbeat/watchdog check */ 57283990Sslm#define MPR_ATA_ID_TIMEOUT 5 /* 5 second timeout for SATA ID cmd */ 58265236Sken 59265236Sken#define IFAULT_IOP_OVER_TEMP_THRESHOLD_EXCEEDED 0x2810 60265236Sken 61265236Sken#define MPR_SCSI_RI_INVALID_FRAME (0x00000002) 62265236Sken#define MPR_STRING_LENGTH 64 63265236Sken 64283990Sslm#define DEFAULT_SPINUP_WAIT 3 /* seconds to wait for spinup */ 65283990Sslm 66265236Sken#include <sys/endian.h> 67265236Sken 68265236Sken/* 69265236Sken * host mapping related macro definitions 70265236Sken */ 71265236Sken#define MPR_MAPTABLE_BAD_IDX 0xFFFFFFFF 72265236Sken#define MPR_DPM_BAD_IDX 0xFFFF 73265236Sken#define MPR_ENCTABLE_BAD_IDX 0xFF 74265236Sken#define MPR_MAX_MISSING_COUNT 0x0F 75265236Sken#define MPR_DEV_RESERVED 0x20000000 76265236Sken#define MPR_MAP_IN_USE 0x10000000 77265236Sken#define MPR_RAID_CHANNEL 1 78265236Sken#define MPR_MAP_BAD_ID 0xFFFFFFFF 79265236Sken 80265236Skentypedef uint8_t u8; 81265236Skentypedef uint16_t u16; 82265236Skentypedef uint32_t u32; 83265236Skentypedef uint64_t u64; 84265236Sken 85265236Sken/** 86265236Sken * struct dev_mapping_table - device mapping information 87265236Sken * @physical_id: SAS address for drives or WWID for RAID volumes 88265236Sken * @device_info: bitfield provides detailed info about the device 89265236Sken * @phy_bits: bitfields indicating controller phys 90265236Sken * @dpm_entry_num: index of this device in device persistent map table 91265236Sken * @dev_handle: device handle for the device pointed by this entry 92265236Sken * @channel: target channel 93265236Sken * @id: target id 94265236Sken * @missing_count: number of times the device not detected by driver 95265236Sken * @hide_flag: Hide this physical disk/not (foreign configuration) 96265236Sken * @init_complete: Whether the start of the day checks completed or not 97265236Sken * @TLR_bits: Turn TLR support on or off 98265236Sken */ 99265236Skenstruct dev_mapping_table { 100265236Sken u64 physical_id; 101265236Sken u32 device_info; 102265236Sken u32 phy_bits; 103265236Sken u16 dpm_entry_num; 104265236Sken u16 dev_handle; 105265236Sken u8 reserved1; 106265236Sken u8 channel; 107265236Sken u16 id; 108265236Sken u8 missing_count; 109265236Sken u8 init_complete; 110265236Sken u8 TLR_bits; 111265236Sken u8 reserved2; 112265236Sken}; 113265236Sken 114265236Sken/** 115265236Sken * struct enc_mapping_table - mapping information about an enclosure 116265236Sken * @enclosure_id: Logical ID of this enclosure 117265236Sken * @start_index: index to the entry in dev_mapping_table 118265236Sken * @phy_bits: bitfields indicating controller phys 119265236Sken * @dpm_entry_num: index of this enclosure in device persistent map table 120265236Sken * @enc_handle: device handle for the enclosure pointed by this entry 121265236Sken * @num_slots: number of slots in the enclosure 122265236Sken * @start_slot: Starting slot id 123265236Sken * @missing_count: number of times the device not detected by driver 124265236Sken * @removal_flag: used to mark the device for removal 125265236Sken * @skip_search: used as a flag to include/exclude enclosure for search 126265236Sken * @init_complete: Whether the start of the day checks completed or not 127265236Sken */ 128265236Skenstruct enc_mapping_table { 129265236Sken u64 enclosure_id; 130265236Sken u32 start_index; 131265236Sken u32 phy_bits; 132265236Sken u16 dpm_entry_num; 133265236Sken u16 enc_handle; 134265236Sken u16 num_slots; 135265236Sken u16 start_slot; 136265236Sken u8 missing_count; 137265236Sken u8 removal_flag; 138265236Sken u8 skip_search; 139265236Sken u8 init_complete; 140265236Sken}; 141265236Sken 142265236Sken/** 143265236Sken * struct map_removal_table - entries to be removed from mapping table 144265236Sken * @dpm_entry_num: index of this device in device persistent map table 145265236Sken * @dev_handle: device handle for the device pointed by this entry 146265236Sken */ 147265236Skenstruct map_removal_table{ 148265236Sken u16 dpm_entry_num; 149265236Sken u16 dev_handle; 150265236Sken}; 151265236Sken 152265236Skentypedef struct mpr_fw_diagnostic_buffer { 153265236Sken size_t size; 154265236Sken uint8_t extended_type; 155265236Sken uint8_t buffer_type; 156265236Sken uint8_t force_release; 157265236Sken uint32_t product_specific[23]; 158265236Sken uint8_t immediate; 159265236Sken uint8_t enabled; 160265236Sken uint8_t valid_data; 161265236Sken uint8_t owned_by_firmware; 162265236Sken uint32_t unique_id; 163265236Sken} mpr_fw_diagnostic_buffer_t; 164265236Sken 165265236Skenstruct mpr_softc; 166265236Skenstruct mpr_command; 167265236Skenstruct mprsas_softc; 168265236Skenunion ccb; 169265236Skenstruct mprsas_target; 170265236Skenstruct mpr_column_map; 171265236Sken 172265236SkenMALLOC_DECLARE(M_MPR); 173265236Sken 174265236Skentypedef void mpr_evt_callback_t(struct mpr_softc *, uintptr_t, 175265236Sken MPI2_EVENT_NOTIFICATION_REPLY *reply); 176265236Skentypedef void mpr_command_callback_t(struct mpr_softc *, struct mpr_command *cm); 177265236Sken 178265236Skenstruct mpr_chain { 179265236Sken TAILQ_ENTRY(mpr_chain) chain_link; 180265236Sken void *chain; 181265236Sken uint64_t chain_busaddr; 182265236Sken}; 183265236Sken 184265236Sken/* 185265236Sken * This needs to be at least 2 to support SMP passthrough. 186265236Sken */ 187265236Sken#define MPR_IOVEC_COUNT 2 188265236Sken 189265236Skenstruct mpr_command { 190265236Sken TAILQ_ENTRY(mpr_command) cm_link; 191265236Sken TAILQ_ENTRY(mpr_command) cm_recovery; 192265236Sken struct mpr_softc *cm_sc; 193265236Sken union ccb *cm_ccb; 194265236Sken void *cm_data; 195265236Sken u_int cm_length; 196265236Sken u_int cm_out_len; 197265236Sken struct uio cm_uio; 198265236Sken struct iovec cm_iovec[MPR_IOVEC_COUNT]; 199265236Sken u_int cm_max_segs; 200265236Sken u_int cm_sglsize; 201265236Sken void *cm_sge; 202265236Sken uint8_t *cm_req; 203265236Sken uint8_t *cm_reply; 204265236Sken uint32_t cm_reply_data; 205265236Sken mpr_command_callback_t *cm_complete; 206265236Sken void *cm_complete_data; 207265236Sken struct mprsas_target *cm_targ; 208265236Sken MPI2_REQUEST_DESCRIPTOR_UNION cm_desc; 209265236Sken u_int cm_lun; 210265236Sken u_int cm_flags; 211265236Sken#define MPR_CM_FLAGS_POLLED (1 << 0) 212265236Sken#define MPR_CM_FLAGS_COMPLETE (1 << 1) 213265236Sken#define MPR_CM_FLAGS_SGE_SIMPLE (1 << 2) 214265236Sken#define MPR_CM_FLAGS_DATAOUT (1 << 3) 215265236Sken#define MPR_CM_FLAGS_DATAIN (1 << 4) 216265236Sken#define MPR_CM_FLAGS_WAKEUP (1 << 5) 217265236Sken#define MPR_CM_FLAGS_USE_UIO (1 << 6) 218265236Sken#define MPR_CM_FLAGS_SMP_PASS (1 << 7) 219265236Sken#define MPR_CM_FLAGS_CHAIN_FAILED (1 << 8) 220265236Sken#define MPR_CM_FLAGS_ERROR_MASK MPR_CM_FLAGS_CHAIN_FAILED 221265236Sken#define MPR_CM_FLAGS_USE_CCB (1 << 9) 222283990Sslm#define MPR_CM_FLAGS_SATA_ID_TIMEOUT (1 << 10) 223265236Sken u_int cm_state; 224265236Sken#define MPR_CM_STATE_FREE 0 225265236Sken#define MPR_CM_STATE_BUSY 1 226265236Sken#define MPR_CM_STATE_TIMEDOUT 2 227265236Sken bus_dmamap_t cm_dmamap; 228265236Sken struct scsi_sense_data *cm_sense; 229283990Sslm TAILQ_HEAD(, mpr_chain) cm_chain_list; 230265236Sken uint32_t cm_req_busaddr; 231265236Sken uint32_t cm_sense_busaddr; 232265236Sken struct callout cm_callout; 233265236Sken}; 234265236Sken 235265236Skenstruct mpr_column_map { 236265236Sken uint16_t dev_handle; 237265236Sken uint8_t phys_disk_num; 238265236Sken}; 239265236Sken 240265236Skenstruct mpr_event_handle { 241265236Sken TAILQ_ENTRY(mpr_event_handle) eh_list; 242265236Sken mpr_evt_callback_t *callback; 243265236Sken void *data; 244265236Sken uint8_t mask[16]; 245265236Sken}; 246265236Sken 247265236Skenstruct mpr_softc { 248265236Sken device_t mpr_dev; 249265236Sken struct cdev *mpr_cdev; 250265236Sken u_int mpr_flags; 251265236Sken#define MPR_FLAGS_INTX (1 << 0) 252265236Sken#define MPR_FLAGS_MSI (1 << 1) 253265236Sken#define MPR_FLAGS_BUSY (1 << 2) 254265236Sken#define MPR_FLAGS_SHUTDOWN (1 << 3) 255265236Sken#define MPR_FLAGS_DIAGRESET (1 << 4) 256265236Sken#define MPR_FLAGS_ATTACH_DONE (1 << 5) 257265236Sken u_int mpr_debug; 258265236Sken u_int disable_msix; 259265236Sken u_int disable_msi; 260265236Sken int tm_cmds_active; 261265236Sken int io_cmds_active; 262265236Sken int io_cmds_highwater; 263265236Sken int chain_free; 264265236Sken int max_chains; 265265236Sken int chain_free_lowwater; 266283990Sslm u_int enable_ssu; 267283990Sslm int spinup_wait_time; 268265236Sken#if __FreeBSD_version >= 900030 269265236Sken uint64_t chain_alloc_fail; 270265236Sken#endif 271265236Sken struct sysctl_ctx_list sysctl_ctx; 272265236Sken struct sysctl_oid *sysctl_tree; 273265236Sken char fw_version[16]; 274265236Sken struct mpr_command *commands; 275265236Sken struct mpr_chain *chains; 276265236Sken struct callout periodic; 277265236Sken 278265236Sken struct mprsas_softc *sassc; 279265236Sken char tmp_string[MPR_STRING_LENGTH]; 280265236Sken TAILQ_HEAD(, mpr_command) req_list; 281265236Sken TAILQ_HEAD(, mpr_command) high_priority_req_list; 282283990Sslm TAILQ_HEAD(, mpr_chain) chain_list; 283265236Sken TAILQ_HEAD(, mpr_command) tm_list; 284265236Sken int replypostindex; 285265236Sken int replyfreeindex; 286265236Sken 287265236Sken struct resource *mpr_regs_resource; 288265236Sken bus_space_handle_t mpr_bhandle; 289265236Sken bus_space_tag_t mpr_btag; 290265236Sken int mpr_regs_rid; 291265236Sken 292265236Sken bus_dma_tag_t mpr_parent_dmat; 293265236Sken bus_dma_tag_t buffer_dmat; 294265236Sken 295265236Sken MPI2_IOC_FACTS_REPLY *facts; 296265236Sken int num_reqs; 297265236Sken int num_replies; 298265236Sken int fqdepth; /* Free queue */ 299265236Sken int pqdepth; /* Post queue */ 300265236Sken 301265236Sken uint8_t event_mask[16]; 302265236Sken TAILQ_HEAD(, mpr_event_handle) event_list; 303283990Sslm struct mpr_event_handle *mpr_log_eh; 304265236Sken 305265236Sken struct mtx mpr_mtx; 306265236Sken struct intr_config_hook mpr_ich; 307265236Sken struct resource *mpr_irq[MPR_MSI_COUNT]; 308265236Sken void *mpr_intrhand[MPR_MSI_COUNT]; 309265236Sken int mpr_irq_rid[MPR_MSI_COUNT]; 310265236Sken 311265236Sken uint8_t *req_frames; 312265236Sken bus_addr_t req_busaddr; 313265236Sken bus_dma_tag_t req_dmat; 314265236Sken bus_dmamap_t req_map; 315265236Sken 316265236Sken uint8_t *reply_frames; 317265236Sken bus_addr_t reply_busaddr; 318265236Sken bus_dma_tag_t reply_dmat; 319265236Sken bus_dmamap_t reply_map; 320265236Sken 321265236Sken struct scsi_sense_data *sense_frames; 322265236Sken bus_addr_t sense_busaddr; 323265236Sken bus_dma_tag_t sense_dmat; 324265236Sken bus_dmamap_t sense_map; 325265236Sken 326265236Sken uint8_t *chain_frames; 327265236Sken bus_addr_t chain_busaddr; 328265236Sken bus_dma_tag_t chain_dmat; 329265236Sken bus_dmamap_t chain_map; 330265236Sken 331265236Sken MPI2_REPLY_DESCRIPTORS_UNION *post_queue; 332265236Sken bus_addr_t post_busaddr; 333265236Sken uint32_t *free_queue; 334265236Sken bus_addr_t free_busaddr; 335265236Sken bus_dma_tag_t queues_dmat; 336265236Sken bus_dmamap_t queues_map; 337265236Sken 338265236Sken uint8_t *fw_diag_buffer; 339265236Sken bus_addr_t fw_diag_busaddr; 340265236Sken bus_dma_tag_t fw_diag_dmat; 341265236Sken bus_dmamap_t fw_diag_map; 342265236Sken 343265236Sken uint8_t ir_firmware; 344265236Sken 345265236Sken /* static config pages */ 346265236Sken Mpi2IOCPage8_t ioc_pg8; 347265236Sken Mpi2IOUnitPage8_t iounit_pg8; 348265236Sken 349265236Sken /* host mapping support */ 350265236Sken struct dev_mapping_table *mapping_table; 351265236Sken struct enc_mapping_table *enclosure_table; 352265236Sken struct map_removal_table *removal_table; 353265236Sken uint8_t *dpm_entry_used; 354265236Sken uint8_t *dpm_flush_entry; 355265236Sken Mpi2DriverMappingPage0_t *dpm_pg0; 356265236Sken uint16_t max_devices; 357265236Sken uint16_t max_enclosures; 358265236Sken uint16_t max_expanders; 359265236Sken uint8_t max_volumes; 360265236Sken uint8_t num_enc_table_entries; 361265236Sken uint8_t num_rsvd_entries; 362265236Sken uint8_t num_channels; 363265236Sken uint16_t max_dpm_entries; 364265236Sken uint8_t is_dpm_enable; 365265236Sken uint8_t track_mapping_events; 366265236Sken uint32_t pending_map_events; 367265236Sken uint8_t mt_full_retry; 368265236Sken uint8_t mt_add_device_failed; 369265236Sken 370265236Sken /* FW diag Buffer List */ 371265236Sken mpr_fw_diagnostic_buffer_t 372265236Sken fw_diag_buffer_list[MPI2_DIAG_BUF_TYPE_COUNT]; 373265236Sken 374265236Sken /* Event Recording IOCTL support */ 375265236Sken uint32_t events_to_record[4]; 376265236Sken mpr_event_entry_t recorded_events[MPR_EVENT_QUEUE_SIZE]; 377265236Sken uint8_t event_index; 378265236Sken uint32_t event_number; 379265236Sken 380265236Sken /* EEDP and TLR support */ 381265236Sken uint8_t eedp_enabled; 382265236Sken uint8_t control_TLR; 383265236Sken 384265236Sken /* Shutdown Event Handler */ 385265236Sken eventhandler_tag shutdown_eh; 386265236Sken 387265236Sken /* To track topo events during reset */ 388265236Sken#define MPR_DIAG_RESET_TIMEOUT 300000 389265236Sken uint8_t wait_for_port_enable; 390265236Sken uint8_t port_enable_complete; 391265236Sken uint8_t msleep_fake_chan; 392265236Sken 393265236Sken /* StartStopUnit command handling at shutdown */ 394265236Sken uint32_t SSU_refcount; 395265236Sken uint8_t SSU_started; 396265236Sken 397265236Sken char exclude_ids[80]; 398265236Sken struct timeval lastfail; 399265236Sken}; 400265236Sken 401265236Skenstruct mpr_config_params { 402265236Sken MPI2_CONFIG_EXT_PAGE_HEADER_UNION hdr; 403265236Sken u_int action; 404265236Sken u_int page_address; /* Attributes, not a phys address */ 405265236Sken u_int status; 406265236Sken void *buffer; 407265236Sken u_int length; 408265236Sken int timeout; 409265236Sken void (*callback)(struct mpr_softc *, struct mpr_config_params *); 410265236Sken void *cbdata; 411265236Sken}; 412265236Sken 413265236Skenstruct scsi_read_capacity_eedp 414265236Sken{ 415265236Sken uint8_t addr[8]; 416265236Sken uint8_t length[4]; 417265236Sken uint8_t protect; 418265236Sken}; 419265236Sken 420265236Skenstatic __inline uint32_t 421265236Skenmpr_regread(struct mpr_softc *sc, uint32_t offset) 422265236Sken{ 423265236Sken return (bus_space_read_4(sc->mpr_btag, sc->mpr_bhandle, offset)); 424265236Sken} 425265236Sken 426265236Skenstatic __inline void 427265236Skenmpr_regwrite(struct mpr_softc *sc, uint32_t offset, uint32_t val) 428265236Sken{ 429265236Sken bus_space_write_4(sc->mpr_btag, sc->mpr_bhandle, offset, val); 430265236Sken} 431265236Sken 432265236Sken/* free_queue must have Little Endian address 433265236Sken * TODO- cm_reply_data is unwanted. We can remove it. 434265236Sken * */ 435265236Skenstatic __inline void 436265236Skenmpr_free_reply(struct mpr_softc *sc, uint32_t busaddr) 437265236Sken{ 438265236Sken if (++sc->replyfreeindex >= sc->fqdepth) 439265236Sken sc->replyfreeindex = 0; 440265236Sken sc->free_queue[sc->replyfreeindex] = htole32(busaddr); 441265236Sken mpr_regwrite(sc, MPI2_REPLY_FREE_HOST_INDEX_OFFSET, sc->replyfreeindex); 442265236Sken} 443265236Sken 444265236Skenstatic __inline struct mpr_chain * 445265236Skenmpr_alloc_chain(struct mpr_softc *sc) 446265236Sken{ 447265236Sken struct mpr_chain *chain; 448265236Sken 449265236Sken if ((chain = TAILQ_FIRST(&sc->chain_list)) != NULL) { 450265236Sken TAILQ_REMOVE(&sc->chain_list, chain, chain_link); 451265236Sken sc->chain_free--; 452265236Sken if (sc->chain_free < sc->chain_free_lowwater) 453265236Sken sc->chain_free_lowwater = sc->chain_free; 454265236Sken } 455265236Sken#if __FreeBSD_version >= 900030 456265236Sken else 457265236Sken sc->chain_alloc_fail++; 458265236Sken#endif 459265236Sken return (chain); 460265236Sken} 461265236Sken 462265236Skenstatic __inline void 463265236Skenmpr_free_chain(struct mpr_softc *sc, struct mpr_chain *chain) 464265236Sken{ 465265236Sken#if 0 466265236Sken bzero(chain->chain, 128); 467265236Sken#endif 468265236Sken sc->chain_free++; 469265236Sken TAILQ_INSERT_TAIL(&sc->chain_list, chain, chain_link); 470265236Sken} 471265236Sken 472265236Skenstatic __inline void 473265236Skenmpr_free_command(struct mpr_softc *sc, struct mpr_command *cm) 474265236Sken{ 475265236Sken struct mpr_chain *chain, *chain_temp; 476265236Sken 477265236Sken if (cm->cm_reply != NULL) 478265236Sken mpr_free_reply(sc, cm->cm_reply_data); 479265236Sken cm->cm_reply = NULL; 480265236Sken cm->cm_flags = 0; 481265236Sken cm->cm_complete = NULL; 482265236Sken cm->cm_complete_data = NULL; 483265236Sken cm->cm_ccb = NULL; 484265236Sken cm->cm_targ = NULL; 485265236Sken cm->cm_max_segs = 0; 486265236Sken cm->cm_lun = 0; 487265236Sken cm->cm_state = MPR_CM_STATE_FREE; 488265236Sken cm->cm_data = NULL; 489265236Sken cm->cm_length = 0; 490265236Sken cm->cm_out_len = 0; 491265236Sken cm->cm_sglsize = 0; 492265236Sken cm->cm_sge = NULL; 493265236Sken 494265236Sken TAILQ_FOREACH_SAFE(chain, &cm->cm_chain_list, chain_link, chain_temp) { 495265236Sken TAILQ_REMOVE(&cm->cm_chain_list, chain, chain_link); 496265236Sken mpr_free_chain(sc, chain); 497265236Sken } 498265236Sken TAILQ_INSERT_TAIL(&sc->req_list, cm, cm_link); 499265236Sken} 500265236Sken 501265236Skenstatic __inline struct mpr_command * 502265236Skenmpr_alloc_command(struct mpr_softc *sc) 503265236Sken{ 504265236Sken struct mpr_command *cm; 505265236Sken 506265236Sken cm = TAILQ_FIRST(&sc->req_list); 507265236Sken if (cm == NULL) 508265236Sken return (NULL); 509265236Sken 510265236Sken TAILQ_REMOVE(&sc->req_list, cm, cm_link); 511265236Sken KASSERT(cm->cm_state == MPR_CM_STATE_FREE, ("mpr: Allocating busy command\n")); 512265236Sken cm->cm_state = MPR_CM_STATE_BUSY; 513265236Sken return (cm); 514265236Sken} 515265236Sken 516265236Skenstatic __inline void 517265236Skenmpr_free_high_priority_command(struct mpr_softc *sc, struct mpr_command *cm) 518265236Sken{ 519265236Sken struct mpr_chain *chain, *chain_temp; 520265236Sken 521265236Sken if (cm->cm_reply != NULL) 522265236Sken mpr_free_reply(sc, cm->cm_reply_data); 523265236Sken cm->cm_reply = NULL; 524265236Sken cm->cm_flags = 0; 525265236Sken cm->cm_complete = NULL; 526265236Sken cm->cm_complete_data = NULL; 527265236Sken cm->cm_ccb = NULL; 528265236Sken cm->cm_targ = NULL; 529265236Sken cm->cm_lun = 0; 530265236Sken cm->cm_state = MPR_CM_STATE_FREE; 531265236Sken TAILQ_FOREACH_SAFE(chain, &cm->cm_chain_list, chain_link, chain_temp) { 532265236Sken TAILQ_REMOVE(&cm->cm_chain_list, chain, chain_link); 533265236Sken mpr_free_chain(sc, chain); 534265236Sken } 535265236Sken TAILQ_INSERT_TAIL(&sc->high_priority_req_list, cm, cm_link); 536265236Sken} 537265236Sken 538265236Skenstatic __inline struct mpr_command * 539265236Skenmpr_alloc_high_priority_command(struct mpr_softc *sc) 540265236Sken{ 541265236Sken struct mpr_command *cm; 542265236Sken 543265236Sken cm = TAILQ_FIRST(&sc->high_priority_req_list); 544265236Sken if (cm == NULL) 545265236Sken return (NULL); 546265236Sken 547265236Sken TAILQ_REMOVE(&sc->high_priority_req_list, cm, cm_link); 548265236Sken KASSERT(cm->cm_state == MPR_CM_STATE_FREE, ("mpr: Allocating busy command\n")); 549265236Sken cm->cm_state = MPR_CM_STATE_BUSY; 550265236Sken return (cm); 551265236Sken} 552265236Sken 553265236Skenstatic __inline void 554265236Skenmpr_lock(struct mpr_softc *sc) 555265236Sken{ 556265236Sken mtx_lock(&sc->mpr_mtx); 557265236Sken} 558265236Sken 559265236Skenstatic __inline void 560265236Skenmpr_unlock(struct mpr_softc *sc) 561265236Sken{ 562265236Sken mtx_unlock(&sc->mpr_mtx); 563265236Sken} 564265236Sken 565265236Sken#define MPR_INFO (1 << 0) /* Basic info */ 566265236Sken#define MPR_FAULT (1 << 1) /* Hardware faults */ 567265236Sken#define MPR_EVENT (1 << 2) /* Event data from the controller */ 568265236Sken#define MPR_LOG (1 << 3) /* Log data from the controller */ 569265236Sken#define MPR_RECOVERY (1 << 4) /* Command error recovery tracing */ 570265236Sken#define MPR_ERROR (1 << 5) /* Parameter errors, programming bugs */ 571265236Sken#define MPR_INIT (1 << 6) /* Things related to system init */ 572265236Sken#define MPR_XINFO (1 << 7) /* More detailed/noisy info */ 573265236Sken#define MPR_USER (1 << 8) /* Trace user-generated commands */ 574265236Sken#define MPR_MAPPING (1 << 9) /* Trace device mappings */ 575265236Sken#define MPR_TRACE (1 << 10) /* Function-by-function trace */ 576265236Sken 577283990Sslm#define MPR_SSU_DISABLE_SSD_DISABLE_HDD 0 578283990Sslm#define MPR_SSU_ENABLE_SSD_DISABLE_HDD 1 579283990Sslm#define MPR_SSU_DISABLE_SSD_ENABLE_HDD 2 580283990Sslm#define MPR_SSU_ENABLE_SSD_ENABLE_HDD 3 581283990Sslm 582265236Sken#define mpr_printf(sc, args...) \ 583265236Sken device_printf((sc)->mpr_dev, ##args) 584265236Sken 585265236Sken#define mpr_vprintf(sc, args...) \ 586265236Skendo { \ 587265236Sken if (bootverbose) \ 588265236Sken mpr_printf(sc, ##args); \ 589265236Sken} while (0) 590265236Sken 591265236Sken#define mpr_dprint(sc, level, msg, args...) \ 592265236Skendo { \ 593265236Sken if ((sc)->mpr_debug & level) \ 594265236Sken device_printf((sc)->mpr_dev, msg, ##args); \ 595265236Sken} while (0) 596265236Sken 597265236Sken#define mpr_dprint_field(sc, level, msg, args...) \ 598265236Skendo { \ 599265236Sken if ((sc)->mpr_debug & level) \ 600265236Sken printf("\t" msg, ##args); \ 601265236Sken} while (0) 602265236Sken 603265236Sken#define MPR_PRINTFIELD_START(sc, tag...) \ 604265236Sken mpr_dprint((sc), MPR_INFO, ##tag); \ 605265236Sken mpr_dprint_field((sc), MPR_INFO, ":\n") 606265236Sken#define MPR_PRINTFIELD_END(sc, tag) \ 607265236Sken mpr_dprint((sc), MPR_INFO, tag "\n") 608265236Sken#define MPR_PRINTFIELD(sc, facts, attr, fmt) \ 609265236Sken mpr_dprint_field((sc), MPR_INFO, #attr ": " #fmt "\n", (facts)->attr) 610265236Sken 611265236Sken#define MPR_EVENTFIELD_START(sc, tag...) \ 612265236Sken mpr_dprint((sc), MPR_EVENT, ##tag); \ 613265236Sken mpr_dprint_field((sc), MPR_EVENT, ":\n") 614265236Sken#define MPR_EVENTFIELD(sc, facts, attr, fmt) \ 615265236Sken mpr_dprint_field((sc), MPR_EVENT, #attr ": " #fmt "\n", (facts)->attr) 616265236Sken 617265236Skenstatic __inline void 618265236Skenmpr_from_u64(uint64_t data, U64 *mpr) 619265236Sken{ 620265236Sken (mpr)->High = htole32((uint32_t)((data) >> 32)); 621265236Sken (mpr)->Low = htole32((uint32_t)((data) & 0xffffffff)); 622265236Sken} 623265236Sken 624265236Skenstatic __inline uint64_t 625265236Skenmpr_to_u64(U64 *data) 626265236Sken{ 627265236Sken return (((uint64_t)le32toh(data->High) << 32) | le32toh(data->Low)); 628265236Sken} 629265236Sken 630265236Skenstatic __inline void 631265236Skenmpr_mask_intr(struct mpr_softc *sc) 632265236Sken{ 633265236Sken uint32_t mask; 634265236Sken 635265236Sken mask = mpr_regread(sc, MPI2_HOST_INTERRUPT_MASK_OFFSET); 636265236Sken mask |= MPI2_HIM_REPLY_INT_MASK; 637265236Sken mpr_regwrite(sc, MPI2_HOST_INTERRUPT_MASK_OFFSET, mask); 638265236Sken} 639265236Sken 640265236Skenstatic __inline void 641265236Skenmpr_unmask_intr(struct mpr_softc *sc) 642265236Sken{ 643265236Sken uint32_t mask; 644265236Sken 645265236Sken mask = mpr_regread(sc, MPI2_HOST_INTERRUPT_MASK_OFFSET); 646265236Sken mask &= ~MPI2_HIM_REPLY_INT_MASK; 647265236Sken mpr_regwrite(sc, MPI2_HOST_INTERRUPT_MASK_OFFSET, mask); 648265236Sken} 649265236Sken 650265236Skenint mpr_pci_setup_interrupts(struct mpr_softc *sc); 651265236Skenint mpr_pci_restore(struct mpr_softc *sc); 652265236Sken 653265236Skenint mpr_attach(struct mpr_softc *sc); 654265236Skenint mpr_free(struct mpr_softc *sc); 655265236Skenvoid mpr_intr(void *); 656265236Skenvoid mpr_intr_msi(void *); 657265236Skenvoid mpr_intr_locked(void *); 658265236Skenint mpr_register_events(struct mpr_softc *, uint8_t *, mpr_evt_callback_t *, 659265236Sken void *, struct mpr_event_handle **); 660265236Skenint mpr_restart(struct mpr_softc *); 661265236Skenint mpr_update_events(struct mpr_softc *, struct mpr_event_handle *, 662265236Sken uint8_t *); 663265236Skenint mpr_deregister_events(struct mpr_softc *, struct mpr_event_handle *); 664265236Skenint mpr_push_sge(struct mpr_command *, MPI2_SGE_SIMPLE64 *, size_t, int); 665265236Skenint mpr_push_ieee_sge(struct mpr_command *, void *, int); 666265236Skenint mpr_add_dmaseg(struct mpr_command *, vm_paddr_t, size_t, u_int, int); 667265236Skenint mpr_attach_sas(struct mpr_softc *sc); 668265236Skenint mpr_detach_sas(struct mpr_softc *sc); 669265236Skenint mpr_read_config_page(struct mpr_softc *, struct mpr_config_params *); 670265236Skenint mpr_write_config_page(struct mpr_softc *, struct mpr_config_params *); 671265236Skenvoid mpr_memaddr_cb(void *, bus_dma_segment_t *, int , int ); 672265236Skenvoid mpr_init_sge(struct mpr_command *cm, void *req, void *sge); 673265236Skenint mpr_attach_user(struct mpr_softc *); 674265236Skenvoid mpr_detach_user(struct mpr_softc *); 675265236Skenvoid mprsas_record_event(struct mpr_softc *sc, 676265236Sken MPI2_EVENT_NOTIFICATION_REPLY *event_reply); 677265236Sken 678265236Skenint mpr_map_command(struct mpr_softc *sc, struct mpr_command *cm); 679265236Skenint mpr_wait_command(struct mpr_softc *sc, struct mpr_command *cm, 680265236Sken int timeout, int sleep_flag); 681265236Skenint mpr_request_polled(struct mpr_softc *sc, struct mpr_command *cm); 682265236Sken 683265236Skenint mpr_config_get_bios_pg3(struct mpr_softc *sc, Mpi2ConfigReply_t 684265236Sken *mpi_reply, Mpi2BiosPage3_t *config_page); 685265236Skenint mpr_config_get_raid_volume_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t 686265236Sken *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 page_address); 687265236Skenint mpr_config_get_ioc_pg8(struct mpr_softc *sc, Mpi2ConfigReply_t *, 688265236Sken Mpi2IOCPage8_t *); 689265236Skenint mpr_config_get_iounit_pg8(struct mpr_softc *sc, 690265236Sken Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage8_t *config_page); 691265236Skenint mpr_config_get_sas_device_pg0(struct mpr_softc *, Mpi2ConfigReply_t *, 692265236Sken Mpi2SasDevicePage0_t *, u32 , u16 ); 693265236Skenint mpr_config_get_dpm_pg0(struct mpr_softc *, Mpi2ConfigReply_t *, 694265236Sken Mpi2DriverMappingPage0_t *, u16 ); 695265236Skenint mpr_config_get_raid_volume_pg1(struct mpr_softc *sc, 696265236Sken Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form, 697265236Sken u16 handle); 698265236Skenint mpr_config_get_volume_wwid(struct mpr_softc *sc, u16 volume_handle, 699265236Sken u64 *wwid); 700265236Skenint mpr_config_get_raid_pd_pg0(struct mpr_softc *sc, 701265236Sken Mpi2ConfigReply_t *mpi_reply, Mpi2RaidPhysDiskPage0_t *config_page, 702265236Sken u32 page_address); 703265236Skenvoid mprsas_ir_shutdown(struct mpr_softc *sc); 704265236Sken 705265236Skenint mpr_reinit(struct mpr_softc *sc); 706265236Skenvoid mprsas_handle_reinit(struct mpr_softc *sc); 707265236Sken 708265236Skenvoid mpr_base_static_config_pages(struct mpr_softc *sc); 709265236Sken 710265236Skenint mpr_mapping_initialize(struct mpr_softc *); 711265236Skenvoid mpr_mapping_topology_change_event(struct mpr_softc *, 712265236Sken Mpi2EventDataSasTopologyChangeList_t *); 713265236Skenint mpr_mapping_is_reinit_required(struct mpr_softc *); 714265236Skenvoid mpr_mapping_free_memory(struct mpr_softc *sc); 715265236Skenint mpr_config_set_dpm_pg0(struct mpr_softc *, Mpi2ConfigReply_t *, 716265236Sken Mpi2DriverMappingPage0_t *, u16 ); 717265236Skenvoid mpr_mapping_exit(struct mpr_softc *); 718265236Skenvoid mpr_mapping_check_devices(struct mpr_softc *, int); 719265236Skenint mpr_mapping_allocate_memory(struct mpr_softc *sc); 720265236Skenunsigned int mpr_mapping_get_sas_id(struct mpr_softc *, uint64_t , u16); 721265236Skenunsigned int mpr_mapping_get_sas_id_from_handle(struct mpr_softc *sc, 722265236Sken u16 handle); 723265236Skenunsigned int mpr_mapping_get_raid_id(struct mpr_softc *sc, u64 wwid, 724265236Sken u16 handle); 725265236Skenunsigned int mpr_mapping_get_raid_id_from_handle(struct mpr_softc *sc, 726265236Sken u16 volHandle); 727265236Skenvoid mpr_mapping_enclosure_dev_status_change_event(struct mpr_softc *, 728265236Sken Mpi2EventDataSasEnclDevStatusChange_t *event_data); 729265236Skenvoid mpr_mapping_ir_config_change_event(struct mpr_softc *sc, 730265236Sken Mpi2EventDataIrConfigChangeList_t *event_data); 731265236Sken 732265236Skenvoid mprsas_evt_handler(struct mpr_softc *sc, uintptr_t data, 733265236Sken MPI2_EVENT_NOTIFICATION_REPLY *event); 734265236Skenvoid mprsas_prepare_remove(struct mprsas_softc *sassc, uint16_t handle); 735265236Skenvoid mprsas_prepare_volume_remove(struct mprsas_softc *sassc, 736265236Sken uint16_t handle); 737265236Skenint mprsas_startup(struct mpr_softc *sc); 738265236Skenstruct mprsas_target * mprsas_find_target_by_handle(struct mprsas_softc *, 739265236Sken int, uint16_t); 740283990Sslmvoid mprsas_realloc_targets(struct mpr_softc *sc, int maxtargets); 741283990Sslmstruct mpr_command * mprsas_alloc_tm(struct mpr_softc *sc); 742283990Sslmvoid mprsas_free_tm(struct mpr_softc *sc, struct mpr_command *tm); 743283990Sslmvoid mprsas_release_simq_reinit(struct mprsas_softc *sassc); 744283990Sslmint mprsas_send_reset(struct mpr_softc *sc, struct mpr_command *tm, 745283990Sslm uint8_t type); 746265236Sken 747265236SkenSYSCTL_DECL(_hw_mpr); 748265236Sken 749265236Sken/* Compatibility shims for different OS versions */ 750265236Sken#if __FreeBSD_version >= 800001 751265236Sken#define mpr_kproc_create(func, farg, proc_ptr, flags, stackpgs, fmtstr, arg) \ 752265236Sken kproc_create(func, farg, proc_ptr, flags, stackpgs, fmtstr, arg) 753265236Sken#define mpr_kproc_exit(arg) kproc_exit(arg) 754265236Sken#else 755265236Sken#define mpr_kproc_create(func, farg, proc_ptr, flags, stackpgs, fmtstr, arg) \ 756265236Sken kthread_create(func, farg, proc_ptr, flags, stackpgs, fmtstr, arg) 757265236Sken#define mpr_kproc_exit(arg) kthread_exit(arg) 758265236Sken#endif 759265236Sken 760265236Sken#if defined(CAM_PRIORITY_XPT) 761265236Sken#define MPR_PRIORITY_XPT CAM_PRIORITY_XPT 762265236Sken#else 763265236Sken#define MPR_PRIORITY_XPT 5 764265236Sken#endif 765265236Sken 766265236Sken#if __FreeBSD_version < 800107 767265236Sken// Prior to FreeBSD-8.0 scp3_flags was not defined. 768265236Sken#define spc3_flags reserved 769265236Sken 770265236Sken#define SPC3_SID_PROTECT 0x01 771265236Sken#define SPC3_SID_3PC 0x08 772265236Sken#define SPC3_SID_TPGS_MASK 0x30 773265236Sken#define SPC3_SID_TPGS_IMPLICIT 0x10 774265236Sken#define SPC3_SID_TPGS_EXPLICIT 0x20 775265236Sken#define SPC3_SID_ACC 0x40 776265236Sken#define SPC3_SID_SCCS 0x80 777265236Sken 778265236Sken#define CAM_PRIORITY_NORMAL CAM_PRIORITY_NONE 779265236Sken#endif 780265236Sken 781265236Sken#endif 782265236Sken 783