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
27extern "C" {
28#endif
29
30typedef 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
72struct 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 */
216typedef 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
226struct 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)
261typedef 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 */
309typedef 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
526typedef 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
536typedef 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 */
553typedef 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 */
567typedef 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