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 #ifndef _PMCS_DEF_H 25 #define _PMCS_DEF_H 26 #ifdef __cplusplus 27 extern "C" { 28 #endif 29 30 typedef enum { 31 NOTHING, /* nothing connected here */ 32 SATA, /* SATA connection */ 33 SAS, /* direct or indirect SAS connection */ 34 EXPANDER, /* connection to an expander */ 35 NEW /* Brand new device (pending state) */ 36 } pmcs_dtype_t; 37 38 /* 39 * This structure defines a PHY device that represents what we 40 * are connected to. 41 * 42 * The eight real physical PHYs that are in the PMC8X6G are represented 43 * as an array of eight of these structures which define what these 44 * real PHYs are connected to. 45 * 46 * Depending upon what is actually connected to each PHY, the 47 * type set will define what we're connected to. If it is 48 * a direct SATA connection, the phy will describe a SATA endpoint 49 * If it is a direct SAS connection, it will describe a SAS 50 * endpoint. 51 * 52 * If it is an EXPANDER, this will describe the edge of an expander. 53 * As we perform discovery on what is in an EXPANDER we define an 54 * additional list of phys that represent what the Expander is connected to. 55 */ 56 #define PMCS_HW_MIN_LINK_RATE SAS_LINK_RATE_1_5GBIT 57 #define PMCS_HW_MAX_LINK_RATE SAS_LINK_RATE_6GBIT 58 59 #define PMCS_INVALID_DEVICE_ID 0xffffffff 60 #define PMCS_DEVICE_ID_MASK 0xffff 61 #define PMCS_PHY_INVALID_PORT_ID 0xf 62 63 #define PMCS_PM_MAX_NAMELEN 16 64 #define PMCS_MAX_REENUMERATE 2 /* Maximum re-enumeration attempts */ 65 66 /* 67 * Number of usecs to wait after last noted activate/deactivate callback 68 * before possibly restarting discovery 69 */ 70 #define PMCS_REDISCOVERY_DELAY (5 * MICROSEC) 71 72 struct pmcs_phy { 73 pmcs_phy_t *sibling; /* sibling phy */ 74 pmcs_phy_t *parent; /* parent phy */ 75 pmcs_phy_t *children; /* head of list of children */ 76 pmcs_phy_t *dead_next; /* dead PHY list link */ 77 list_node_t list_node; /* list element */ 78 uint32_t device_id; /* PMC8X6G device handle */ 79 uint32_t 80 ncphy : 8, /* # of contained phys for expander */ 81 hw_event_ack : 24; /* XXX: first level phy event acked */ 82 uint8_t phynum; /* phy number on parent expander */ 83 uint8_t width; /* how many phys wide */ 84 uint8_t ds_recovery_retries; /* # error retry attempts */ 85 uint8_t ds_prev_good_recoveries; /* # successful recoveries */ 86 clock_t prev_recovery; /* previous successful recovery */ 87 clock_t last_good_recovery; /* oldest successful recovery */ 88 /* within PMCS_MAX_DS_RECOVERY_TIME time frame */ 89 pmcs_dtype_t dtype; /* current dtype of the phy */ 90 pmcs_dtype_t pend_dtype; /* new dtype (pending change) */ 91 uint32_t 92 level : 8, /* level in expander tree */ 93 tolerates_sas2 : 1, /* tolerates SAS2 SMP */ 94 spinup_hold : 1, /* spinup hold needs releasing */ 95 atdt : 3, /* attached device type */ 96 portid : 4, /* PMC8X6G port context */ 97 link_rate : 4, /* current supported speeds */ 98 valid_device_id : 1, /* device id is valid */ 99 abort_sent : 1, /* we've sent an abort */ 100 abort_pending : 1, /* we have an abort pending */ 101 need_rl_ext : 1, /* need SATA RL_EXT recocvery */ 102 subsidiary : 1, /* this is part of a wide phy */ 103 configured : 1, /* is configured */ 104 dead : 1, /* dead */ 105 changed : 1, /* this phy is changing */ 106 reenumerate : 1, /* attempt re-enumeration */ 107 virtual : 1, /* This is a virtual PHY */ 108 deregister_wait : 1; /* phy waiting to get deregistered */ 109 clock_t config_stop; /* When config attempts will stop */ 110 hrtime_t abort_all_start; 111 kcondvar_t abort_all_cv; /* Wait for ABORT_ALL completion */ 112 kmutex_t phy_lock; 113 volatile uint32_t ref_count; /* Targets & work on this PHY */ 114 uint32_t enum_attempts; /* # of enumeration attempts */ 115 uint8_t sas_address[8]; /* SAS address for this PHY */ 116 struct { 117 uint32_t 118 prog_min_rate :4, 119 hw_min_rate :4, 120 prog_max_rate :4, 121 hw_max_rate :4, 122 reserved :16; 123 } state; 124 char path[32]; /* path name for this phy */ 125 pmcs_hw_t *pwp; /* back ptr to hba struct */ 126 pmcs_iport_t *iport; /* back ptr to the iport handle */ 127 pmcs_iport_t *last_iport; /* last iport this PHY was on */ 128 pmcs_xscsi_t *target; /* back ptr to current target */ 129 pmcs_xscsi_t **target_addr; /* address of real target pointer */ 130 kstat_t *phy_stats; /* kstats for this phy */ 131 /* 132 * Attached port phy mask and target port phymask. With 16 bytes 133 * we can represent a phymask for anything with up to 64 ports 134 */ 135 uint64_t att_port_pm; /* att port pm for this PHY */ 136 uint64_t att_port_pm_tmp; /* Temp area for wide-ports */ 137 char att_port_pm_str[PMCS_PM_MAX_NAMELEN + 1]; 138 uint64_t tgt_port_pm; /* tgt port pm for this PHY */ 139 uint64_t tgt_port_pm_tmp; /* Temp area for wide-ports */ 140 char tgt_port_pm_str[PMCS_PM_MAX_NAMELEN + 1]; 141 smp_routing_attr_t routing_attr; /* Routing attr. from discover resp. */ 142 smp_routing_attr_t routing_method; /* Actual routing method used. */ 143 smp_report_general_resp_t rg_resp; /* Response to REPORT_GENERAL */ 144 smp_discover_resp_t disc_resp; /* Response to DISCOVER */ 145 }; 146 147 /* maximum number of ds recovery retries (ds_recovery_retries) */ 148 #define PMCS_MAX_DS_RECOVERY_RETRIES 10 149 150 /* max time allowed for successful recovery */ 151 #define PMCS_MAX_DS_RECOVERY_TIME (60 * 1000000) /* 60 seconds */ 152 153 /* ds recovery on same same phy is not allowed within this interval */ 154 #define PMCS_DS_RECOVERY_INTERVAL (1000000) /* 1 second */ 155 156 157 /* 158 * Inbound and Outbound Queue Related Definitions. 159 * 160 * The PMC8X6G has a programmable number of inbound and outbound circular 161 * queues for use in message passing between the host and the PMC8X6G 162 * (up to 64 queues for the Rev C Chip). This driver does not use all 163 * possible queues. 164 * 165 * Each Queue is given 4K of consistent memory and we set a 64 byte size for 166 * the queue entry size (this gives us 256 queue entries per queue). 167 * 168 * This allocation then continues up a further PMCS_SCRATCH_SIZE bytes 169 * that the driver uses as a temporary scratch area for things like 170 * SMP discovery. 171 * 172 * This control area looks like this: 173 * 174 * Offset What 175 * ------------------------------------------------ 176 * 0 IQ 0 Consumer Index 177 * 4 IQ 1 Consumer Index 178 * 8..255 ... 179 * 252..255 IQ 63 Consumer Index 180 * 256 OQ 0 Producer Index 181 * 260 OQ 1 Producer Index 182 * 264..259 .... 183 * 508..511 OQ 63 Producer Index 184 * 512..512+PMCS_SCRATCH_SIZE-1 Scratch area. 185 */ 186 #define IQCI_BASE_OFFSET 0 187 #define IQ_OFFSET(qnum) (IQCI_BASE_OFFSET + (qnum << 2)) 188 #define OQPI_BASE_OFFSET 256 189 #define OQ_OFFSET(qnum) (OQPI_BASE_OFFSET + (qnum << 2)) 190 191 /* 192 * Work related structures. Each one of these structures is paired 193 * with *any* command that is fed to the PMC8X6G via one of the 194 * Inbound Queues. The work structure has a tag to compare with 195 * the message that comes back out of an Outbound Queue. The 196 * work structure also points to the phy which this command is 197 * tied to. It also has a pointer a callback function (if defined). 198 * See that TAG Architecture below for the various kinds of 199 * dispositions of a work structure. 200 */ 201 202 /* 203 * Work Structure States 204 * 205 * NIL -> READY 206 * READY -> NIL 207 * READY -> ONCHIP 208 * ONCHIP -> INTR 209 * INTR -> READY 210 * INTR -> NIL 211 * INTR -> ABORTED 212 * INTR -> TIMED_OUT 213 * ABORTED -> NIL 214 * TIMED_OUT -> NIL 215 */ 216 typedef enum { 217 PMCS_WORK_STATE_NIL = 0, 218 PMCS_WORK_STATE_READY, 219 PMCS_WORK_STATE_ONCHIP, 220 PMCS_WORK_STATE_INTR, 221 PMCS_WORK_STATE_IOCOMPQ, 222 PMCS_WORK_STATE_ABORTED, 223 PMCS_WORK_STATE_TIMED_OUT 224 } pmcs_work_state_t; 225 226 struct pmcwork { 227 STAILQ_ENTRY(pmcwork) next; 228 kmutex_t lock; 229 kcondvar_t sleep_cv; 230 void *ptr; /* linkage or callback function */ 231 void *arg; /* command specific data */ 232 pmcs_phy_t *phy; /* phy who owns this command */ 233 pmcs_xscsi_t *xp; /* Back pointer to xscsi struct */ 234 volatile uint32_t htag; /* tag for this structure */ 235 uint32_t abt_htag; /* Tag of command to be aborted */ 236 uint32_t 237 timer : 27, 238 onwire : 1, 239 dead : 1, 240 state : 3; 241 hrtime_t start; /* timestamp start */ 242 uint32_t ssp_event; /* ssp event */ 243 pmcs_dtype_t dtype; /* stash, incase phy gets cleared */ 244 245 void *last_ptr; 246 void *last_arg; 247 pmcs_phy_t *last_phy; 248 pmcs_xscsi_t *last_xp; 249 uint32_t last_htag; 250 pmcs_work_state_t last_state; 251 hrtime_t finish; 252 }; 253 #define PMCS_ABT_HTAG_ALL 0xffffffff 254 255 #define PMCS_REC_EVENT 0xffffffff /* event recovery */ 256 257 /* 258 * This structure defines a PMC-Sierra defined firmware header. 259 */ 260 #pragma pack(4) 261 typedef struct { 262 char vendor_id[8]; 263 uint8_t product_id; 264 uint8_t hwrev; 265 uint8_t destination_partition; 266 uint8_t reserved0; 267 uint8_t fwrev[4]; 268 uint32_t firmware_length; 269 uint32_t crc; 270 uint32_t start_address; 271 uint8_t data[]; 272 } pmcs_fw_hdr_t; 273 #pragma pack() 274 275 /* 276 * Offlevel work as a bit pattern. 277 */ 278 #define PMCS_WORK_DISCOVER 0 279 #define PMCS_WORK_ABORT_HANDLE 3 280 #define PMCS_WORK_SPINUP_RELEASE 4 281 #define PMCS_WORK_SAS_HW_ACK 5 282 #define PMCS_WORK_SATA_RUN 6 283 #define PMCS_WORK_RUN_QUEUES 7 284 #define PMCS_WORK_ADD_DMA_CHUNKS 8 285 #define PMCS_WORK_DS_ERR_RECOVERY 9 286 #define PMCS_WORK_SSP_EVT_RECOVERY 10 287 #define PMCS_WORK_DEREGISTER_DEV 11 288 #define PMCS_WORK_DUMP_REGS 12 289 290 /* 291 * The actual values as they appear in work_flags 292 */ 293 #define PMCS_WORK_FLAG_DISCOVER (1 << 0) 294 #define PMCS_WORK_FLAG_ABORT_HANDLE (1 << 3) 295 #define PMCS_WORK_FLAG_SPINUP_RELEASE (1 << 4) 296 #define PMCS_WORK_FLAG_SAS_HW_ACK (1 << 5) 297 #define PMCS_WORK_FLAG_SATA_RUN (1 << 6) 298 #define PMCS_WORK_FLAG_RUN_QUEUES (1 << 7) 299 #define PMCS_WORK_FLAG_ADD_DMA_CHUNKS (1 << 8) 300 #define PMCS_WORK_FLAG_DS_ERR_RECOVERY (1 << 9) 301 #define PMCS_WORK_FLAG_SSP_EVT_RECOVERY (1 << 10) 302 #define PMCS_WORK_FLAG_DEREGISTER_DEV (1 << 11) 303 #define PMCS_WORK_FLAG_DUMP_REGS (1 << 12) 304 305 /* 306 * This structure is used by this function to test MPI (and interrupts) 307 * after MPI has been started to make sure it's working reliably. 308 */ 309 typedef struct { 310 uint32_t signature; 311 uint32_t count; 312 uint32_t *ptr; 313 } echo_test_t; 314 #define ECHO_SIGNATURE 0xbebebeef 315 316 /* 317 * Tag Architecture. The PMC has 32 bit tags for MPI messages. 318 * We use this tag this way. 319 * 320 * bits what 321 * ------------------------ 322 * 31 done bit 323 * 30 non-io cmd bit 324 * 29..28 tag type 325 * 27..12 rolling serial number 326 * 11..0 index into work area to get pmcwork structure 327 * 328 * A tag type of NONE means that nobody is waiting on any results, 329 * so the interrupt code frees the work structure that has this 330 * tag. 331 * 332 * A tag type of CBACK means that the the interrupt handler 333 * takes the tag 'arg' in the work structure to be a callback 334 * function pointer (see pmcs_cb_t). The callee is responsible 335 * for freeing the work structure that has this tag. 336 * 337 * A tag type of WAIT means that the issuer of the work needs 338 * be woken up from interrupt level when the command completes 339 * (or times out). If work structure tag 'arg' is non-null, 340 * up to 2*PMCS_QENTRY_SIZE bits of data from the Outbound Queue 341 * entry may be copied to the area pointed to by 'arg'. This 342 * allows issuers to get directly at the results of the command 343 * they issed. The synchronization point for the issuer and the 344 * interrupt code for command done notification is the setting 345 * of the 'DONE' bit in the tag as stored in the work structure. 346 */ 347 #define PMCS_TAG_TYPE_FREE 0 348 #define PMCS_TAG_TYPE_NONE 1 349 #define PMCS_TAG_TYPE_CBACK 2 350 #define PMCS_TAG_TYPE_WAIT 3 351 #define PMCS_TAG_TYPE_SHIFT 28 352 #define PMCS_TAG_SERNO_SHIFT 12 353 #define PMCS_TAG_INDEX_SHIFT 0 354 #define PMCS_TAG_TYPE_MASK 0x30000000 355 #define PMCS_TAG_NONIO_CMD 0x40000000 356 #define PMCS_TAG_DONE 0x80000000 357 #define PMCS_TAG_SERNO_MASK 0x0ffff000 358 #define PMCS_TAG_INDEX_MASK 0x00000fff 359 #define PMCS_TAG_TYPE(x) \ 360 (((x) & PMCS_TAG_TYPE_MASK) >> PMCS_TAG_TYPE_SHIFT) 361 #define PMCS_TAG_SERNO(x) \ 362 (((x) & PMCS_TAG_SERNO_MASK) >> PMCS_TAG_SERNO_SHIFT) 363 #define PMCS_TAG_INDEX(x) \ 364 (((x) & PMCS_TAG_INDEX_MASK) >> PMCS_TAG_INDEX_SHIFT) 365 #define PMCS_TAG_FREE 0 366 #define PMCS_COMMAND_DONE(x) \ 367 (((x)->htag == PMCS_TAG_FREE) || (((x)->htag & PMCS_TAG_DONE) != 0)) 368 #define PMCS_COMMAND_ACTIVE(x) \ 369 ((x)->htag != PMCS_TAG_FREE && (x)->state == PMCS_WORK_STATE_ONCHIP) 370 371 /* 372 * Miscellaneous Definitions 373 */ 374 #define CLEAN_MESSAGE(m, x) { \ 375 int _j = x; \ 376 while (_j < PMCS_MSG_SIZE) { \ 377 m[_j++] = 0; \ 378 } \ 379 } 380 381 #define COPY_MESSAGE(t, f, a) { \ 382 int _j; \ 383 for (_j = 0; _j < a; _j++) { \ 384 t[_j] = f[_j]; \ 385 } \ 386 while (_j < PMCS_MSG_SIZE) { \ 387 t[_j++] = 0; \ 388 } \ 389 } 390 391 #define PMCS_PHY_ADDRESSABLE(pp) \ 392 ((pp)->level == 0 && (pp)->dtype == SATA && \ 393 ((pp)->sas_address[0] >> 4) != 5) 394 395 #define RESTART_DISCOVERY(pwp) \ 396 ASSERT(!mutex_owned(&pwp->config_lock)); \ 397 mutex_enter(&pwp->config_lock); \ 398 pwp->config_changed = B_TRUE; \ 399 mutex_exit(&pwp->config_lock); \ 400 SCHEDULE_WORK(pwp, PMCS_WORK_DISCOVER); 401 402 #define RESTART_DISCOVERY_LOCKED(pwp) \ 403 ASSERT(mutex_owned(&pwp->config_lock)); \ 404 pwp->config_changed = B_TRUE; \ 405 SCHEDULE_WORK(pwp, PMCS_WORK_DISCOVER); 406 407 #define PHY_CHANGED(pwp, p) \ 408 pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, p, NULL, "%s changed in " \ 409 "%s line %d", p->path, __func__, __LINE__); \ 410 p->changed = 1; \ 411 p->enum_attempts = 0 412 413 #define PHY_CHANGED_AT_LOCATION(pwp, p, func, line) \ 414 pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, p, NULL, "%s changed in " \ 415 "%s line %d", p->path, func, line); \ 416 p->changed = 1; \ 417 p->enum_attempts = 0 418 419 #define PHY_TYPE(pptr) \ 420 (((pptr)->dtype == NOTHING)? "NOTHING" : \ 421 (((pptr)->dtype == SATA)? "SATA" : \ 422 (((pptr)->dtype == SAS)? "SAS" : "EXPANDER"))) 423 424 #define IS_ROOT_PHY(pptr) (pptr->parent == NULL) 425 426 #define PMCS_HIPRI(pwp, oq, c) \ 427 (pwp->hipri_queue & (1 << PMCS_IQ_OTHER)) ? \ 428 (PMCS_IOMB_HIPRI | PMCS_IOMB_IN_SAS(oq, c)) : \ 429 (PMCS_IOMB_IN_SAS(oq, c)) 430 431 #define SCHEDULE_WORK(hwp, wrk) \ 432 (void) atomic_set_long_excl(&hwp->work_flags, wrk) 433 434 /* 435 * Check to see if the requested work bit is set. Either way, the bit will 436 * be cleared upon return. 437 */ 438 #define WORK_SCHEDULED(hwp, wrk) \ 439 (atomic_clear_long_excl(&hwp->work_flags, wrk) == 0) 440 441 /* 442 * Check to see if the requested work bit is set. The value will not be 443 * changed in this case. The atomic_xx_nv operations can be quite expensive 444 * so this should not be used in non-DEBUG code. 445 */ 446 #define WORK_IS_SCHEDULED(hwp, wrk) \ 447 ((atomic_and_ulong_nv(&hwp->work_flags, (ulong_t)-1) & (1 << wrk)) != 0) 448 449 #define WAIT_FOR(p, t, r) \ 450 clock_t _lb = ddi_get_lbolt(); \ 451 r = 0; \ 452 while (!PMCS_COMMAND_DONE(p)) { \ 453 clock_t _ret = cv_timedwait(&p->sleep_cv, \ 454 &p->lock, _lb + drv_usectohz(t * 1000)); \ 455 if (!PMCS_COMMAND_DONE(p) && _ret < 0) { \ 456 r = 1; \ 457 break; \ 458 } \ 459 } 460 461 /* 462 * Signal the next I/O completion thread to start running. 463 */ 464 465 #define PMCS_CQ_RUN_LOCKED(hwp) \ 466 if (!STAILQ_EMPTY(&hwp->cq) || hwp->iocomp_cb_head) { \ 467 pmcs_cq_thr_info_t *cqti; \ 468 cqti = &hwp->cq_info.cq_thr_info \ 469 [hwp->cq_info.cq_next_disp_thr]; \ 470 hwp->cq_info.cq_next_disp_thr++; \ 471 if (hwp->cq_info.cq_next_disp_thr == \ 472 hwp->cq_info.cq_threads) { \ 473 hwp->cq_info.cq_next_disp_thr = 0; \ 474 } \ 475 mutex_enter(&cqti->cq_thr_lock); \ 476 cv_signal(&cqti->cq_cv); \ 477 mutex_exit(&cqti->cq_thr_lock); \ 478 } 479 480 #define PMCS_CQ_RUN(hwp) \ 481 mutex_enter(&hwp->cq_lock); \ 482 PMCS_CQ_RUN_LOCKED(hwp); \ 483 mutex_exit(&hwp->cq_lock); 484 485 486 /* 487 * Watchdog/SCSA timer definitions 488 */ 489 /* usecs to SCSA watchdog ticks */ 490 #define US2WT(x) (x)/10 491 492 /* 493 * More misc 494 */ 495 #define BYTE0(x) (((x) >> 0) & 0xff) 496 #define BYTE1(x) (((x) >> 8) & 0xff) 497 #define BYTE2(x) (((x) >> 16) & 0xff) 498 #define BYTE3(x) (((x) >> 24) & 0xff) 499 #define BYTE4(x) (((x) >> 32) & 0xff) 500 #define BYTE5(x) (((x) >> 40) & 0xff) 501 #define BYTE6(x) (((x) >> 48) & 0xff) 502 #define BYTE7(x) (((x) >> 56) & 0xff) 503 #define WORD0(x) (((x) >> 0) & 0xffff) 504 #define WORD1(x) (((x) >> 16) & 0xffff) 505 #define WORD2(x) (((x) >> 32) & 0xffff) 506 #define WORD3(x) (((x) >> 48) & 0xffff) 507 #define DWORD0(x) ((uint32_t)(x)) 508 #define DWORD1(x) ((uint32_t)(((uint64_t)x) >> 32)) 509 510 #define SAS_ADDR_FMT "0x%02x%02x%02x%02x%02x%02x%02x%02x" 511 #define SAS_ADDR_PRT(x) x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7] 512 513 #define PMCS_VALID_LINK_RATE(r) \ 514 ((r == SAS_LINK_RATE_1_5GBIT) || (r == SAS_LINK_RATE_3GBIT) || \ 515 (r == SAS_LINK_RATE_6GBIT)) 516 517 /* 518 * This is here to avoid inclusion of <sys/ctype.h> which is not lint clean. 519 */ 520 #define HEXDIGIT(x) (((x) >= '0' && (x) <= '9') || \ 521 ((x) >= 'a' && (x) <= 'f') || ((x) >= 'A' && (x) <= 'F')) 522 523 #define NSECS_PER_SEC 1000000000UL 524 525 526 typedef void (*pmcs_cb_t) (pmcs_hw_t *, pmcwork_t *, uint32_t *); 527 528 /* 529 * Defines and structure used for tracing/logging information 530 */ 531 532 #define PMCS_TBUF_ELEM_SIZE 120 533 #define PMCS_TBUF_NUM_ELEMS_DEF 100000 534 535 #define PMCS_TBUF_UA_MAX_SIZE 32 536 typedef struct { 537 /* Target-specific data */ 538 uint16_t target_num; 539 char target_ua[PMCS_TBUF_UA_MAX_SIZE]; 540 /* PHY-specific data */ 541 uint8_t phy_sas_address[8]; 542 char phy_path[32]; 543 pmcs_dtype_t phy_dtype; 544 /* Log data */ 545 timespec_t timestamp; 546 uint64_t fw_timestamp; 547 char buf[PMCS_TBUF_ELEM_SIZE]; 548 } pmcs_tbuf_t; 549 550 /* 551 * Firmware event log header format 552 */ 553 typedef struct pmcs_fw_event_hdr_s { 554 uint32_t fw_el_signature; 555 uint32_t fw_el_entry_start_offset; 556 uint32_t fw_el_rsvd1; 557 uint32_t fw_el_buf_size; 558 uint32_t fw_el_rsvd2; 559 uint32_t fw_el_oldest_idx; 560 uint32_t fw_el_latest_idx; 561 uint32_t fw_el_entry_size; 562 } pmcs_fw_event_hdr_t; 563 564 /* 565 * Firmware event log entry format 566 */ 567 typedef struct pmcs_fw_event_entry_s { 568 uint32_t num_words : 3, 569 reserved : 25, 570 severity: 4; 571 uint32_t ts_upper; 572 uint32_t ts_lower; 573 uint32_t seq_num; 574 uint32_t logw0; 575 uint32_t logw1; 576 uint32_t logw2; 577 uint32_t logw3; 578 } pmcs_fw_event_entry_t; 579 580 #define PMCS_FWLOG_TIMER_DIV 8 /* fw timer has 8ns granularity */ 581 #define PMCS_FWLOG_AAP1_SIG 0x1234AAAA 582 #define PMCS_FWLOG_IOP_SIG 0x5678CCCC 583 584 /* 585 * Receptacle information 586 */ 587 #define PMCS_NUM_RECEPTACLES 2 588 589 #define PMCS_RECEPT_LABEL_0 "SAS0" 590 #define PMCS_RECEPT_LABEL_1 "SAS1" 591 592 #define PMCS_RECEPT_PM_0 "f0" 593 #define PMCS_RECEPT_PM_1 "f" 594 595 #ifdef __cplusplus 596 } 597 #endif 598 #endif /* _PMCS_DEF_H */ 599