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 (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
24  */
25 
26 #ifndef _SI3124VAR_H
27 #define	_SI3124VAR_H
28 
29 #ifdef	__cplusplus
30 extern "C" {
31 #endif
32 
33 #define	SI3124_MAX_PORTS		4
34 #define	SI3132_MAX_PORTS		2
35 #define	SI3531_MAX_PORTS		1
36 #define	SI_MAX_PORTS			SI3124_MAX_PORTS
37 
38 #define	SI_LOGBUF_LEN			512
39 
40 #define	SI_SUCCESS			(0)	/* successful return */
41 #define	SI_TIMEOUT			(1)	/* timed out */
42 #define	SI_FAILURE			(-1)	/* unsuccessful return */
43 
44 #define	SI_MAX_SGT_TABLES_PER_PRB	21844
45 #define	SI_DEFAULT_SGT_TABLES_PER_PRB	85
46 #define	SI_MIN_SGT_TABLES_PER_PRB	1
47 /*
48  * While the si_sge_t and si_sgt_t correspond to the actual SGE and SGT
49  * definitions as per the datasheet, the si_sgblock_t (i.e scatter gather
50  * block) is a logical data structure which can hold dynamic SGEs and it
51  * is tunable through global variables /etc/system si3124:si_dma_sg_number.
52  * The idea is to use multiple tunable chained SGT tables per each PRB request.
53  */
54 
55 typedef struct si_sgblock {
56 	si_sgt_t sgb_sgt[1];
57 } si_sgblock_t;
58 
59 /*
60  * Each SGT (Scatter Gather Table) has 4 SGEs (Scatter Gather Entries).
61  * But each SGT effectively can host only 3 SGEs since the last SGE entry
62  * is used to hold a link to the next SGT in the chain. However the last
63  * SGT in the chain can host all the 4 entries since it does not need to
64  * link any more.
65  */
66 #define	SGE_LENGTH(x)	(3*(x)+1)
67 #define	SI_DEFAULT_SGL_LENGTH	SGE_LENGTH(SI_DEFAULT_SGT_TABLES_PER_PRB)
68 
69 /* Argument to be used for calls to timeout() */
70 typedef struct si_event_arg {
71 	void *siea_ctlp;
72 	int siea_port;
73 } si_event_arg_t;
74 
75 typedef struct si_portmult_state {
76 	int sipm_num_ports;
77 	uint8_t sipm_port_type[15];
78 	/* one of PORT_TYPE_[NODEV | MULTIPLIER | ATAPI | DISK | UNKNOWN] */
79 
80 	/*
81 	 * sipm_port_type[] is good enough to capture the state of ports
82 	 * behind the multiplier. Since any of the port behind a multiplier
83 	 * is accessed through the same main controller port, we don't need
84 	 * additional si_port_state_t here.
85 	 */
86 
87 } si_portmult_state_t;
88 
89 
90 /* The following are for port types */
91 #define	PORT_TYPE_NODEV		0x0
92 #define	PORT_TYPE_MULTIPLIER	0x1
93 #define	PORT_TYPE_ATAPI		0x2
94 #define	PORT_TYPE_DISK		0x3
95 #define	PORT_TYPE_UNKNOWN	0x4
96 
97 /* The following are for active state */
98 #define	PORT_INACTIVE		0x0
99 #define	PORT_ACTIVE		0x1
100 
101 typedef struct si_port_state {
102 	struct si_ctl_state *siport_ctlp;	/* back pointer to controller */
103 
104 	uint8_t siport_port_type;
105 	/* one of PORT_TYPE_[NODEV | MULTIPLIER | ATAPI | DISK | UNKNOWN] */
106 
107 	uint8_t siport_active;		/* one of ACTIVE or INACTIVE */
108 
109 	uint8_t siport_port_num;	/* port number */
110 
111 	si_portmult_state_t siport_portmult_state;
112 
113 	si_prb_t *siport_prbpool; 	/* These are 31 incore PRBs */
114 	uint64_t siport_prbpool_physaddr;
115 	ddi_dma_handle_t siport_prbpool_dma_handle;
116 	ddi_acc_handle_t siport_prbpool_acc_handle;
117 
118 
119 	si_sgblock_t *siport_sgbpool; 	/* These are 31 incore sg blocks */
120 	uint64_t siport_sgbpool_physaddr;
121 	ddi_dma_handle_t siport_sgbpool_dma_handle;
122 	ddi_acc_handle_t siport_sgbpool_acc_handle;
123 
124 	kmutex_t siport_mutex; 		/* main per port mutex */
125 	uint32_t siport_pending_tags;	/* remembers the pending tags */
126 	sata_pkt_t *siport_slot_pkts[SI_NUM_SLOTS];
127 
128 	/*
129 	 * While the reset is in progress, we don't accept any more commands
130 	 * until we receive the command with SATA_CLEAR_DEV_RESET_STATE flag.
131 	 * However any commands with SATA_IGNORE_DEV_RESET_STATE are allowed in
132 	 * during such blockage.
133 	 */
134 	int siport_reset_in_progress;
135 
136 	/* Argument to be used for calls to timeout() */
137 	si_event_arg_t *siport_event_args;
138 
139 	/*
140 	 * We mop the commands for either abort, reset, timeout or
141 	 * error handling cases. This counts how many mops are in progress.
142 	 * It is also used to return BUSY in tran_start if a mop is going on.
143 	 */
144 	int mopping_in_progress;
145 
146 	/* error recovery related info */
147 	uint32_t siport_err_tags_SDBERROR;
148 	uint32_t siport_err_tags_nonSDBERROR;
149 	int siport_pending_ncq_count;
150 
151 } si_port_state_t;
152 
153 /* Warlock annotation */
154 _NOTE(MUTEX_PROTECTS_DATA(si_port_state_t::siport_mutex, si_port_state_t))
155 _NOTE(READ_ONLY_DATA(si_port_state_t::siport_prbpool_dma_handle))
156 _NOTE(READ_ONLY_DATA(si_port_state_t::siport_sgbpool_dma_handle))
157 _NOTE(DATA_READABLE_WITHOUT_LOCK(si_port_state_t::siport_ctlp))
158 _NOTE(DATA_READABLE_WITHOUT_LOCK(si_port_state_t::siport_port_num))
159 
160 
161 typedef struct si_ctl_state {
162 
163 	dev_info_t *sictl_devinfop;
164 
165 	int sictl_num_ports;	/* number of controller ports */
166 	si_port_state_t *sictl_ports[SI_MAX_PORTS];
167 
168 	int sictl_devid; /* device id of the controller */
169 	int sictl_flags; /* some important state of controller */
170 	int sictl_power_level;
171 
172 	/* pci config space handle */
173 	ddi_acc_handle_t sictl_pci_conf_handle;
174 
175 	/* mapping into bar 0 */
176 	ddi_acc_handle_t sictl_global_acc_handle;
177 	uintptr_t sictl_global_addr;
178 
179 	/* mapping into bar 1 */
180 	ddi_acc_handle_t sictl_port_acc_handle;
181 	uintptr_t sictl_port_addr;
182 
183 	struct sata_hba_tran *sictl_sata_hba_tran;
184 	timeout_id_t sictl_timeout_id;
185 
186 	kmutex_t sictl_mutex; 			/* per controller mutex */
187 
188 	ddi_intr_handle_t *sictl_htable;	/* For array of interrupts */
189 	int sictl_intr_type;			/* What type of interrupt */
190 	int sictl_intr_cnt;			/* # of intrs count returned */
191 	size_t sictl_intr_size;			/* Size of intr array */
192 	uint_t sictl_intr_pri;			/* Interrupt priority */
193 	int sictl_intr_cap;			/* Interrupt capabilities */
194 	int fm_capabilities;			/* FMA capabilities */
195 
196 } si_ctl_state_t;
197 
198 /* Warlock annotation */
199 _NOTE(MUTEX_PROTECTS_DATA(si_ctl_state_t::sictl_mutex,
200 					si_ctl_state_t::sictl_ports))
201 _NOTE(MUTEX_PROTECTS_DATA(si_ctl_state_t::sictl_mutex,
202 					si_ctl_state_t::sictl_power_level))
203 _NOTE(MUTEX_PROTECTS_DATA(si_ctl_state_t::sictl_mutex,
204 					si_ctl_state_t::sictl_flags))
205 _NOTE(MUTEX_PROTECTS_DATA(si_ctl_state_t::sictl_mutex,
206 					si_ctl_state_t::sictl_timeout_id))
207 _NOTE(DATA_READABLE_WITHOUT_LOCK(si_ctl_state_t::sictl_ports))
208 /*
209  * flags for si_flags
210  */
211 #define	SI_PM			0x01
212 #define	SI_ATTACH		0x02
213 #define	SI_DETACH		0x04
214 #define	SI_NO_TIMEOUTS		0x08
215 #define	SI_FRAMEWORK_ATTACHED	0x10	/* are we attached to framework ? */
216 
217 /* progress values for si_attach */
218 #define	ATTACH_PROGRESS_NONE			(1<<0)
219 #define	ATTACH_PROGRESS_STATEP_ALLOC		(1<<1)
220 #define	ATTACH_PROGRESS_INIT_FMA		(1<<2)
221 #define	ATTACH_PROGRESS_CONF_HANDLE		(1<<3)
222 #define	ATTACH_PROGRESS_BAR0_MAP		(1<<4)
223 #define	ATTACH_PROGRESS_BAR1_MAP		(1<<5)
224 #define	ATTACH_PROGRESS_INTR_ADDED		(1<<6)
225 #define	ATTACH_PROGRESS_MUTEX_INIT		(1<<7)
226 #define	ATTACH_PROGRESS_HW_INIT			(1<<8)
227 
228 #define	SI_10MS_TICKS	(drv_usectohz(10000))	/* ticks in 10 millisec */
229 #define	SI_1MS_TICKS	(drv_usectohz(1000))	/* ticks in 1 millisec */
230 #define	SI_1MS_USECS	(1000)			/* usecs in 1 millisec */
231 #define	SI_POLLRATE_SOFT_RESET		1000
232 #define	SI_POLLRATE_SSTATUS		10
233 #define	SI_POLLRATE_PORTREADY		50
234 #define	SI_POLLRATE_SLOTSTATUS		50
235 #define	SI_POLLRATE_RECOVERPORTMULT	1000
236 
237 #define	PORTMULT_CONTROL_PORT		0xf
238 
239 /* clearing & setting the n'th bit in a given tag */
240 #define	CLEAR_BIT(tag, bit)	(tag &= ~(0x1<<bit))
241 #define	SET_BIT(tag, bit)	(tag |= (0x1<<bit))
242 
243 #if DEBUG
244 
245 #define	SI_DEBUG	1
246 
247 #endif /* DEBUG */
248 
249 /* si_debug_flags */
250 #define	SIDBG_TEST	0x0001
251 #define	SIDBG_INIT	0x0002
252 #define	SIDBG_ENTRY	0x0004
253 #define	SIDBG_DUMP_PRB	0x0008
254 #define	SIDBG_EVENT	0x0010
255 #define	SIDBG_POLL_LOOP	0x0020
256 #define	SIDBG_PKTCOMP	0x0040
257 #define	SIDBG_TIMEOUT	0x0080
258 #define	SIDBG_INFO	0x0100
259 #define	SIDBG_VERBOSE	0x0200
260 #define	SIDBG_INTR	0x0400
261 #define	SIDBG_ERRS	0x0800
262 #define	SIDBG_COOKIES	0x1000
263 #define	SIDBG_POWER	0x2000
264 #define	SIDBG_RESET	0x4000
265 
266 extern uint32_t si_debug_flags;
267 
268 #define	SIDBG(flag, format, args ...) \
269 	if (si_debug_flags & (flag)) { \
270 		si_log(NULL, NULL, format, ## args); \
271 	}
272 
273 #define	SIDBG_P(flag, si_portp, format, args ...) \
274 	if (si_debug_flags & (flag)) { \
275 		si_log(NULL, si_portp, format, ## args); \
276 	}
277 
278 #define	SIDBG_C(flag, si_ctlp, format, args ...) \
279 	if (si_debug_flags & (flag)) { \
280 		si_log(si_ctlp, NULL, format, ## args); \
281 	}
282 
283 
284 /* Flags controlling the reset behavior */
285 #define	SI_PORT_RESET		0x1	/* Reset the port */
286 #define	SI_DEVICE_RESET		0x2	/* Reset the device, not the port */
287 #define	SI_RESET_NO_EVENTS_UP	0x4	/* Don't send reset events up */
288 
289 #ifdef	__cplusplus
290 }
291 #endif
292 
293 #endif /* _SI3124VAR_H */
294