1*4c06356bSdh /* 2*4c06356bSdh * CDDL HEADER START 3*4c06356bSdh * 4*4c06356bSdh * The contents of this file are subject to the terms of the 5*4c06356bSdh * Common Development and Distribution License (the "License"). 6*4c06356bSdh * You may not use this file except in compliance with the License. 7*4c06356bSdh * 8*4c06356bSdh * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*4c06356bSdh * or http://www.opensolaris.org/os/licensing. 10*4c06356bSdh * See the License for the specific language governing permissions 11*4c06356bSdh * and limitations under the License. 12*4c06356bSdh * 13*4c06356bSdh * When distributing Covered Code, include this CDDL HEADER in each 14*4c06356bSdh * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*4c06356bSdh * If applicable, add the following below this CDDL HEADER, with the 16*4c06356bSdh * fields enclosed by brackets "[]" replaced with your own identifying 17*4c06356bSdh * information: Portions Copyright [yyyy] [name of copyright owner] 18*4c06356bSdh * 19*4c06356bSdh * CDDL HEADER END 20*4c06356bSdh * 21*4c06356bSdh * 22*4c06356bSdh * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23*4c06356bSdh * Use is subject to license terms. 24*4c06356bSdh */ 25*4c06356bSdh #ifndef _PMCS_DEF_H 26*4c06356bSdh #define _PMCS_DEF_H 27*4c06356bSdh #ifdef __cplusplus 28*4c06356bSdh extern "C" { 29*4c06356bSdh #endif 30*4c06356bSdh 31*4c06356bSdh typedef enum { 32*4c06356bSdh NOTHING, /* nothing connected here */ 33*4c06356bSdh SATA, /* SATA connection */ 34*4c06356bSdh SAS, /* direct or indirect SAS connection */ 35*4c06356bSdh EXPANDER, /* connection to an expander */ 36*4c06356bSdh NEW /* Brand new device (pending state) */ 37*4c06356bSdh } pmcs_dtype_t; 38*4c06356bSdh 39*4c06356bSdh /* 40*4c06356bSdh * This structure defines a PHY device that represents what we 41*4c06356bSdh * are connected to. 42*4c06356bSdh * 43*4c06356bSdh * The eight real physical PHYs that are in the PMC8X6G are represented 44*4c06356bSdh * as an array of eight of these structures which define what these 45*4c06356bSdh * real PHYs are connected to. 46*4c06356bSdh * 47*4c06356bSdh * Depending upon what is actually connected to each PHY, the 48*4c06356bSdh * type set will define what we're connected to. If it is 49*4c06356bSdh * a direct SATA connection, the phy will describe a SATA endpoint 50*4c06356bSdh * If it is a direct SAS connection, it will describe a SAS 51*4c06356bSdh * endpoint. 52*4c06356bSdh * 53*4c06356bSdh * If it is an EXPANDER, this will describe the edge of an expander. 54*4c06356bSdh * As we perform discovery on what is in an EXPANDER we define an 55*4c06356bSdh * additional list of phys that represent what the Expander is connected to. 56*4c06356bSdh */ 57*4c06356bSdh #define PMCS_HW_MIN_LINK_RATE SAS_LINK_RATE_1_5GBIT 58*4c06356bSdh #define PMCS_HW_MAX_LINK_RATE SAS_LINK_RATE_6GBIT 59*4c06356bSdh 60*4c06356bSdh #define PMCS_INVALID_DEVICE_ID 0xffffffff 61*4c06356bSdh 62*4c06356bSdh struct pmcs_phy { 63*4c06356bSdh pmcs_phy_t *sibling; /* sibling phy */ 64*4c06356bSdh pmcs_phy_t *parent; /* parent phy */ 65*4c06356bSdh pmcs_phy_t *children; /* head of list of children */ 66*4c06356bSdh pmcs_phy_t *dead_next; /* dead PHY list link */ 67*4c06356bSdh list_node_t list_node; /* list element */ 68*4c06356bSdh uint32_t device_id; /* PMC8X6G device handle */ 69*4c06356bSdh uint32_t 70*4c06356bSdh ncphy : 8, /* # of contained phys for expander */ 71*4c06356bSdh hw_event_ack : 24; /* XXX: first level phy event acked */ 72*4c06356bSdh uint8_t phynum; /* phy number on parent expander */ 73*4c06356bSdh uint8_t width; /* how many phys wide */ 74*4c06356bSdh uint8_t ds_recovery_retries; /* # error retry attempts */ 75*4c06356bSdh pmcs_dtype_t dtype; /* current dtype of the phy */ 76*4c06356bSdh pmcs_dtype_t pend_dtype; /* new dtype (pending change) */ 77*4c06356bSdh uint32_t 78*4c06356bSdh level : 8, /* level in expander tree */ 79*4c06356bSdh tolerates_sas2 : 1, /* tolerates SAS2 SMP */ 80*4c06356bSdh spinup_hold : 1, /* spinup hold needs releasing */ 81*4c06356bSdh atdt : 3, /* attached device type */ 82*4c06356bSdh portid : 4, /* PMC8X6G port context */ 83*4c06356bSdh link_rate : 4, /* current supported speeds */ 84*4c06356bSdh valid_device_id : 1, /* device id is valid */ 85*4c06356bSdh abort_sent : 1, /* we've sent an abort */ 86*4c06356bSdh abort_pending : 1, /* we have an abort pending */ 87*4c06356bSdh need_rl_ext : 1, /* need SATA RL_EXT recocvery */ 88*4c06356bSdh subsidiary : 1, /* this is part of a wide phy */ 89*4c06356bSdh configured : 1, /* is configured */ 90*4c06356bSdh dead : 1, /* dead */ 91*4c06356bSdh changed : 1; /* this phy is changing */ 92*4c06356bSdh clock_t config_stop; /* When config attempts will stop */ 93*4c06356bSdh hrtime_t abort_all_start; 94*4c06356bSdh kcondvar_t abort_all_cv; /* Wait for ABORT_ALL completion */ 95*4c06356bSdh kmutex_t phy_lock; 96*4c06356bSdh volatile uint32_t ref_count; /* Targets & work on this PHY */ 97*4c06356bSdh uint8_t sas_address[8]; /* SAS address for this PHY */ 98*4c06356bSdh struct { 99*4c06356bSdh uint32_t 100*4c06356bSdh prog_min_rate :4, 101*4c06356bSdh hw_min_rate :4, 102*4c06356bSdh prog_max_rate :4, 103*4c06356bSdh hw_max_rate :4, 104*4c06356bSdh reserved :16; 105*4c06356bSdh } state; 106*4c06356bSdh char path[32]; /* path name for this phy */ 107*4c06356bSdh pmcs_hw_t *pwp; /* back ptr to hba struct */ 108*4c06356bSdh pmcs_iport_t *iport; /* back ptr to the iport handle */ 109*4c06356bSdh pmcs_xscsi_t *target; /* back ptr to current target */ 110*4c06356bSdh kstat_t *phy_stats; /* kstats for this phy */ 111*4c06356bSdh }; 112*4c06356bSdh 113*4c06356bSdh /* maximum number of ds recovery retries (ds_recovery_retries) */ 114*4c06356bSdh #define PMCS_MAX_DS_RECOVERY_RETRIES 4 115*4c06356bSdh 116*4c06356bSdh 117*4c06356bSdh /* 118*4c06356bSdh * Inbound and Outbound Queue Related Definitions. 119*4c06356bSdh * 120*4c06356bSdh * The PMC8X6G has a programmable number of inbound and outbound circular 121*4c06356bSdh * queues for use in message passing between the host and the PMC8X6G 122*4c06356bSdh * (up to 64 queues for the Rev C Chip). This driver does not use all 123*4c06356bSdh * possible queues. 124*4c06356bSdh * 125*4c06356bSdh * Each Queue is given 4K of consistent memory and we set a 64 byte size for 126*4c06356bSdh * the queue entry size (this gives us 256 queue entries per queue). 127*4c06356bSdh * 128*4c06356bSdh * This allocation then continues up a further PMCS_SCRATCH_SIZE bytes 129*4c06356bSdh * that the driver uses as a temporary scratch area for things like 130*4c06356bSdh * SMP discovery. 131*4c06356bSdh * 132*4c06356bSdh * This control area looks like this: 133*4c06356bSdh * 134*4c06356bSdh * Offset What 135*4c06356bSdh * ------------------------------------------------ 136*4c06356bSdh * 0 IQ 0 Consumer Index 137*4c06356bSdh * 4 IQ 1 Consumer Index 138*4c06356bSdh * 8..255 ... 139*4c06356bSdh * 252..255 IQ 63 Consumer Index 140*4c06356bSdh * 256 OQ 0 Producer Index 141*4c06356bSdh * 260 OQ 1 Producer Index 142*4c06356bSdh * 264..259 .... 143*4c06356bSdh * 508..511 OQ 63 Producer Index 144*4c06356bSdh * 512..512+PMCS_SCRATCH_SIZE-1 Scratch area. 145*4c06356bSdh */ 146*4c06356bSdh #define IQCI_BASE_OFFSET 0 147*4c06356bSdh #define IQ_OFFSET(qnum) (IQCI_BASE_OFFSET + (qnum << 2)) 148*4c06356bSdh #define OQPI_BASE_OFFSET 256 149*4c06356bSdh #define OQ_OFFSET(qnum) (OQPI_BASE_OFFSET + (qnum << 2)) 150*4c06356bSdh 151*4c06356bSdh /* 152*4c06356bSdh * Work related structures. Each one of these structures is paired 153*4c06356bSdh * with *any* command that is fed to the PMC8X6G via one of the 154*4c06356bSdh * Inbound Queues. The work structure has a tag to compare with 155*4c06356bSdh * the message that comes back out of an Outbound Queue. The 156*4c06356bSdh * work structure also points to the phy which this command is 157*4c06356bSdh * tied to. It also has a pointer a callback function (if defined). 158*4c06356bSdh * See that TAG Architecture below for the various kinds of 159*4c06356bSdh * dispositions of a work structure. 160*4c06356bSdh */ 161*4c06356bSdh 162*4c06356bSdh /* 163*4c06356bSdh * Work Structure States 164*4c06356bSdh * 165*4c06356bSdh * NIL -> READY 166*4c06356bSdh * READY -> NIL 167*4c06356bSdh * READY -> ONCHIP 168*4c06356bSdh * ONCHIP -> INTR 169*4c06356bSdh * INTR -> READY 170*4c06356bSdh * INTR -> NIL 171*4c06356bSdh * INTR -> ABORTED 172*4c06356bSdh * INTR -> TIMED_OUT 173*4c06356bSdh * ABORTED -> NIL 174*4c06356bSdh * TIMED_OUT -> NIL 175*4c06356bSdh */ 176*4c06356bSdh typedef enum { 177*4c06356bSdh PMCS_WORK_STATE_NIL = 0, 178*4c06356bSdh PMCS_WORK_STATE_READY, 179*4c06356bSdh PMCS_WORK_STATE_ONCHIP, 180*4c06356bSdh PMCS_WORK_STATE_INTR, 181*4c06356bSdh PMCS_WORK_STATE_IOCOMPQ, 182*4c06356bSdh PMCS_WORK_STATE_ABORTED, 183*4c06356bSdh PMCS_WORK_STATE_TIMED_OUT 184*4c06356bSdh } pmcs_work_state_t; 185*4c06356bSdh 186*4c06356bSdh struct pmcwork { 187*4c06356bSdh STAILQ_ENTRY(pmcwork) next; 188*4c06356bSdh kmutex_t lock; 189*4c06356bSdh kcondvar_t sleep_cv; 190*4c06356bSdh void *ptr; /* linkage or callback function */ 191*4c06356bSdh void *arg; /* command specific data */ 192*4c06356bSdh pmcs_phy_t *phy; /* phy who owns this command */ 193*4c06356bSdh pmcs_xscsi_t *xp; /* Back pointer to xscsi struct */ 194*4c06356bSdh volatile uint32_t htag; /* tag for this structure */ 195*4c06356bSdh uint32_t 196*4c06356bSdh timer : 27, 197*4c06356bSdh onwire : 1, 198*4c06356bSdh dead : 1, 199*4c06356bSdh state : 3; 200*4c06356bSdh hrtime_t start; /* timestamp start */ 201*4c06356bSdh uint32_t ssp_event; /* ssp event */ 202*4c06356bSdh pmcs_dtype_t dtype; /* stash, incase phy gets cleared */ 203*4c06356bSdh 204*4c06356bSdh /* DEBUG-only fields from here on */ 205*4c06356bSdh void *last_ptr; 206*4c06356bSdh void *last_arg; 207*4c06356bSdh pmcs_phy_t *last_phy; 208*4c06356bSdh pmcs_xscsi_t *last_xp; 209*4c06356bSdh uint32_t last_htag; 210*4c06356bSdh pmcs_work_state_t last_state; 211*4c06356bSdh hrtime_t finish; 212*4c06356bSdh }; 213*4c06356bSdh 214*4c06356bSdh #define PMCS_REC_EVENT 0xffffffff /* event recovery */ 215*4c06356bSdh 216*4c06356bSdh /* 217*4c06356bSdh * This structure defines a PMC-Sierra defined firmware header. 218*4c06356bSdh */ 219*4c06356bSdh #pragma pack(4) 220*4c06356bSdh typedef struct { 221*4c06356bSdh char vendor_id[8]; 222*4c06356bSdh uint8_t product_id; 223*4c06356bSdh uint8_t hwrev; 224*4c06356bSdh uint8_t destination_partition; 225*4c06356bSdh uint8_t reserved0; 226*4c06356bSdh uint8_t fwrev[4]; 227*4c06356bSdh uint32_t firmware_length; 228*4c06356bSdh uint32_t crc; 229*4c06356bSdh uint32_t start_address; 230*4c06356bSdh uint8_t data[]; 231*4c06356bSdh } pmcs_fw_hdr_t; 232*4c06356bSdh #pragma pack() 233*4c06356bSdh 234*4c06356bSdh /* 235*4c06356bSdh * Offlevel work as a bit pattern. 236*4c06356bSdh */ 237*4c06356bSdh #define PMCS_WORK_DISCOVER 0 238*4c06356bSdh #define PMCS_WORK_REM_DEVICES 2 239*4c06356bSdh #define PMCS_WORK_ABORT_HANDLE 3 240*4c06356bSdh #define PMCS_WORK_SPINUP_RELEASE 4 241*4c06356bSdh #define PMCS_WORK_SAS_HW_ACK 5 242*4c06356bSdh #define PMCS_WORK_SATA_RUN 6 243*4c06356bSdh #define PMCS_WORK_RUN_QUEUES 7 244*4c06356bSdh #define PMCS_WORK_ADD_DMA_CHUNKS 8 245*4c06356bSdh #define PMCS_WORK_DS_ERR_RECOVERY 9 246*4c06356bSdh #define PMCS_WORK_SSP_EVT_RECOVERY 10 247*4c06356bSdh 248*4c06356bSdh /* 249*4c06356bSdh * The actual values as they appear in work_flags 250*4c06356bSdh */ 251*4c06356bSdh #define PMCS_WORK_FLAG_DISCOVER (1 << 0) 252*4c06356bSdh #define PMCS_WORK_FLAG_REM_DEVICES (1 << 2) 253*4c06356bSdh #define PMCS_WORK_FLAG_ABORT_HANDLE (1 << 3) 254*4c06356bSdh #define PMCS_WORK_FLAG_SPINUP_RELEASE (1 << 4) 255*4c06356bSdh #define PMCS_WORK_FLAG_SAS_HW_ACK (1 << 5) 256*4c06356bSdh #define PMCS_WORK_FLAG_SATA_RUN (1 << 6) 257*4c06356bSdh #define PMCS_WORK_FLAG_RUN_QUEUES (1 << 7) 258*4c06356bSdh #define PMCS_WORK_FLAG_ADD_DMA_CHUNKS (1 << 8) 259*4c06356bSdh #define PMCS_WORK_FLAG_DS_ERR_RECOVERY (1 << 9) 260*4c06356bSdh #define PMCS_WORK_FLAG_SSP_EVT_RECOVERY (1 << 10) 261*4c06356bSdh 262*4c06356bSdh /* 263*4c06356bSdh * This structure is used by this function to test MPI (and interrupts) 264*4c06356bSdh * after MPI has been started to make sure it's working reliably. 265*4c06356bSdh */ 266*4c06356bSdh typedef struct { 267*4c06356bSdh uint32_t signature; 268*4c06356bSdh uint32_t count; 269*4c06356bSdh uint32_t *ptr; 270*4c06356bSdh } echo_test_t; 271*4c06356bSdh #define ECHO_SIGNATURE 0xbebebeef 272*4c06356bSdh 273*4c06356bSdh /* 274*4c06356bSdh * Tag Architecture. The PMC has 32 bit tags for MPI messages. 275*4c06356bSdh * We use this tag this way. 276*4c06356bSdh * 277*4c06356bSdh * bits what 278*4c06356bSdh * ------------------------ 279*4c06356bSdh * 31 done bit 280*4c06356bSdh * 30..28 tag type 281*4c06356bSdh * 27..12 rolling serial number 282*4c06356bSdh * 11..0 index into work area to get pmcwork structure 283*4c06356bSdh * 284*4c06356bSdh * A tag type of NONE means that nobody is waiting on any results, 285*4c06356bSdh * so the interrupt code frees the work structure that has this 286*4c06356bSdh * tag. 287*4c06356bSdh * 288*4c06356bSdh * A tag type of CBACK means that the the interrupt handler 289*4c06356bSdh * takes the tag 'arg' in the work structure to be a callback 290*4c06356bSdh * function pointer (see pmcs_cb_t). The callee is responsible 291*4c06356bSdh * for freeing the work structure that has this tag. 292*4c06356bSdh * 293*4c06356bSdh * A tag type of WAIT means that the issuer of the work needs 294*4c06356bSdh * be woken up from interrupt level when the command completes 295*4c06356bSdh * (or times out). If work structure tag 'arg' is non-null, 296*4c06356bSdh * up to 2*PMCS_QENTRY_SIZE bits of data from the Outbound Queue 297*4c06356bSdh * entry may be copied to the area pointed to by 'arg'. This 298*4c06356bSdh * allows issuers to get directly at the results of the command 299*4c06356bSdh * they issed. The synchronization point for the issuer and the 300*4c06356bSdh * interrupt code for command done notification is the setting 301*4c06356bSdh * of the 'DONE' bit in the tag as stored in the work structure. 302*4c06356bSdh */ 303*4c06356bSdh #define PMCS_TAG_TYPE_FREE 0 304*4c06356bSdh #define PMCS_TAG_TYPE_NONE 1 305*4c06356bSdh #define PMCS_TAG_TYPE_CBACK 2 306*4c06356bSdh #define PMCS_TAG_TYPE_WAIT 3 307*4c06356bSdh #define PMCS_TAG_TYPE_SHIFT 28 308*4c06356bSdh #define PMCS_TAG_SERNO_SHIFT 12 309*4c06356bSdh #define PMCS_TAG_INDEX_SHIFT 0 310*4c06356bSdh #define PMCS_TAG_TYPE_MASK 0x70000000 311*4c06356bSdh #define PMCS_TAG_DONE 0x80000000 312*4c06356bSdh #define PMCS_TAG_SERNO_MASK 0x0ffff000 313*4c06356bSdh #define PMCS_TAG_INDEX_MASK 0x00000fff 314*4c06356bSdh #define PMCS_TAG_TYPE(x) \ 315*4c06356bSdh (((x) & PMCS_TAG_TYPE_MASK) >> PMCS_TAG_TYPE_SHIFT) 316*4c06356bSdh #define PMCS_TAG_SERNO(x) \ 317*4c06356bSdh (((x) & PMCS_TAG_SERNO_MASK) >> PMCS_TAG_SERNO_SHIFT) 318*4c06356bSdh #define PMCS_TAG_INDEX(x) \ 319*4c06356bSdh (((x) & PMCS_TAG_INDEX_MASK) >> PMCS_TAG_INDEX_SHIFT) 320*4c06356bSdh #define PMCS_TAG_FREE 0 321*4c06356bSdh #define PMCS_COMMAND_DONE(x) \ 322*4c06356bSdh (((x)->htag == PMCS_TAG_FREE) || (((x)->htag & PMCS_TAG_DONE) != 0)) 323*4c06356bSdh #define PMCS_COMMAND_ACTIVE(x) \ 324*4c06356bSdh ((x)->htag != PMCS_TAG_FREE && (x)->state == PMCS_WORK_STATE_ONCHIP) 325*4c06356bSdh 326*4c06356bSdh /* 327*4c06356bSdh * Miscellaneous Definitions 328*4c06356bSdh */ 329*4c06356bSdh #define CLEAN_MESSAGE(m, x) { \ 330*4c06356bSdh int _j = x; \ 331*4c06356bSdh while (_j < PMCS_MSG_SIZE) { \ 332*4c06356bSdh m[_j++] = 0; \ 333*4c06356bSdh } \ 334*4c06356bSdh } 335*4c06356bSdh 336*4c06356bSdh #define COPY_MESSAGE(t, f, a) { \ 337*4c06356bSdh int _j; \ 338*4c06356bSdh for (_j = 0; _j < a; _j++) { \ 339*4c06356bSdh t[_j] = f[_j]; \ 340*4c06356bSdh } \ 341*4c06356bSdh while (_j < PMCS_MSG_SIZE) { \ 342*4c06356bSdh t[_j++] = 0; \ 343*4c06356bSdh } \ 344*4c06356bSdh } 345*4c06356bSdh 346*4c06356bSdh #define PMCS_PHY_ADDRESSABLE(pp) \ 347*4c06356bSdh ((pp)->level == 0 && (pp)->dtype == SATA && \ 348*4c06356bSdh ((pp)->sas_address[0] >> 4) != 5) 349*4c06356bSdh 350*4c06356bSdh #define RESTART_DISCOVERY(pwp) \ 351*4c06356bSdh ASSERT(!mutex_owned(&pwp->config_lock)); \ 352*4c06356bSdh mutex_enter(&pwp->config_lock); \ 353*4c06356bSdh pwp->config_changed = B_TRUE; \ 354*4c06356bSdh mutex_exit(&pwp->config_lock); \ 355*4c06356bSdh SCHEDULE_WORK(pwp, PMCS_WORK_DISCOVER); 356*4c06356bSdh 357*4c06356bSdh #define RESTART_DISCOVERY_LOCKED(pwp) \ 358*4c06356bSdh ASSERT(mutex_owned(&pwp->config_lock)); \ 359*4c06356bSdh pwp->config_changed = B_TRUE; \ 360*4c06356bSdh SCHEDULE_WORK(pwp, PMCS_WORK_DISCOVER); 361*4c06356bSdh 362*4c06356bSdh #define PHY_CHANGED(pwp, p) \ 363*4c06356bSdh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, "%s changed in %s line %d", \ 364*4c06356bSdh p->path, __func__, __LINE__); \ 365*4c06356bSdh p->changed = 1 366*4c06356bSdh 367*4c06356bSdh #define PHY_CHANGED_AT_LOCATION(pwp, p, func, line) \ 368*4c06356bSdh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, "%s changed in %s line %d", \ 369*4c06356bSdh p->path, func, line); \ 370*4c06356bSdh p->changed = 1 371*4c06356bSdh 372*4c06356bSdh #define PHY_TYPE(pptr) \ 373*4c06356bSdh (((pptr)->dtype == NOTHING)? "NOTHING" : \ 374*4c06356bSdh (((pptr)->dtype == SATA)? "SATA" : \ 375*4c06356bSdh (((pptr)->dtype == SAS)? "SAS" : "EXPANDER"))) 376*4c06356bSdh 377*4c06356bSdh #define IS_ROOT_PHY(pptr) (pptr->parent == NULL) 378*4c06356bSdh 379*4c06356bSdh #define PMCS_HIPRI(pwp, oq, c) \ 380*4c06356bSdh (pwp->hipri_queue & (1 << PMCS_IQ_OTHER)) ? \ 381*4c06356bSdh (PMCS_IOMB_HIPRI | PMCS_IOMB_IN_SAS(oq, c)) : \ 382*4c06356bSdh (PMCS_IOMB_IN_SAS(oq, c)) 383*4c06356bSdh 384*4c06356bSdh #define SCHEDULE_WORK(hwp, wrk) \ 385*4c06356bSdh (void) atomic_set_long_excl(&hwp->work_flags, wrk) 386*4c06356bSdh 387*4c06356bSdh /* 388*4c06356bSdh * Check to see if the requested work bit is set. Either way, the bit will 389*4c06356bSdh * be cleared upon return. 390*4c06356bSdh */ 391*4c06356bSdh #define WORK_SCHEDULED(hwp, wrk) \ 392*4c06356bSdh (atomic_clear_long_excl(&hwp->work_flags, wrk) == 0) 393*4c06356bSdh 394*4c06356bSdh /* 395*4c06356bSdh * Check to see if the requested work bit is set. The value will not be 396*4c06356bSdh * changed in this case. The atomic_xx_nv operations can be quite expensive 397*4c06356bSdh * so this should not be used in non-DEBUG code. 398*4c06356bSdh */ 399*4c06356bSdh #define WORK_IS_SCHEDULED(hwp, wrk) \ 400*4c06356bSdh ((atomic_and_ulong_nv(&hwp->work_flags, (ulong_t)-1) & (1 << wrk)) != 0) 401*4c06356bSdh 402*4c06356bSdh #define WAIT_FOR(p, t, r) \ 403*4c06356bSdh r = 0; \ 404*4c06356bSdh while (!PMCS_COMMAND_DONE(p)) { \ 405*4c06356bSdh clock_t tmp = cv_timedwait(&p->sleep_cv, \ 406*4c06356bSdh &p->lock, ddi_get_lbolt() + \ 407*4c06356bSdh drv_usectohz(t * 1000)); \ 408*4c06356bSdh if (!PMCS_COMMAND_DONE(p) && tmp < 0) { \ 409*4c06356bSdh r = 1; \ 410*4c06356bSdh break; \ 411*4c06356bSdh } \ 412*4c06356bSdh } 413*4c06356bSdh 414*4c06356bSdh /* 415*4c06356bSdh * Signal the next I/O completion thread to start running. 416*4c06356bSdh */ 417*4c06356bSdh 418*4c06356bSdh #define PMCS_CQ_RUN_LOCKED(hwp) \ 419*4c06356bSdh if (!STAILQ_EMPTY(&hwp->cq) || hwp->iocomp_cb_head) { \ 420*4c06356bSdh pmcs_cq_thr_info_t *cqti; \ 421*4c06356bSdh cqti = &hwp->cq_info.cq_thr_info \ 422*4c06356bSdh [hwp->cq_info.cq_next_disp_thr]; \ 423*4c06356bSdh hwp->cq_info.cq_next_disp_thr++; \ 424*4c06356bSdh if (hwp->cq_info.cq_next_disp_thr == \ 425*4c06356bSdh hwp->cq_info.cq_threads) { \ 426*4c06356bSdh hwp->cq_info.cq_next_disp_thr = 0; \ 427*4c06356bSdh } \ 428*4c06356bSdh mutex_enter(&cqti->cq_thr_lock); \ 429*4c06356bSdh cv_signal(&cqti->cq_cv); \ 430*4c06356bSdh mutex_exit(&cqti->cq_thr_lock); \ 431*4c06356bSdh } \ 432*4c06356bSdh 433*4c06356bSdh #define PMCS_CQ_RUN(hwp) \ 434*4c06356bSdh mutex_enter(&hwp->cq_lock); \ 435*4c06356bSdh PMCS_CQ_RUN_LOCKED(hwp); \ 436*4c06356bSdh mutex_exit(&hwp->cq_lock); 437*4c06356bSdh 438*4c06356bSdh 439*4c06356bSdh /* 440*4c06356bSdh * Watchdog/SCSA timer definitions 441*4c06356bSdh */ 442*4c06356bSdh /* usecs to SCSA watchdog ticks */ 443*4c06356bSdh #define US2WT(x) (x)/10 444*4c06356bSdh 445*4c06356bSdh /* 446*4c06356bSdh * More misc 447*4c06356bSdh */ 448*4c06356bSdh #define BYTE0(x) (((x) >> 0) & 0xff) 449*4c06356bSdh #define BYTE1(x) (((x) >> 8) & 0xff) 450*4c06356bSdh #define BYTE2(x) (((x) >> 16) & 0xff) 451*4c06356bSdh #define BYTE3(x) (((x) >> 24) & 0xff) 452*4c06356bSdh #define BYTE4(x) (((x) >> 32) & 0xff) 453*4c06356bSdh #define BYTE5(x) (((x) >> 40) & 0xff) 454*4c06356bSdh #define BYTE6(x) (((x) >> 48) & 0xff) 455*4c06356bSdh #define BYTE7(x) (((x) >> 56) & 0xff) 456*4c06356bSdh #define WORD0(x) (((x) >> 0) & 0xffff) 457*4c06356bSdh #define WORD1(x) (((x) >> 16) & 0xffff) 458*4c06356bSdh #define WORD2(x) (((x) >> 32) & 0xffff) 459*4c06356bSdh #define WORD3(x) (((x) >> 48) & 0xffff) 460*4c06356bSdh #define DWORD0(x) ((uint32_t)(x)) 461*4c06356bSdh #define DWORD1(x) ((uint32_t)(((uint64_t)x) >> 32)) 462*4c06356bSdh 463*4c06356bSdh #define SAS_ADDR_FMT "0x%02x%02x%02x%02x%02x%02x%02x%02x" 464*4c06356bSdh #define SAS_ADDR_PRT(x) x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7] 465*4c06356bSdh 466*4c06356bSdh #define PMCS_VALID_LINK_RATE(r) \ 467*4c06356bSdh ((r == SAS_LINK_RATE_1_5GBIT) || (r == SAS_LINK_RATE_3GBIT) || \ 468*4c06356bSdh (r == SAS_LINK_RATE_6GBIT)) 469*4c06356bSdh 470*4c06356bSdh /* 471*4c06356bSdh * This is here to avoid inclusion of <sys/ctype.h> which is not lint clean. 472*4c06356bSdh */ 473*4c06356bSdh #define HEXDIGIT(x) (((x) >= '0' && (x) <= '9') || \ 474*4c06356bSdh ((x) >= 'a' && (x) <= 'f') || ((x) >= 'A' && (x) <= 'F')) 475*4c06356bSdh 476*4c06356bSdh 477*4c06356bSdh typedef void (*pmcs_cb_t) (pmcs_hw_t *, pmcwork_t *, uint32_t *); 478*4c06356bSdh 479*4c06356bSdh /* 480*4c06356bSdh * Defines and structure used for tracing/logging information 481*4c06356bSdh */ 482*4c06356bSdh 483*4c06356bSdh #define PMCS_TBUF_ELEM_SIZE 120 484*4c06356bSdh 485*4c06356bSdh #ifdef DEBUG 486*4c06356bSdh #define PMCS_TBUF_NUM_ELEMS_DEF 100000 487*4c06356bSdh #else 488*4c06356bSdh #define PMCS_TBUF_NUM_ELEMS_DEF 15000 489*4c06356bSdh #endif 490*4c06356bSdh 491*4c06356bSdh typedef struct { 492*4c06356bSdh timespec_t timestamp; 493*4c06356bSdh char buf[PMCS_TBUF_ELEM_SIZE]; 494*4c06356bSdh } pmcs_tbuf_t; 495*4c06356bSdh 496*4c06356bSdh /* 497*4c06356bSdh * Firmware event log header format 498*4c06356bSdh */ 499*4c06356bSdh 500*4c06356bSdh typedef struct pmcs_fw_event_hdr_s { 501*4c06356bSdh uint32_t fw_el_signature; 502*4c06356bSdh uint32_t fw_el_entry_start_offset; 503*4c06356bSdh uint32_t fw_el_rsvd1; 504*4c06356bSdh uint32_t fw_el_buf_size; 505*4c06356bSdh uint32_t fw_el_rsvd2; 506*4c06356bSdh uint32_t fw_el_oldest_idx; 507*4c06356bSdh uint32_t fw_el_latest_idx; 508*4c06356bSdh uint32_t fw_el_entry_size; 509*4c06356bSdh } pmcs_fw_event_hdr_t; 510*4c06356bSdh 511*4c06356bSdh #ifdef __cplusplus 512*4c06356bSdh } 513*4c06356bSdh #endif 514*4c06356bSdh #endif /* _PMCS_DEF_H */ 515