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