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