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