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