14c06356bSdh /* 24c06356bSdh * CDDL HEADER START 34c06356bSdh * 44c06356bSdh * The contents of this file are subject to the terms of the 54c06356bSdh * Common Development and Distribution License (the "License"). 64c06356bSdh * You may not use this file except in compliance with the License. 74c06356bSdh * 84c06356bSdh * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 94c06356bSdh * or http://www.opensolaris.org/os/licensing. 104c06356bSdh * See the License for the specific language governing permissions 114c06356bSdh * and limitations under the License. 124c06356bSdh * 134c06356bSdh * When distributing Covered Code, include this CDDL HEADER in each 144c06356bSdh * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 154c06356bSdh * If applicable, add the following below this CDDL HEADER, with the 164c06356bSdh * fields enclosed by brackets "[]" replaced with your own identifying 174c06356bSdh * information: Portions Copyright [yyyy] [name of copyright owner] 184c06356bSdh * 194c06356bSdh * CDDL HEADER END 20658280b6SDavid Hollister */ 21658280b6SDavid Hollister /* 22658280b6SDavid Hollister * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. 234c06356bSdh */ 244c06356bSdh #ifndef _PMCS_DEF_H 254c06356bSdh #define _PMCS_DEF_H 264c06356bSdh #ifdef __cplusplus 274c06356bSdh extern "C" { 284c06356bSdh #endif 294c06356bSdh 304c06356bSdh typedef enum { 314c06356bSdh NOTHING, /* nothing connected here */ 324c06356bSdh SATA, /* SATA connection */ 334c06356bSdh SAS, /* direct or indirect SAS connection */ 344c06356bSdh EXPANDER, /* connection to an expander */ 354c06356bSdh NEW /* Brand new device (pending state) */ 364c06356bSdh } pmcs_dtype_t; 374c06356bSdh 384c06356bSdh /* 394c06356bSdh * This structure defines a PHY device that represents what we 404c06356bSdh * are connected to. 414c06356bSdh * 424c06356bSdh * The eight real physical PHYs that are in the PMC8X6G are represented 434c06356bSdh * as an array of eight of these structures which define what these 444c06356bSdh * real PHYs are connected to. 454c06356bSdh * 464c06356bSdh * Depending upon what is actually connected to each PHY, the 474c06356bSdh * type set will define what we're connected to. If it is 484c06356bSdh * a direct SATA connection, the phy will describe a SATA endpoint 494c06356bSdh * If it is a direct SAS connection, it will describe a SAS 504c06356bSdh * endpoint. 514c06356bSdh * 524c06356bSdh * If it is an EXPANDER, this will describe the edge of an expander. 534c06356bSdh * As we perform discovery on what is in an EXPANDER we define an 544c06356bSdh * additional list of phys that represent what the Expander is connected to. 554c06356bSdh */ 564c06356bSdh #define PMCS_HW_MIN_LINK_RATE SAS_LINK_RATE_1_5GBIT 574c06356bSdh #define PMCS_HW_MAX_LINK_RATE SAS_LINK_RATE_6GBIT 584c06356bSdh 59601c90f1SSrikanth, Ramana #define PMCS_INVALID_DEVICE_ID 0xffffffff 60*65e70c04SDavid Hollister #define PMCS_DEVICE_ID_MASK 0xffff 61601c90f1SSrikanth, Ramana #define PMCS_PHY_INVALID_PORT_ID 0xf 624c06356bSdh 63499cfd15SDavid Hollister #define PMCS_PM_MAX_NAMELEN 16 649aed1621SDavid Hollister #define PMCS_MAX_REENUMERATE 2 /* Maximum re-enumeration attempts */ 659aed1621SDavid Hollister 669aed1621SDavid Hollister /* 679aed1621SDavid Hollister * Number of usecs to wait after last noted activate/deactivate callback 689aed1621SDavid Hollister * before possibly restarting discovery 699aed1621SDavid Hollister */ 709aed1621SDavid Hollister #define PMCS_REDISCOVERY_DELAY (5 * MICROSEC) 71499cfd15SDavid Hollister 724c06356bSdh struct pmcs_phy { 734c06356bSdh pmcs_phy_t *sibling; /* sibling phy */ 744c06356bSdh pmcs_phy_t *parent; /* parent phy */ 754c06356bSdh pmcs_phy_t *children; /* head of list of children */ 764c06356bSdh pmcs_phy_t *dead_next; /* dead PHY list link */ 774c06356bSdh list_node_t list_node; /* list element */ 784c06356bSdh uint32_t device_id; /* PMC8X6G device handle */ 794c06356bSdh uint32_t 804c06356bSdh ncphy : 8, /* # of contained phys for expander */ 814c06356bSdh hw_event_ack : 24; /* XXX: first level phy event acked */ 824c06356bSdh uint8_t phynum; /* phy number on parent expander */ 834c06356bSdh uint8_t width; /* how many phys wide */ 844c06356bSdh uint8_t ds_recovery_retries; /* # error retry attempts */ 85af685682SSrikanth, Ramana uint8_t ds_prev_good_recoveries; /* # successful recoveries */ 86af685682SSrikanth, Ramana clock_t prev_recovery; /* previous successful recovery */ 87af685682SSrikanth, Ramana clock_t last_good_recovery; /* oldest successful recovery */ 88af685682SSrikanth, Ramana /* within PMCS_MAX_DS_RECOVERY_TIME time frame */ 894c06356bSdh pmcs_dtype_t dtype; /* current dtype of the phy */ 904c06356bSdh pmcs_dtype_t pend_dtype; /* new dtype (pending change) */ 914c06356bSdh uint32_t 924c06356bSdh level : 8, /* level in expander tree */ 934c06356bSdh tolerates_sas2 : 1, /* tolerates SAS2 SMP */ 944c06356bSdh spinup_hold : 1, /* spinup hold needs releasing */ 954c06356bSdh atdt : 3, /* attached device type */ 964c06356bSdh portid : 4, /* PMC8X6G port context */ 974c06356bSdh link_rate : 4, /* current supported speeds */ 984c06356bSdh valid_device_id : 1, /* device id is valid */ 994c06356bSdh abort_sent : 1, /* we've sent an abort */ 1004c06356bSdh abort_pending : 1, /* we have an abort pending */ 1014c06356bSdh need_rl_ext : 1, /* need SATA RL_EXT recocvery */ 1024c06356bSdh subsidiary : 1, /* this is part of a wide phy */ 1034c06356bSdh configured : 1, /* is configured */ 1044c06356bSdh dead : 1, /* dead */ 105601c90f1SSrikanth, Ramana changed : 1, /* this phy is changing */ 1069aed1621SDavid Hollister reenumerate : 1, /* attempt re-enumeration */ 107c80dec56SDavid Hollister virtual : 1, /* This is a virtual PHY */ 108601c90f1SSrikanth, Ramana deregister_wait : 1; /* phy waiting to get deregistered */ 1094c06356bSdh clock_t config_stop; /* When config attempts will stop */ 1104c06356bSdh hrtime_t abort_all_start; 1114c06356bSdh kcondvar_t abort_all_cv; /* Wait for ABORT_ALL completion */ 1124c06356bSdh kmutex_t phy_lock; 1134c06356bSdh volatile uint32_t ref_count; /* Targets & work on this PHY */ 1149aed1621SDavid Hollister uint32_t enum_attempts; /* # of enumeration attempts */ 1154c06356bSdh uint8_t sas_address[8]; /* SAS address for this PHY */ 1164c06356bSdh struct { 1174c06356bSdh uint32_t 1184c06356bSdh prog_min_rate :4, 1194c06356bSdh hw_min_rate :4, 1204c06356bSdh prog_max_rate :4, 1214c06356bSdh hw_max_rate :4, 1224c06356bSdh reserved :16; 1234c06356bSdh } state; 1244c06356bSdh char path[32]; /* path name for this phy */ 1254c06356bSdh pmcs_hw_t *pwp; /* back ptr to hba struct */ 1264c06356bSdh pmcs_iport_t *iport; /* back ptr to the iport handle */ 12773a3eccdSDavid Hollister pmcs_iport_t *last_iport; /* last iport this PHY was on */ 1284c06356bSdh pmcs_xscsi_t *target; /* back ptr to current target */ 129188eaed9SSrikanth Suravajhala pmcs_xscsi_t **target_addr; /* address of real target pointer */ 1304c06356bSdh kstat_t *phy_stats; /* kstats for this phy */ 131499cfd15SDavid Hollister /* 132499cfd15SDavid Hollister * Attached port phy mask and target port phymask. With 16 bytes 133499cfd15SDavid Hollister * we can represent a phymask for anything with up to 64 ports 134499cfd15SDavid Hollister */ 135499cfd15SDavid Hollister uint64_t att_port_pm; /* att port pm for this PHY */ 136499cfd15SDavid Hollister uint64_t att_port_pm_tmp; /* Temp area for wide-ports */ 137499cfd15SDavid Hollister char att_port_pm_str[PMCS_PM_MAX_NAMELEN + 1]; 138499cfd15SDavid Hollister uint64_t tgt_port_pm; /* tgt port pm for this PHY */ 139499cfd15SDavid Hollister uint64_t tgt_port_pm_tmp; /* Temp area for wide-ports */ 140499cfd15SDavid Hollister char tgt_port_pm_str[PMCS_PM_MAX_NAMELEN + 1]; 1419aed1621SDavid Hollister smp_routing_attr_t routing_attr; /* Routing attr. from discover resp. */ 1429aed1621SDavid Hollister smp_routing_attr_t routing_method; /* Actual routing method used. */ 1439aed1621SDavid Hollister smp_report_general_resp_t rg_resp; /* Response to REPORT_GENERAL */ 1449aed1621SDavid Hollister smp_discover_resp_t disc_resp; /* Response to DISCOVER */ 1454c06356bSdh }; 1464c06356bSdh 1474c06356bSdh /* maximum number of ds recovery retries (ds_recovery_retries) */ 148601c90f1SSrikanth, Ramana #define PMCS_MAX_DS_RECOVERY_RETRIES 10 1494c06356bSdh 150af685682SSrikanth, Ramana /* max time allowed for successful recovery */ 151af685682SSrikanth, Ramana #define PMCS_MAX_DS_RECOVERY_TIME (60 * 1000000) /* 60 seconds */ 152af685682SSrikanth, Ramana 153af685682SSrikanth, Ramana /* ds recovery on same same phy is not allowed within this interval */ 154af685682SSrikanth, Ramana #define PMCS_DS_RECOVERY_INTERVAL (1000000) /* 1 second */ 155af685682SSrikanth, Ramana 1564c06356bSdh 1574c06356bSdh /* 1584c06356bSdh * Inbound and Outbound Queue Related Definitions. 1594c06356bSdh * 1604c06356bSdh * The PMC8X6G has a programmable number of inbound and outbound circular 1614c06356bSdh * queues for use in message passing between the host and the PMC8X6G 1624c06356bSdh * (up to 64 queues for the Rev C Chip). This driver does not use all 1634c06356bSdh * possible queues. 1644c06356bSdh * 1654c06356bSdh * Each Queue is given 4K of consistent memory and we set a 64 byte size for 1664c06356bSdh * the queue entry size (this gives us 256 queue entries per queue). 1674c06356bSdh * 1684c06356bSdh * This allocation then continues up a further PMCS_SCRATCH_SIZE bytes 1694c06356bSdh * that the driver uses as a temporary scratch area for things like 1704c06356bSdh * SMP discovery. 1714c06356bSdh * 1724c06356bSdh * This control area looks like this: 1734c06356bSdh * 1744c06356bSdh * Offset What 1754c06356bSdh * ------------------------------------------------ 1764c06356bSdh * 0 IQ 0 Consumer Index 1774c06356bSdh * 4 IQ 1 Consumer Index 1784c06356bSdh * 8..255 ... 1794c06356bSdh * 252..255 IQ 63 Consumer Index 1804c06356bSdh * 256 OQ 0 Producer Index 1814c06356bSdh * 260 OQ 1 Producer Index 1824c06356bSdh * 264..259 .... 1834c06356bSdh * 508..511 OQ 63 Producer Index 1844c06356bSdh * 512..512+PMCS_SCRATCH_SIZE-1 Scratch area. 1854c06356bSdh */ 1864c06356bSdh #define IQCI_BASE_OFFSET 0 1874c06356bSdh #define IQ_OFFSET(qnum) (IQCI_BASE_OFFSET + (qnum << 2)) 1884c06356bSdh #define OQPI_BASE_OFFSET 256 1894c06356bSdh #define OQ_OFFSET(qnum) (OQPI_BASE_OFFSET + (qnum << 2)) 1904c06356bSdh 1914c06356bSdh /* 1924c06356bSdh * Work related structures. Each one of these structures is paired 1934c06356bSdh * with *any* command that is fed to the PMC8X6G via one of the 1944c06356bSdh * Inbound Queues. The work structure has a tag to compare with 1954c06356bSdh * the message that comes back out of an Outbound Queue. The 1964c06356bSdh * work structure also points to the phy which this command is 1974c06356bSdh * tied to. It also has a pointer a callback function (if defined). 1984c06356bSdh * See that TAG Architecture below for the various kinds of 1994c06356bSdh * dispositions of a work structure. 2004c06356bSdh */ 2014c06356bSdh 2024c06356bSdh /* 2034c06356bSdh * Work Structure States 2044c06356bSdh * 2054c06356bSdh * NIL -> READY 2064c06356bSdh * READY -> NIL 2074c06356bSdh * READY -> ONCHIP 2084c06356bSdh * ONCHIP -> INTR 2094c06356bSdh * INTR -> READY 2104c06356bSdh * INTR -> NIL 2114c06356bSdh * INTR -> ABORTED 2124c06356bSdh * INTR -> TIMED_OUT 2134c06356bSdh * ABORTED -> NIL 2144c06356bSdh * TIMED_OUT -> NIL 2154c06356bSdh */ 2164c06356bSdh typedef enum { 2174c06356bSdh PMCS_WORK_STATE_NIL = 0, 2184c06356bSdh PMCS_WORK_STATE_READY, 2194c06356bSdh PMCS_WORK_STATE_ONCHIP, 2204c06356bSdh PMCS_WORK_STATE_INTR, 2214c06356bSdh PMCS_WORK_STATE_IOCOMPQ, 2224c06356bSdh PMCS_WORK_STATE_ABORTED, 2234c06356bSdh PMCS_WORK_STATE_TIMED_OUT 2244c06356bSdh } pmcs_work_state_t; 2254c06356bSdh 2264c06356bSdh struct pmcwork { 2274c06356bSdh STAILQ_ENTRY(pmcwork) next; 2284c06356bSdh kmutex_t lock; 2294c06356bSdh kcondvar_t sleep_cv; 2304c06356bSdh void *ptr; /* linkage or callback function */ 2314c06356bSdh void *arg; /* command specific data */ 2324c06356bSdh pmcs_phy_t *phy; /* phy who owns this command */ 2334c06356bSdh pmcs_xscsi_t *xp; /* Back pointer to xscsi struct */ 2344c06356bSdh volatile uint32_t htag; /* tag for this structure */ 235c3bc407cSdh uint32_t abt_htag; /* Tag of command to be aborted */ 2364c06356bSdh uint32_t 2374c06356bSdh timer : 27, 2384c06356bSdh onwire : 1, 2394c06356bSdh dead : 1, 2404c06356bSdh state : 3; 2414c06356bSdh hrtime_t start; /* timestamp start */ 2424c06356bSdh uint32_t ssp_event; /* ssp event */ 2434c06356bSdh pmcs_dtype_t dtype; /* stash, incase phy gets cleared */ 2444c06356bSdh 2454c06356bSdh void *last_ptr; 2464c06356bSdh void *last_arg; 2474c06356bSdh pmcs_phy_t *last_phy; 2484c06356bSdh pmcs_xscsi_t *last_xp; 2494c06356bSdh uint32_t last_htag; 2504c06356bSdh pmcs_work_state_t last_state; 2514c06356bSdh hrtime_t finish; 2524c06356bSdh }; 25339cd77a0SJesse Butler #define PMCS_ABT_HTAG_ALL 0xffffffff 2544c06356bSdh 2554c06356bSdh #define PMCS_REC_EVENT 0xffffffff /* event recovery */ 2564c06356bSdh 2574c06356bSdh /* 2584c06356bSdh * This structure defines a PMC-Sierra defined firmware header. 2594c06356bSdh */ 2604c06356bSdh #pragma pack(4) 2614c06356bSdh typedef struct { 2624c06356bSdh char vendor_id[8]; 2634c06356bSdh uint8_t product_id; 2644c06356bSdh uint8_t hwrev; 2654c06356bSdh uint8_t destination_partition; 2664c06356bSdh uint8_t reserved0; 2674c06356bSdh uint8_t fwrev[4]; 2684c06356bSdh uint32_t firmware_length; 2694c06356bSdh uint32_t crc; 2704c06356bSdh uint32_t start_address; 2714c06356bSdh uint8_t data[]; 2724c06356bSdh } pmcs_fw_hdr_t; 2734c06356bSdh #pragma pack() 2744c06356bSdh 2754c06356bSdh /* 2764c06356bSdh * Offlevel work as a bit pattern. 2774c06356bSdh */ 2784c06356bSdh #define PMCS_WORK_DISCOVER 0 2794c06356bSdh #define PMCS_WORK_ABORT_HANDLE 3 2804c06356bSdh #define PMCS_WORK_SPINUP_RELEASE 4 2814c06356bSdh #define PMCS_WORK_SAS_HW_ACK 5 2824c06356bSdh #define PMCS_WORK_SATA_RUN 6 2834c06356bSdh #define PMCS_WORK_RUN_QUEUES 7 2844c06356bSdh #define PMCS_WORK_ADD_DMA_CHUNKS 8 2854c06356bSdh #define PMCS_WORK_DS_ERR_RECOVERY 9 2864c06356bSdh #define PMCS_WORK_SSP_EVT_RECOVERY 10 287601c90f1SSrikanth, Ramana #define PMCS_WORK_DEREGISTER_DEV 11 288c280a92bSDavid Hollister #define PMCS_WORK_DUMP_REGS 12 2894c06356bSdh 2904c06356bSdh /* 2914c06356bSdh * The actual values as they appear in work_flags 2924c06356bSdh */ 2934c06356bSdh #define PMCS_WORK_FLAG_DISCOVER (1 << 0) 2944c06356bSdh #define PMCS_WORK_FLAG_ABORT_HANDLE (1 << 3) 2954c06356bSdh #define PMCS_WORK_FLAG_SPINUP_RELEASE (1 << 4) 2964c06356bSdh #define PMCS_WORK_FLAG_SAS_HW_ACK (1 << 5) 2974c06356bSdh #define PMCS_WORK_FLAG_SATA_RUN (1 << 6) 2984c06356bSdh #define PMCS_WORK_FLAG_RUN_QUEUES (1 << 7) 2994c06356bSdh #define PMCS_WORK_FLAG_ADD_DMA_CHUNKS (1 << 8) 3004c06356bSdh #define PMCS_WORK_FLAG_DS_ERR_RECOVERY (1 << 9) 3014c06356bSdh #define PMCS_WORK_FLAG_SSP_EVT_RECOVERY (1 << 10) 302601c90f1SSrikanth, Ramana #define PMCS_WORK_FLAG_DEREGISTER_DEV (1 << 11) 303c280a92bSDavid Hollister #define PMCS_WORK_FLAG_DUMP_REGS (1 << 12) 3044c06356bSdh 3054c06356bSdh /* 3064c06356bSdh * This structure is used by this function to test MPI (and interrupts) 3074c06356bSdh * after MPI has been started to make sure it's working reliably. 3084c06356bSdh */ 3094c06356bSdh typedef struct { 3104c06356bSdh uint32_t signature; 3114c06356bSdh uint32_t count; 3124c06356bSdh uint32_t *ptr; 3134c06356bSdh } echo_test_t; 3144c06356bSdh #define ECHO_SIGNATURE 0xbebebeef 3154c06356bSdh 3164c06356bSdh /* 3174c06356bSdh * Tag Architecture. The PMC has 32 bit tags for MPI messages. 3184c06356bSdh * We use this tag this way. 3194c06356bSdh * 3204c06356bSdh * bits what 3214c06356bSdh * ------------------------ 3224c06356bSdh * 31 done bit 323978d7443SSrikanth Suravajhala * 30 non-io cmd bit 324978d7443SSrikanth Suravajhala * 29..28 tag type 3254c06356bSdh * 27..12 rolling serial number 3264c06356bSdh * 11..0 index into work area to get pmcwork structure 3274c06356bSdh * 3284c06356bSdh * A tag type of NONE means that nobody is waiting on any results, 3294c06356bSdh * so the interrupt code frees the work structure that has this 3304c06356bSdh * tag. 3314c06356bSdh * 3324c06356bSdh * A tag type of CBACK means that the the interrupt handler 3334c06356bSdh * takes the tag 'arg' in the work structure to be a callback 3344c06356bSdh * function pointer (see pmcs_cb_t). The callee is responsible 3354c06356bSdh * for freeing the work structure that has this tag. 3364c06356bSdh * 3374c06356bSdh * A tag type of WAIT means that the issuer of the work needs 3384c06356bSdh * be woken up from interrupt level when the command completes 3394c06356bSdh * (or times out). If work structure tag 'arg' is non-null, 3404c06356bSdh * up to 2*PMCS_QENTRY_SIZE bits of data from the Outbound Queue 3414c06356bSdh * entry may be copied to the area pointed to by 'arg'. This 3424c06356bSdh * allows issuers to get directly at the results of the command 3434c06356bSdh * they issed. The synchronization point for the issuer and the 3444c06356bSdh * interrupt code for command done notification is the setting 3454c06356bSdh * of the 'DONE' bit in the tag as stored in the work structure. 3464c06356bSdh */ 3474c06356bSdh #define PMCS_TAG_TYPE_FREE 0 3484c06356bSdh #define PMCS_TAG_TYPE_NONE 1 3494c06356bSdh #define PMCS_TAG_TYPE_CBACK 2 3504c06356bSdh #define PMCS_TAG_TYPE_WAIT 3 3514c06356bSdh #define PMCS_TAG_TYPE_SHIFT 28 3524c06356bSdh #define PMCS_TAG_SERNO_SHIFT 12 3534c06356bSdh #define PMCS_TAG_INDEX_SHIFT 0 354978d7443SSrikanth Suravajhala #define PMCS_TAG_TYPE_MASK 0x30000000 355978d7443SSrikanth Suravajhala #define PMCS_TAG_NONIO_CMD 0x40000000 3564c06356bSdh #define PMCS_TAG_DONE 0x80000000 3574c06356bSdh #define PMCS_TAG_SERNO_MASK 0x0ffff000 3584c06356bSdh #define PMCS_TAG_INDEX_MASK 0x00000fff 3594c06356bSdh #define PMCS_TAG_TYPE(x) \ 3604c06356bSdh (((x) & PMCS_TAG_TYPE_MASK) >> PMCS_TAG_TYPE_SHIFT) 3614c06356bSdh #define PMCS_TAG_SERNO(x) \ 3624c06356bSdh (((x) & PMCS_TAG_SERNO_MASK) >> PMCS_TAG_SERNO_SHIFT) 3634c06356bSdh #define PMCS_TAG_INDEX(x) \ 3644c06356bSdh (((x) & PMCS_TAG_INDEX_MASK) >> PMCS_TAG_INDEX_SHIFT) 3654c06356bSdh #define PMCS_TAG_FREE 0 3664c06356bSdh #define PMCS_COMMAND_DONE(x) \ 3674c06356bSdh (((x)->htag == PMCS_TAG_FREE) || (((x)->htag & PMCS_TAG_DONE) != 0)) 3684c06356bSdh #define PMCS_COMMAND_ACTIVE(x) \ 3694c06356bSdh ((x)->htag != PMCS_TAG_FREE && (x)->state == PMCS_WORK_STATE_ONCHIP) 3704c06356bSdh 3714c06356bSdh /* 3724c06356bSdh * Miscellaneous Definitions 3734c06356bSdh */ 3744c06356bSdh #define CLEAN_MESSAGE(m, x) { \ 3754c06356bSdh int _j = x; \ 3764c06356bSdh while (_j < PMCS_MSG_SIZE) { \ 3774c06356bSdh m[_j++] = 0; \ 3784c06356bSdh } \ 3794c06356bSdh } 3804c06356bSdh 3814c06356bSdh #define COPY_MESSAGE(t, f, a) { \ 3824c06356bSdh int _j; \ 3834c06356bSdh for (_j = 0; _j < a; _j++) { \ 3844c06356bSdh t[_j] = f[_j]; \ 3854c06356bSdh } \ 3864c06356bSdh while (_j < PMCS_MSG_SIZE) { \ 3874c06356bSdh t[_j++] = 0; \ 3884c06356bSdh } \ 3894c06356bSdh } 3904c06356bSdh 3914c06356bSdh #define PMCS_PHY_ADDRESSABLE(pp) \ 3924c06356bSdh ((pp)->level == 0 && (pp)->dtype == SATA && \ 3934c06356bSdh ((pp)->sas_address[0] >> 4) != 5) 3944c06356bSdh 3954c06356bSdh #define RESTART_DISCOVERY(pwp) \ 3964c06356bSdh ASSERT(!mutex_owned(&pwp->config_lock)); \ 3974c06356bSdh mutex_enter(&pwp->config_lock); \ 3984c06356bSdh pwp->config_changed = B_TRUE; \ 3994c06356bSdh mutex_exit(&pwp->config_lock); \ 4004c06356bSdh SCHEDULE_WORK(pwp, PMCS_WORK_DISCOVER); 4014c06356bSdh 4024c06356bSdh #define RESTART_DISCOVERY_LOCKED(pwp) \ 4034c06356bSdh ASSERT(mutex_owned(&pwp->config_lock)); \ 4044c06356bSdh pwp->config_changed = B_TRUE; \ 4054c06356bSdh SCHEDULE_WORK(pwp, PMCS_WORK_DISCOVER); 4064c06356bSdh 4074c06356bSdh #define PHY_CHANGED(pwp, p) \ 408c3bc407cSdh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, p, NULL, "%s changed in " \ 409c3bc407cSdh "%s line %d", p->path, __func__, __LINE__); \ 4109aed1621SDavid Hollister p->changed = 1; \ 4119aed1621SDavid Hollister p->enum_attempts = 0 4124c06356bSdh 4134c06356bSdh #define PHY_CHANGED_AT_LOCATION(pwp, p, func, line) \ 414c3bc407cSdh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, p, NULL, "%s changed in " \ 415c3bc407cSdh "%s line %d", p->path, func, line); \ 4169aed1621SDavid Hollister p->changed = 1; \ 4179aed1621SDavid Hollister p->enum_attempts = 0 4184c06356bSdh 4194c06356bSdh #define PHY_TYPE(pptr) \ 4204c06356bSdh (((pptr)->dtype == NOTHING)? "NOTHING" : \ 4214c06356bSdh (((pptr)->dtype == SATA)? "SATA" : \ 4224c06356bSdh (((pptr)->dtype == SAS)? "SAS" : "EXPANDER"))) 4234c06356bSdh 4244c06356bSdh #define IS_ROOT_PHY(pptr) (pptr->parent == NULL) 4254c06356bSdh 4264c06356bSdh #define PMCS_HIPRI(pwp, oq, c) \ 4274c06356bSdh (pwp->hipri_queue & (1 << PMCS_IQ_OTHER)) ? \ 4284c06356bSdh (PMCS_IOMB_HIPRI | PMCS_IOMB_IN_SAS(oq, c)) : \ 4294c06356bSdh (PMCS_IOMB_IN_SAS(oq, c)) 4304c06356bSdh 4314c06356bSdh #define SCHEDULE_WORK(hwp, wrk) \ 4324c06356bSdh (void) atomic_set_long_excl(&hwp->work_flags, wrk) 4334c06356bSdh 4344c06356bSdh /* 4354c06356bSdh * Check to see if the requested work bit is set. Either way, the bit will 4364c06356bSdh * be cleared upon return. 4374c06356bSdh */ 4384c06356bSdh #define WORK_SCHEDULED(hwp, wrk) \ 4394c06356bSdh (atomic_clear_long_excl(&hwp->work_flags, wrk) == 0) 4404c06356bSdh 4414c06356bSdh /* 4424c06356bSdh * Check to see if the requested work bit is set. The value will not be 4434c06356bSdh * changed in this case. The atomic_xx_nv operations can be quite expensive 4444c06356bSdh * so this should not be used in non-DEBUG code. 4454c06356bSdh */ 4464c06356bSdh #define WORK_IS_SCHEDULED(hwp, wrk) \ 4474c06356bSdh ((atomic_and_ulong_nv(&hwp->work_flags, (ulong_t)-1) & (1 << wrk)) != 0) 4484c06356bSdh 4494c06356bSdh #define WAIT_FOR(p, t, r) \ 45032b54db7SJesse Butler clock_t _lb = ddi_get_lbolt(); \ 4514c06356bSdh r = 0; \ 4524c06356bSdh while (!PMCS_COMMAND_DONE(p)) { \ 45332b54db7SJesse Butler clock_t _ret = cv_timedwait(&p->sleep_cv, \ 45432b54db7SJesse Butler &p->lock, _lb + drv_usectohz(t * 1000)); \ 45532b54db7SJesse Butler if (!PMCS_COMMAND_DONE(p) && _ret < 0) { \ 4564c06356bSdh r = 1; \ 4574c06356bSdh break; \ 4584c06356bSdh } \ 4594c06356bSdh } 4604c06356bSdh 4614c06356bSdh /* 4624c06356bSdh * Signal the next I/O completion thread to start running. 4634c06356bSdh */ 4644c06356bSdh 4654c06356bSdh #define PMCS_CQ_RUN_LOCKED(hwp) \ 4664c06356bSdh if (!STAILQ_EMPTY(&hwp->cq) || hwp->iocomp_cb_head) { \ 4674c06356bSdh pmcs_cq_thr_info_t *cqti; \ 4684c06356bSdh cqti = &hwp->cq_info.cq_thr_info \ 4694c06356bSdh [hwp->cq_info.cq_next_disp_thr]; \ 4704c06356bSdh hwp->cq_info.cq_next_disp_thr++; \ 4714c06356bSdh if (hwp->cq_info.cq_next_disp_thr == \ 4724c06356bSdh hwp->cq_info.cq_threads) { \ 4734c06356bSdh hwp->cq_info.cq_next_disp_thr = 0; \ 4744c06356bSdh } \ 4754c06356bSdh mutex_enter(&cqti->cq_thr_lock); \ 4764c06356bSdh cv_signal(&cqti->cq_cv); \ 4774c06356bSdh mutex_exit(&cqti->cq_thr_lock); \ 4788f514e74SDavid Hollister } 4794c06356bSdh 4804c06356bSdh #define PMCS_CQ_RUN(hwp) \ 4814c06356bSdh mutex_enter(&hwp->cq_lock); \ 4824c06356bSdh PMCS_CQ_RUN_LOCKED(hwp); \ 4834c06356bSdh mutex_exit(&hwp->cq_lock); 4844c06356bSdh 4854c06356bSdh 4864c06356bSdh /* 4874c06356bSdh * Watchdog/SCSA timer definitions 4884c06356bSdh */ 4894c06356bSdh /* usecs to SCSA watchdog ticks */ 4904c06356bSdh #define US2WT(x) (x)/10 4914c06356bSdh 4924c06356bSdh /* 4934c06356bSdh * More misc 4944c06356bSdh */ 4954c06356bSdh #define BYTE0(x) (((x) >> 0) & 0xff) 4964c06356bSdh #define BYTE1(x) (((x) >> 8) & 0xff) 4974c06356bSdh #define BYTE2(x) (((x) >> 16) & 0xff) 4984c06356bSdh #define BYTE3(x) (((x) >> 24) & 0xff) 4994c06356bSdh #define BYTE4(x) (((x) >> 32) & 0xff) 5004c06356bSdh #define BYTE5(x) (((x) >> 40) & 0xff) 5014c06356bSdh #define BYTE6(x) (((x) >> 48) & 0xff) 5024c06356bSdh #define BYTE7(x) (((x) >> 56) & 0xff) 5034c06356bSdh #define WORD0(x) (((x) >> 0) & 0xffff) 5044c06356bSdh #define WORD1(x) (((x) >> 16) & 0xffff) 5054c06356bSdh #define WORD2(x) (((x) >> 32) & 0xffff) 5064c06356bSdh #define WORD3(x) (((x) >> 48) & 0xffff) 5074c06356bSdh #define DWORD0(x) ((uint32_t)(x)) 5084c06356bSdh #define DWORD1(x) ((uint32_t)(((uint64_t)x) >> 32)) 5094c06356bSdh 5104c06356bSdh #define SAS_ADDR_FMT "0x%02x%02x%02x%02x%02x%02x%02x%02x" 5114c06356bSdh #define SAS_ADDR_PRT(x) x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7] 5124c06356bSdh 5134c06356bSdh #define PMCS_VALID_LINK_RATE(r) \ 5144c06356bSdh ((r == SAS_LINK_RATE_1_5GBIT) || (r == SAS_LINK_RATE_3GBIT) || \ 5154c06356bSdh (r == SAS_LINK_RATE_6GBIT)) 5164c06356bSdh 5174c06356bSdh /* 5184c06356bSdh * This is here to avoid inclusion of <sys/ctype.h> which is not lint clean. 5194c06356bSdh */ 5204c06356bSdh #define HEXDIGIT(x) (((x) >= '0' && (x) <= '9') || \ 5214c06356bSdh ((x) >= 'a' && (x) <= 'f') || ((x) >= 'A' && (x) <= 'F')) 5224c06356bSdh 5231f81b464SDavid Hollister #define NSECS_PER_SEC 1000000000UL 5241f81b464SDavid Hollister 5254c06356bSdh 5264c06356bSdh typedef void (*pmcs_cb_t) (pmcs_hw_t *, pmcwork_t *, uint32_t *); 5274c06356bSdh 5284c06356bSdh /* 5294c06356bSdh * Defines and structure used for tracing/logging information 5304c06356bSdh */ 5314c06356bSdh 5324c06356bSdh #define PMCS_TBUF_ELEM_SIZE 120 5334c06356bSdh #define PMCS_TBUF_NUM_ELEMS_DEF 100000 5344c06356bSdh 535c3bc407cSdh #define PMCS_TBUF_UA_MAX_SIZE 32 5364c06356bSdh typedef struct { 537c3bc407cSdh /* Target-specific data */ 538c3bc407cSdh uint16_t target_num; 539c3bc407cSdh char target_ua[PMCS_TBUF_UA_MAX_SIZE]; 540c3bc407cSdh /* PHY-specific data */ 541c3bc407cSdh uint8_t phy_sas_address[8]; 542c3bc407cSdh char phy_path[32]; 543c3bc407cSdh pmcs_dtype_t phy_dtype; 544c3bc407cSdh /* Log data */ 5454c06356bSdh timespec_t timestamp; 5461f81b464SDavid Hollister uint64_t fw_timestamp; 5474c06356bSdh char buf[PMCS_TBUF_ELEM_SIZE]; 5484c06356bSdh } pmcs_tbuf_t; 5494c06356bSdh 5504c06356bSdh /* 5514c06356bSdh * Firmware event log header format 5524c06356bSdh */ 5534c06356bSdh typedef struct pmcs_fw_event_hdr_s { 5544c06356bSdh uint32_t fw_el_signature; 5554c06356bSdh uint32_t fw_el_entry_start_offset; 5564c06356bSdh uint32_t fw_el_rsvd1; 5574c06356bSdh uint32_t fw_el_buf_size; 5584c06356bSdh uint32_t fw_el_rsvd2; 5594c06356bSdh uint32_t fw_el_oldest_idx; 5604c06356bSdh uint32_t fw_el_latest_idx; 5614c06356bSdh uint32_t fw_el_entry_size; 5624c06356bSdh } pmcs_fw_event_hdr_t; 5634c06356bSdh 5641f81b464SDavid Hollister /* 5651f81b464SDavid Hollister * Firmware event log entry format 5661f81b464SDavid Hollister */ 5671f81b464SDavid Hollister typedef struct pmcs_fw_event_entry_s { 5681f81b464SDavid Hollister uint32_t num_words : 3, 5691f81b464SDavid Hollister reserved : 25, 5701f81b464SDavid Hollister severity: 4; 5711f81b464SDavid Hollister uint32_t ts_upper; 5721f81b464SDavid Hollister uint32_t ts_lower; 5731f81b464SDavid Hollister uint32_t seq_num; 5741f81b464SDavid Hollister uint32_t logw0; 5751f81b464SDavid Hollister uint32_t logw1; 5761f81b464SDavid Hollister uint32_t logw2; 5771f81b464SDavid Hollister uint32_t logw3; 5781f81b464SDavid Hollister } pmcs_fw_event_entry_t; 5791f81b464SDavid Hollister 5801f81b464SDavid Hollister #define PMCS_FWLOG_TIMER_DIV 8 /* fw timer has 8ns granularity */ 5811f81b464SDavid Hollister #define PMCS_FWLOG_AAP1_SIG 0x1234AAAA 5821f81b464SDavid Hollister #define PMCS_FWLOG_IOP_SIG 0x5678CCCC 5831f81b464SDavid Hollister 584658280b6SDavid Hollister /* 585658280b6SDavid Hollister * Receptacle information 586658280b6SDavid Hollister */ 587658280b6SDavid Hollister #define PMCS_NUM_RECEPTACLES 2 588658280b6SDavid Hollister 589658280b6SDavid Hollister #define PMCS_RECEPT_LABEL_0 "SAS0" 590658280b6SDavid Hollister #define PMCS_RECEPT_LABEL_1 "SAS1" 591658280b6SDavid Hollister 5921f81b464SDavid Hollister #define PMCS_RECEPT_PM_0 "f0" 5931f81b464SDavid Hollister #define PMCS_RECEPT_PM_1 "f" 594658280b6SDavid Hollister 5954c06356bSdh #ifdef __cplusplus 5964c06356bSdh } 5974c06356bSdh #endif 5984c06356bSdh #endif /* _PMCS_DEF_H */ 599