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