ahcivar.h revision 6187:27b2dddfa732
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/*
23 * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27
28#ifndef _AHCIVAR_H
29#define	_AHCIVAR_H
30
31#pragma ident	"%Z%%M%	%I%	%E% SMI"
32
33#ifdef	__cplusplus
34extern "C" {
35#endif
36
37/* Type for argument of event handler */
38typedef	struct ahci_event_arg {
39	void		*ahciea_ctlp;
40	void		*ahciea_portp;
41	uint32_t	ahciea_event;
42} ahci_event_arg_t;
43
44/* Warlock annotation */
45_NOTE(DATA_READABLE_WITHOUT_LOCK(ahci_event_arg_t::ahciea_ctlp))
46_NOTE(DATA_READABLE_WITHOUT_LOCK(ahci_event_arg_t::ahciea_portp))
47_NOTE(DATA_READABLE_WITHOUT_LOCK(ahci_event_arg_t::ahciea_event))
48
49/*
50 * flags for ahciport_flags
51 *
52 * AHCI_PORT_FLAG_SPINUP: this flag will be set when a HBA which supports
53 * staggered spin-up needs to do a spin-up.
54 *
55 * AHCI_PORT_FLAG_MOPPING: this flag will be set when the HBA is stopped,
56 * and all the outstanding commands need to be aborted and sent to upper
57 * layers.
58 *
59 * AHCI_PORT_FLAG_POLLING: this flag will be set when the interrupt is
60 * disabled, and the command is executed in POLLING mode.
61 *
62 * AHCI_PORT_FLAG_RQSENSE: this flag will be set when a REQUEST SENSE which
63 * is used to retrieve sense data is being executed.
64 *
65 * AHCI_PORT_FLAG_STARTED: this flag will be set when the port is started,
66 * that is PxCMD.ST is set with '1', and be cleared when the port is put into
67 * idle, that is PxCMD.ST is changed from '1' to '0'.
68 *
69 * AHCI_PORT_FLAG_RDLOGEXT: this flag will be set when a READ LOG EXT which
70 * is used to retrieve NCQ failure context is being executed.
71 *
72 * AHCI_PORT_FLAG_NODEV: this flag will be set when a device is found gone
73 * during ahci_restart_port_wait_till_ready process.
74 */
75#define	AHCI_PORT_FLAG_SPINUP	0x01
76#define	AHCI_PORT_FLAG_MOPPING	0x02
77#define	AHCI_PORT_FLAG_POLLING	0x04
78#define	AHCI_PORT_FLAG_RQSENSE	0x08
79#define	AHCI_PORT_FLAG_STARTED	0x10
80#define	AHCI_PORT_FLAG_RDLOGEXT	0x20
81#define	AHCI_PORT_FLAG_NODEV	0x40
82
83typedef struct ahci_port {
84	/* The physical port number */
85	uint8_t			ahciport_port_num;
86
87	/* Type of the device attached to the port */
88	uint8_t			ahciport_device_type;
89	/* State of the port */
90	uint32_t		ahciport_port_state;
91
92	/*
93	 * AHCI_PORT_FLAG_SPINUP
94	 * AHCI_PORT_FLAG_MOPPING
95	 * AHCI_PORT_FLAG_POLLING
96	 * AHCI_PORT_FLAG_RQSENSE
97	 * AHCI_PORT_FLAG_STARTED
98	 * AHCI_PORT_FLAG_RDLOGEXT
99	 * AHCI_PORT_FLAG_NODEV
100	 */
101	int			ahciport_flags;
102
103	/* Pointer to received FIS structure */
104	ahci_rcvd_fis_t		*ahciport_rcvd_fis;
105	ddi_dma_handle_t	ahciport_rcvd_fis_dma_handle;
106	ddi_acc_handle_t	ahciport_rcvd_fis_acc_handle;
107	ddi_dma_cookie_t	ahciport_rcvd_fis_dma_cookie;
108
109	/* Pointer to command list structure */
110	ahci_cmd_header_t	*ahciport_cmd_list;
111	ddi_dma_handle_t	ahciport_cmd_list_dma_handle;
112	ddi_acc_handle_t	ahciport_cmd_list_acc_handle;
113	ddi_dma_cookie_t	ahciport_cmd_list_dma_cookie;
114
115	/* Pointer to cmmand table structure */
116	ahci_cmd_table_t	\
117			*ahciport_cmd_tables[AHCI_PORT_MAX_CMD_SLOTS];
118	ddi_dma_handle_t	\
119			ahciport_cmd_tables_dma_handle[AHCI_PORT_MAX_CMD_SLOTS];
120	ddi_acc_handle_t	\
121			ahciport_cmd_tables_acc_handle[AHCI_PORT_MAX_CMD_SLOTS];
122
123	/* Condition variable used for sync mode commands */
124	kcondvar_t		ahciport_cv;
125
126	/* The whole mutex for the port structure */
127	kmutex_t		ahciport_mutex;
128
129	/* The maximum number of tags for native queuing command transfers */
130	int			ahciport_max_ncq_tags;
131
132	/* Keep the tags of all pending non-ncq commands */
133	uint32_t		ahciport_pending_tags;
134
135	/*
136	 * Keep the tags of all pending ncq commands
137	 * (READ/WRITE FPDMA QUEUED)
138	 */
139	uint32_t		ahciport_pending_ncq_tags;
140
141	/* Keep all the pending sata packets */
142	sata_pkt_t		*ahciport_slot_pkts[AHCI_PORT_MAX_CMD_SLOTS];
143
144	/* Keep the error retrieval sata packet */
145	sata_pkt_t		*ahciport_err_retri_pkt;
146
147	/*
148	 * SATA HBA driver is supposed to remember and maintain device
149	 * reset state. While the reset is in progress, it doesn't accept
150	 * any more commands until receiving the command with
151	 * SATA_CLEAR_DEV_RESET_STATE flag and SATA_IGNORE_DEV_RESET_STATE.
152	 */
153	int			ahciport_reset_in_progress;
154
155	/* This is for error recovery handler */
156	ahci_event_arg_t	*ahciport_event_args;
157
158	/* This is to calculate how many mops are in progress */
159	int			ahciport_mop_in_progress;
160} ahci_port_t;
161
162/* Warlock annotation */
163_NOTE(READ_ONLY_DATA(ahci_port_t::ahciport_rcvd_fis_dma_handle))
164_NOTE(READ_ONLY_DATA(ahci_port_t::ahciport_cmd_list_dma_handle))
165_NOTE(READ_ONLY_DATA(ahci_port_t::ahciport_cmd_tables_dma_handle))
166_NOTE(MUTEX_PROTECTS_DATA(ahci_port_t::ahciport_mutex,
167				    ahci_port_t::ahciport_device_type))
168_NOTE(MUTEX_PROTECTS_DATA(ahci_port_t::ahciport_mutex,
169				    ahci_port_t::ahciport_port_state))
170_NOTE(MUTEX_PROTECTS_DATA(ahci_port_t::ahciport_mutex,
171				    ahci_port_t::ahciport_flags))
172_NOTE(MUTEX_PROTECTS_DATA(ahci_port_t::ahciport_mutex,
173				    ahci_port_t::ahciport_pending_tags))
174_NOTE(MUTEX_PROTECTS_DATA(ahci_port_t::ahciport_mutex,
175				    ahci_port_t::ahciport_slot_pkts))
176_NOTE(MUTEX_PROTECTS_DATA(ahci_port_t::ahciport_mutex,
177				    ahci_port_t::ahciport_reset_in_progress))
178_NOTE(MUTEX_PROTECTS_DATA(ahci_port_t::ahciport_mutex,
179				    ahci_port_t::ahciport_mop_in_progress))
180
181typedef struct ahci_ctl {
182	dev_info_t		*ahcictl_dip;
183	/* To map port number to cport number */
184	uint8_t			ahcictl_port_to_cport[AHCI_MAX_PORTS];
185	/* To map cport number to port number */
186	uint8_t			ahcictl_cport_to_port[AHCI_MAX_PORTS];
187
188	/* Number of controller ports */
189	int			ahcictl_num_ports;
190	/* Number of command slots */
191	int			ahcictl_num_cmd_slots;
192	/* Number of implemented ports */
193	int			ahcictl_num_implemented_ports;
194	/* Bit map to indicate which port is implemented */
195	uint32_t		ahcictl_ports_implemented;
196	ahci_port_t		*ahcictl_ports[AHCI_MAX_PORTS];
197
198	int			ahcictl_flags;
199	int			ahcictl_power_level;
200	off_t			ahcictl_pmcsr_offset;
201
202	/*
203	 * AHCI_CAP_PIO_MDRQ
204	 * AHCI_CAP_NO_MCMDLIST_NONQUEUE
205	 * AHCI_CAP_NCQ
206	 * AHCI_CAP_PM
207	 */
208	int			ahcictl_cap;
209
210	/* Pci configuration space handle */
211	ddi_acc_handle_t	ahcictl_pci_conf_handle;
212
213	/* Mapping into bar 5 - AHCI base address */
214	ddi_acc_handle_t	ahcictl_ahci_acc_handle;
215	uintptr_t		ahcictl_ahci_addr;
216
217	/* Pointer used for sata hba framework registration */
218	struct sata_hba_tran	*ahcictl_sata_hba_tran;
219
220	/* DMA attributes for the data buffer */
221	ddi_dma_attr_t		ahcictl_buffer_dma_attr;
222	/* DMA attributes for the rcvd FIS */
223	ddi_dma_attr_t		ahcictl_rcvd_fis_dma_attr;
224	/* DMA attributes for the command list */
225	ddi_dma_attr_t		ahcictl_cmd_list_dma_attr;
226	/* DMA attributes for command tables */
227	ddi_dma_attr_t		ahcictl_cmd_table_dma_attr;
228
229	/* Used for watchdog handler */
230	timeout_id_t		ahcictl_timeout_id;
231
232	/* Per controller mutex */
233	kmutex_t		ahcictl_mutex;
234
235	/* Components for interrupt */
236	ddi_intr_handle_t	*ahcictl_intr_htable;   /* For array of intrs */
237	int			ahcictl_intr_type; /* What type of interrupt */
238	int			ahcictl_intr_cnt;  /* # of intrs returned */
239	size_t			ahcictl_intr_size; /* Size of intr array */
240	uint_t			ahcictl_intr_pri;  /* Intr priority */
241	int			ahcictl_intr_cap;  /* Intr capabilities */
242
243	/* Taskq for handling event */
244	ddi_taskq_t		*ahcictl_event_taskq;
245} ahci_ctl_t;
246
247/* Warlock annotation */
248_NOTE(READ_ONLY_DATA(ahci_ctl_t::ahcictl_ports))
249_NOTE(READ_ONLY_DATA(ahci_ctl_t::ahcictl_cport_to_port))
250_NOTE(READ_ONLY_DATA(ahci_ctl_t::ahcictl_port_to_cport))
251
252_NOTE(MUTEX_PROTECTS_DATA(ahci_ctl_t::ahcictl_mutex,
253					ahci_ctl_t::ahcictl_power_level))
254_NOTE(MUTEX_PROTECTS_DATA(ahci_ctl_t::ahcictl_mutex,
255					ahci_ctl_t::ahcictl_flags))
256_NOTE(MUTEX_PROTECTS_DATA(ahci_ctl_t::ahcictl_mutex,
257					ahci_ctl_t::ahcictl_timeout_id))
258
259#define	AHCI_SUCCESS	(0)  /* Successful return */
260#define	AHCI_TIMEOUT	(1)  /* Timed out */
261#define	AHCI_FAILURE	(-1) /* Unsuccessful return */
262
263/* Flags for ahcictl_flags */
264#define	AHCI_ATTACH		0x1
265#define	AHCI_DETACH		0x2
266#define	AHCI_SUSPEND		0x4
267
268/* Values for ahcictl_cap */
269/* PIO Multiple DRQ Block */
270#define	AHCI_CAP_PIO_MDRQ		0x1
271/*
272 * Multiple command slots in the command list cannot be used for
273 * non-queued commands
274 */
275#define	AHCI_CAP_NO_MCMDLIST_NONQUEUE	0x2
276/* Native Command Queuing (NCQ) */
277#define	AHCI_CAP_NCQ			0x4
278/* Power Management (PM) */
279#define	AHCI_CAP_PM			0x8
280
281/* Flags controlling the restart port behavior */
282#define	AHCI_PORT_RESET		0x0001	/* Reset the port */
283#define	AHCI_PORT_INIT		0x0002	/* Initialize port */
284#define	AHCI_RESET_NO_EVENTS_UP	0x0004	/* Don't send reset events up */
285
286#define	ERR_RETRI_CMD_IN_PROGRESS(ahci_portp)		\
287	(ahci_portp->ahciport_flags &			\
288	(AHCI_PORT_FLAG_RQSENSE|AHCI_PORT_FLAG_RDLOGEXT))
289
290#define	NON_NCQ_CMD_IN_PROGRESS(ahci_portp)		\
291	(!ERR_RETRI_CMD_IN_PROGRESS(ahci_portp) &&	\
292	ahci_portp->ahciport_pending_tags != 0 &&	\
293	ahci_portp->ahciport_pending_ncq_tags == 0)
294
295#define	NCQ_CMD_IN_PROGRESS(ahci_portp)			\
296	(!ERR_RETRI_CMD_IN_PROGRESS(ahci_portp) &&	\
297	ahci_portp->ahciport_pending_ncq_tags != 0)
298
299/* Command type for ahci_claim_free_slot routine */
300#define	AHCI_NON_NCQ_CMD	0x0
301#define	AHCI_NCQ_CMD		0x1
302#define	AHCI_ERR_RETRI_CMD	0x2
303
304/* State values for ahci_attach */
305#define	AHCI_ATTACH_STATE_NONE			(0x1 << 0)
306#define	AHCI_ATTACH_STATE_STATEP_ALLOC		(0x1 << 1)
307#define	AHCI_ATTACH_STATE_REG_MAP		(0x1 << 2)
308#define	AHCI_ATTACH_STATE_PCICFG_SETUP		(0x1 << 3)
309#define	AHCI_ATTACH_STATE_INTR_ADDED		(0x1 << 4)
310#define	AHCI_ATTACH_STATE_MUTEX_INIT		(0x1 << 5)
311#define	AHCI_ATTACH_STATE_PORT_ALLOC		(0x1 << 6)
312#define	AHCI_ATTACH_STATE_ERR_RECV_TASKQ	(0x1 << 7)
313#define	AHCI_ATTACH_STATE_HW_INIT		(0x1 << 8)
314#define	AHCI_ATTACH_STATE_TIMEOUT_ENABLED	(0x1 << 9)
315
316/* Interval used for delay */
317#define	AHCI_10MS_TICKS	(drv_usectohz(10000))	/* ticks in 10 millisec */
318#define	AHCI_1MS_TICKS	(drv_usectohz(1000))	/* ticks in 1 millisec */
319#define	AHCI_100US_TICKS	(drv_usectohz(100))	/* ticks in 100  */
320#define	AHCI_1MS_USECS	(1000)			/* usecs in 1 millisec */
321
322/*
323 * The following values are the numbers of times to retry polled requests.
324 */
325#define	AHCI_POLLRATE_HBA_RESET		100
326#define	AHCI_POLLRATE_PORT_SSTATUS	10
327#define	AHCI_POLLRATE_PORT_TFD_ERROR	1100
328#define	AHCI_POLLRATE_PORT_IDLE		50
329#define	AHCI_POLLRATE_PORT_SOFTRESET	100
330#define	AHCI_POLLRATE_GET_SPKT		100
331
332
333/* Clearing & setting the n'th bit in a given tag */
334#define	CLEAR_BIT(tag, bit)	(tag &= ~(0x1<<bit))
335#define	SET_BIT(tag, bit)	(tag |= (0x1<<bit))
336
337
338#if DEBUG
339
340#define	AHCI_DEBUG		1
341
342#define	AHCIDBG_INIT		0x0001
343#define	AHCIDBG_ENTRY		0x0002
344#define	AHCIDBG_DUMP_PRB	0x0004
345#define	AHCIDBG_EVENT		0x0008
346#define	AHCIDBG_POLL_LOOP	0x0010
347#define	AHCIDBG_PKTCOMP		0x0020
348#define	AHCIDBG_TIMEOUT		0x0040
349#define	AHCIDBG_INFO		0x0080
350#define	AHCIDBG_VERBOSE		0x0100
351#define	AHCIDBG_INTR		0x0200
352#define	AHCIDBG_ERRS		0x0400
353#define	AHCIDBG_COOKIES		0x0800
354#define	AHCIDBG_POWER		0x1000
355#define	AHCIDBG_COMMAND		0x2000
356#define	AHCIDBG_SENSEDATA	0x4000
357#define	AHCIDBG_NCQ		0x8000
358#define	AHCIDBG_PM		0x10000
359
360extern int ahci_debug_flag;
361
362#define	AHCIDBG0(flag, ahci_ctlp, format)			\
363	if (ahci_debug_flags & (flag)) {			\
364		ahci_log(ahci_ctlp, CE_WARN, format);		\
365	}
366
367#define	AHCIDBG1(flag, ahci_ctlp, format, arg1)			\
368	if (ahci_debug_flags & (flag)) {			\
369		ahci_log(ahci_ctlp, CE_WARN, format, arg1);	\
370	}
371
372#define	AHCIDBG2(flag, ahci_ctlp, format, arg1, arg2)			\
373	if (ahci_debug_flags & (flag)) {				\
374		ahci_log(ahci_ctlp, CE_WARN, format, arg1, arg2);	\
375	}
376
377#define	AHCIDBG3(flag, ahci_ctlp, format, arg1, arg2, arg3)		\
378	if (ahci_debug_flags & (flag)) {				\
379		ahci_log(ahci_ctlp, CE_WARN, format, arg1, arg2, arg3); \
380	}
381
382#define	AHCIDBG4(flag, ahci_ctlp, format, arg1, arg2, arg3, arg4)	\
383	if (ahci_debug_flags & (flag)) {				\
384		ahci_log(ahci_ctlp, CE_WARN, format, arg1, arg2, arg3, arg4); \
385	}
386
387#define	AHCIDBG5(flag, ahci_ctlp, format, arg1, arg2, arg3, arg4, arg5)	\
388	if (ahci_debug_flags & (flag)) {				\
389		ahci_log(ahci_ctlp, CE_WARN, format, arg1, arg2,	\
390		    arg3, arg4, arg5); 					\
391	}
392#else
393
394#define	AHCIDBG0(flag, dip, frmt)
395#define	AHCIDBG1(flag, dip, frmt, arg1)
396#define	AHCIDBG2(flag, dip, frmt, arg1, arg2)
397#define	AHCIDBG3(flag, dip, frmt, arg1, arg2, arg3)
398#define	AHCIDBG4(flag, dip, frmt, arg1, arg2, arg3, arg4)
399#define	AHCIDBG5(flag, dip, frmt, arg1, arg2, arg3, arg4, arg5)
400
401#endif /* DEBUG */
402
403
404#ifdef	__cplusplus
405}
406#endif
407
408#endif /* _AHCIVAR_H */
409