qlt.h revision 10428:3386c7875cc2
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 * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23 * Use is subject to license terms.
24 */
25#ifndef	_QLT_H
26#define	_QLT_H
27
28#include <stmf_defines.h>
29#include <qlt_regs.h>
30
31#ifdef	__cplusplus
32extern "C" {
33#endif
34
35/*
36 * Qlogic logging
37 */
38extern int enable_extended_logging;
39
40/*
41 * Caution: 1) LOG will be available in debug/non-debug mode
42 *	    2) Anything which can potentially flood the log should be under
43 *	       extended logging, and use QLT_EXT_LOG.
44 *	    3) Don't use QLT_EXT_LOG in performance-critical code path, such
45 *	       as normal SCSI I/O code path. It could hurt system performance.
46 *	    4) Use kmdb to change enable_extened_logging in the fly to adjust
47 *	       tracing
48 */
49#define	QLT_EXT_LOG(log_ident, ...)	\
50		if (enable_extended_logging) {	\
51			stmf_trace(log_ident, __VA_ARGS__);	\
52		}
53
54#define	QLT_LOG(log_ident, ...)	\
55	stmf_trace(log_ident, __VA_ARGS__)
56
57/*
58 * Error codes. FSC stands for Failure sub code.
59 */
60#define	QLT_FAILURE			FCT_FCA_FAILURE
61#define	QLT_SUCCESS			FCT_SUCCESS
62#define	QLT_FSC(x)			((uint64_t)(x) << 40)
63#define	QLT_DMA_STUCK			(QLT_FAILURE | QLT_FSC(1))
64#define	QLT_MAILBOX_STUCK		(QLT_FAILURE | QLT_FSC(2))
65#define	QLT_ROM_STUCK			(QLT_FAILURE | QLT_FSC(3))
66#define	QLT_UNEXPECTED_RESPONSE		(QLT_FAILURE | QLT_FSC(4))
67#define	QLT_MBOX_FAILED			(QLT_FAILURE | QLT_FSC(5))
68#define	QLT_MBOX_NOT_INITIALIZED	(QLT_FAILURE | QLT_FSC(6))
69#define	QLT_MBOX_BUSY			(QLT_FAILURE | QLT_FSC(7))
70#define	QLT_MBOX_ABORTED		(QLT_FAILURE | QLT_FSC(8))
71#define	QLT_MBOX_TIMEOUT		(QLT_FAILURE | QLT_FSC(9))
72#define	QLT_RESP_TIMEOUT		(QLT_FAILURE | QLT_FSC(10))
73#define	QLT_FLASH_TIMEOUT		(QLT_FAILURE | QLT_FSC(11))
74#define	QLT_FLASH_ACCESS_ERROR		(QLT_FAILURE | QLT_FSC(12))
75#define	QLT_BAD_NVRAM_DATA		(QLT_FAILURE | QLT_FSC(13))
76#define	QLT_FIRMWARE_ERROR_CODE		(QLT_FAILURE | QLT_FSC(14))
77
78#define	QLT_FIRMWARE_ERROR(s, c1, c2)	(QLT_FIRMWARE_ERROR_CODE | \
79	(((uint64_t)s) << 32) | (((uint64_t)c1) << 24) | ((uint64_t)c2))
80
81extern uint32_t fw2400_code01[];
82extern uint32_t fw2400_length01;
83extern uint32_t fw2400_addr01;
84extern uint32_t fw2400_code02[];
85extern uint32_t fw2400_length02;
86extern uint32_t fw2400_addr02;
87
88extern uint32_t fw2500_code01[];
89extern uint32_t fw2500_length01;
90extern uint32_t fw2500_addr01;
91extern uint32_t fw2500_code02[];
92extern uint32_t fw2500_length02;
93extern uint32_t fw2500_addr02;
94
95typedef enum {
96	MBOX_STATE_UNKNOWN = 0,
97	MBOX_STATE_READY,
98	MBOX_STATE_CMD_RUNNING,
99	MBOX_STATE_CMD_DONE
100} mbox_state_t;
101
102#define	IOCB_SIZE		64
103
104/*
105 * These should not be constents but should be obtained from fw.
106 */
107#define	QLT_MAX_LOGINS	2048
108#define	QLT_MAX_XCHGES	2048
109
110#define	MAX_MBOXES	32
111#define	MBOX_TIMEOUT	(2*1000*1000)
112#define	DEREG_RP_TIMEOUT	(2*1000*1000)
113
114typedef struct {
115	uint16_t	to_fw[MAX_MBOXES];
116	uint32_t	to_fw_mask;
117	uint16_t	from_fw[MAX_MBOXES];
118	uint32_t	from_fw_mask;
119	stmf_data_buf_t *dbuf;
120} mbox_cmd_t;
121
122typedef struct qlt_abts_cmd {
123	uint8_t		buf[IOCB_SIZE];
124} qlt_abts_cmd_t;
125
126struct qlt_dmem_bucket;
127
128#define	QLT_INTR_FIXED	0x1
129#define	QLT_INTR_MSI	0x2
130#define	QLT_INTR_MSIX	0x4
131
132typedef struct qlt_state {
133	dev_info_t		*dip;
134	char			qlt_minor_name[16];
135	char			qlt_port_alias[16];
136	fct_local_port_t	*qlt_port;
137	struct qlt_dmem_bucket	**dmem_buckets;
138
139	int			instance;
140	uint8_t			qlt_state:7,
141				qlt_state_not_acked:1;
142	uint8_t			qlt_intr_enabled:1,
143				qlt_25xx_chip:1,
144				qlt_stay_offline:1,
145				qlt_link_up,
146				qlt_rsvd1:4;
147	uint8_t			cur_topology;
148
149	/* Registers */
150	caddr_t		regs;
151	ddi_acc_handle_t regs_acc_handle;
152	ddi_acc_handle_t pcicfg_acc_handle;
153
154	/* Interrupt stuff */
155	kmutex_t		intr_lock;	/* Only used by intr routine */
156	int			intr_sneak_counter;
157	ddi_intr_handle_t	*htable;
158	int			intr_size;
159	int			intr_cnt;
160	uint_t			intr_pri;
161	int			intr_cap;
162	int			intr_flags;
163
164	/* Queues */
165	ddi_dma_handle_t queue_mem_dma_handle;
166	ddi_acc_handle_t queue_mem_acc_handle;
167	caddr_t		 queue_mem_ptr;
168	ddi_dma_cookie_t queue_mem_cookie;
169
170	kmutex_t	req_lock;
171	caddr_t		req_ptr;
172	uint32_t	req_ndx_to_fw;
173	uint32_t	req_ndx_from_fw;
174	uint32_t	req_available;
175
176	caddr_t		resp_ptr;
177	uint32_t	resp_ndx_to_fw;
178	uint32_t	resp_ndx_from_fw;
179
180	kmutex_t	preq_lock;
181	caddr_t		preq_ptr;
182	uint32_t	preq_ndx_to_fw;
183	uint32_t	preq_ndx_from_fw;
184
185	kcondvar_t	rp_dereg_cv; /* for deregister cmd */
186	uint32_t	rp_id_in_dereg; /* remote port in deregistering */
187	fct_status_t	rp_dereg_status;
188
189	caddr_t		atio_ptr;
190	uint16_t	atio_ndx_to_fw;
191	uint16_t	atio_ndx_from_fw;
192
193	kmutex_t	dma_mem_lock;
194
195	/* MailBox data */
196	kmutex_t	mbox_lock;
197	kcondvar_t	mbox_cv;
198	mbox_state_t	mbox_io_state;
199	mbox_cmd_t	*mcp;
200	qlt_nvram_t	*nvram;
201
202	uint8_t		link_speed;	/* Cached from intr routine */
203	uint16_t	fw_major;
204	uint16_t	fw_minor;
205	uint16_t	fw_subminor;
206	uint16_t	fw_endaddrlo;
207	uint16_t	fw_endaddrhi;
208	uint16_t	fw_attr;
209
210	uint32_t	fw_addr01;
211	uint32_t	fw_length01;
212	uint32_t	*fw_code01;
213	uint32_t	fw_addr02;
214	uint32_t	fw_length02;
215	uint32_t	*fw_code02;
216
217	uint32_t	qlt_ioctl_flags;
218	kmutex_t	qlt_ioctl_lock;
219	caddr_t		qlt_fwdump_buf;	/* FWDUMP will use ioctl flags/lock */
220	uint32_t	qlt_change_state_flags;	/* Cached for ACK handling */
221} qlt_state_t;
222
223/*
224 * FWDUMP flags (part of IOCTL flags)
225 */
226#define	QLT_FWDUMP_INPROGRESS		0x0100	/* if it's dumping now */
227#define	QLT_FWDUMP_TRIGGERED_BY_USER	0x0200	/* if users triggered it */
228#define	QLT_FWDUMP_FETCHED_BY_USER	0x0400	/* if users have viewed it */
229#define	QLT_FWDUMP_ISVALID		0x0800
230
231/*
232 * IOCTL supporting stuff
233 */
234#define	QLT_IOCTL_FLAG_MASK		0xFF
235#define	QLT_IOCTL_FLAG_IDLE		0x00
236#define	QLT_IOCTL_FLAG_OPEN		0x01
237#define	QLT_IOCTL_FLAG_EXCL		0x02
238
239typedef struct qlt_cmd {
240	stmf_data_buf_t	*dbuf;		/* dbuf with handle 0 for SCSI cmds */
241	stmf_data_buf_t	*dbuf_rsp_iu;	/* dbuf for possible FCP_RSP IU */
242	uint32_t	fw_xchg_addr;
243	uint16_t	flags;
244	union {
245		uint16_t	resp_offset;
246		uint8_t		atio_byte3;
247	} param;
248} qlt_cmd_t;
249
250/*
251 * cmd flags
252 */
253#define	QLT_CMD_ABORTING		1
254#define	QLT_CMD_ABORTED			2
255#define	QLT_CMD_TYPE_SOLICITED		4
256
257typedef struct {
258	int	dummy;
259} qlt_remote_port_t;
260
261#define	REQUEST_QUEUE_ENTRIES	2048
262#define	RESPONSE_QUEUE_ENTRIES	2048
263#define	ATIO_QUEUE_ENTRIES	2048
264#define	PRIORITY_QUEUE_ENTRIES	128
265
266#define	REQUEST_QUEUE_OFFSET	0
267#define	RESPONSE_QUEUE_OFFSET	(REQUEST_QUEUE_OFFSET + \
268				    (REQUEST_QUEUE_ENTRIES * IOCB_SIZE))
269#define	ATIO_QUEUE_OFFSET	(RESPONSE_QUEUE_OFFSET + \
270				    (RESPONSE_QUEUE_ENTRIES * IOCB_SIZE))
271#define	PRIORITY_QUEUE_OFFSET	(ATIO_QUEUE_OFFSET + \
272				    (ATIO_QUEUE_ENTRIES * IOCB_SIZE))
273#define	MBOX_DMA_MEM_SIZE	4096
274#define	MBOX_DMA_MEM_OFFSET		(PRIORITY_QUEUE_OFFSET + \
275				    (PRIORITY_QUEUE_ENTRIES * IOCB_SIZE))
276#define	TOTAL_DMA_MEM_SIZE	(MBOX_DMA_MEM_OFFSET + MBOX_DMA_MEM_SIZE)
277
278#define	QLT_MAX_ITERATIONS_PER_INTR	32
279
280#define	REG_RD16(qlt, addr) \
281	ddi_get16(qlt->regs_acc_handle, (uint16_t *)(qlt->regs + addr))
282#define	REG_RD32(qlt, addr) \
283	ddi_get32(qlt->regs_acc_handle, (uint32_t *)(qlt->regs + addr))
284#define	REG_WR16(qlt, addr, data) \
285	ddi_put16(qlt->regs_acc_handle, (uint16_t *)(qlt->regs + addr), \
286	(uint16_t)(data))
287#define	REG_WR32(qlt, addr, data) \
288	ddi_put32(qlt->regs_acc_handle, (uint32_t *)(qlt->regs + addr), \
289	(uint32_t)(data))
290#define	PCICFG_RD16(qlt, addr) \
291	pci_config_get16(qlt->pcicfg_acc_handle, (off_t)(addr))
292#define	PCICFG_RD32(qlt, addr) \
293	pci_config_get32(qlt->pcicfg_acc_handle, (off_t)(addr))
294#define	PCICFG_WR16(qlt, addr, data) \
295	pci_config_put16(qlt->pcicfg_acc_handle, (off_t)(addr), \
296		(uint16_t)(data))
297#define	QMEM_RD16(qlt, addr) \
298	ddi_get16(qlt->queue_mem_acc_handle, (uint16_t *)(addr))
299#define	DMEM_RD16(qlt, addr) LE_16((uint16_t)(*((uint16_t *)(addr))))
300#define	QMEM_RD32(qlt, addr) \
301	ddi_get32(qlt->queue_mem_acc_handle, (uint32_t *)(addr))
302#define	DMEM_RD32(qlt, addr) LE_32((uint32_t)(*((uint32_t *)(addr))))
303/*
304 * #define	QMEM_RD64(qlt, addr) \
305 *	ddi_get64(qlt->queue_mem_acc_handle, (uint64_t *)(addr))
306 */
307#define	QMEM_WR16(qlt, addr, data) \
308	ddi_put16(qlt->queue_mem_acc_handle, (uint16_t *)(addr), \
309	(uint16_t)(data))
310#define	DMEM_WR16(qlt, addr, data) (*((uint16_t *)(addr)) = \
311						LE_16((uint16_t)(data)))
312#define	QMEM_WR32(qlt, addr, data) \
313	ddi_put32(qlt->queue_mem_acc_handle, (uint32_t *)(addr), \
314	(uint32_t)(data))
315#define	DMEM_WR32(qlt, addr, data) (*((uint32_t *)(addr)) = \
316						LE_32((uint32_t)(data)))
317
318/*
319 * [QD]MEM is always little endian so the [QD]MEM_WR64 macro works for
320 * both sparc and x86.
321 */
322#define	QMEM_WR64(qlt, addr, data) \
323	QMEM_WR32(qlt, addr, (data & 0xffffffff)), \
324	QMEM_WR32(qlt, (addr)+4, ((uint64_t)data) >> 32)
325
326#define	DMEM_WR64(qlt, addr, data) \
327	DMEM_WR32(qlt, addr, (data & 0xffffffff)), \
328	DMEM_WR32(qlt, (addr)+4, ((uint64_t)data) >> 32)
329
330
331#ifdef	__cplusplus
332}
333#endif
334
335#endif /* _QLT_H */
336