qlt.h revision 10733:b95259752377
1234285Sdim/*
2234285Sdim * CDDL HEADER START
3234285Sdim *
4234285Sdim * The contents of this file are subject to the terms of the
5234285Sdim * Common Development and Distribution License (the "License").
6234285Sdim * You may not use this file except in compliance with the License.
7234285Sdim *
8234285Sdim * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9234285Sdim * or http://www.opensolaris.org/os/licensing.
10234285Sdim * See the License for the specific language governing permissions
11234285Sdim * and limitations under the License.
12234285Sdim *
13234285Sdim * When distributing Covered Code, include this CDDL HEADER in each
14234285Sdim * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15234285Sdim * If applicable, add the following below this CDDL HEADER, with the
16234285Sdim * fields enclosed by brackets "[]" replaced with your own identifying
17239462Sdim * information: Portions Copyright [yyyy] [name of copyright owner]
18234285Sdim *
19234285Sdim * CDDL HEADER END
20234285Sdim */
21234285Sdim
22234285Sdim/*
23234285Sdim * Copyright 2009 QLogic Corporation.  All rights reserved.
24234285Sdim * Use is subject to license terms.
25234285Sdim */
26234285Sdim
27234285Sdim/*
28234285Sdim * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
29234285Sdim * Use is subject to license terms.
30249423Sdim */
31249423Sdim
32249423Sdim#ifndef	_QLT_H
33234285Sdim#define	_QLT_H
34234285Sdim
35234285Sdim#include <stmf_defines.h>
36234285Sdim#include <qlt_regs.h>
37234285Sdim
38234285Sdim#ifdef	__cplusplus
39234285Sdimextern "C" {
40249423Sdim#endif
41234285Sdim
42234285Sdim/*
43249423Sdim * Qlogic logging
44249423Sdim */
45249423Sdimextern int enable_extended_logging;
46234285Sdim
47234285Sdim/*
48234285Sdim * Caution: 1) LOG will be available in debug/non-debug mode
49234285Sdim *	    2) Anything which can potentially flood the log should be under
50234285Sdim *	       extended logging, and use QLT_EXT_LOG.
51234285Sdim *	    3) Don't use QLT_EXT_LOG in performance-critical code path, such
52251662Sdim *	       as normal SCSI I/O code path. It could hurt system performance.
53251662Sdim *	    4) Use kmdb to change enable_extened_logging in the fly to adjust
54251662Sdim *	       tracing
55251662Sdim */
56251662Sdim#define	QLT_EXT_LOG(log_ident, ...)	\
57234285Sdim		if (enable_extended_logging) {	\
58234285Sdim			stmf_trace(log_ident, __VA_ARGS__);	\
59234285Sdim		}
60251662Sdim
61234285Sdim#define	QLT_LOG(log_ident, ...)	\
62234285Sdim	stmf_trace(log_ident, __VA_ARGS__)
63234285Sdim
64234285Sdim/*
65251662Sdim * Error codes. FSC stands for Failure sub code.
66251662Sdim */
67251662Sdim#define	QLT_FAILURE			FCT_FCA_FAILURE
68251662Sdim#define	QLT_SUCCESS			FCT_SUCCESS
69234285Sdim#define	QLT_FSC(x)			((uint64_t)(x) << 40)
70234285Sdim#define	QLT_DMA_STUCK			(QLT_FAILURE | QLT_FSC(1))
71234285Sdim#define	QLT_MAILBOX_STUCK		(QLT_FAILURE | QLT_FSC(2))
72234285Sdim#define	QLT_ROM_STUCK			(QLT_FAILURE | QLT_FSC(3))
73234285Sdim#define	QLT_UNEXPECTED_RESPONSE		(QLT_FAILURE | QLT_FSC(4))
74234285Sdim#define	QLT_MBOX_FAILED			(QLT_FAILURE | QLT_FSC(5))
75234285Sdim#define	QLT_MBOX_NOT_INITIALIZED	(QLT_FAILURE | QLT_FSC(6))
76234285Sdim#define	QLT_MBOX_BUSY			(QLT_FAILURE | QLT_FSC(7))
77234285Sdim#define	QLT_MBOX_ABORTED		(QLT_FAILURE | QLT_FSC(8))
78234285Sdim#define	QLT_MBOX_TIMEOUT		(QLT_FAILURE | QLT_FSC(9))
79234285Sdim#define	QLT_RESP_TIMEOUT		(QLT_FAILURE | QLT_FSC(10))
80234285Sdim#define	QLT_FLASH_TIMEOUT		(QLT_FAILURE | QLT_FSC(11))
81234285Sdim#define	QLT_FLASH_ACCESS_ERROR		(QLT_FAILURE | QLT_FSC(12))
82234285Sdim#define	QLT_BAD_NVRAM_DATA		(QLT_FAILURE | QLT_FSC(13))
83234285Sdim#define	QLT_FIRMWARE_ERROR_CODE		(QLT_FAILURE | QLT_FSC(14))
84234285Sdim
85234285Sdim#define	QLT_FIRMWARE_ERROR(s, c1, c2)	(QLT_FIRMWARE_ERROR_CODE | \
86234285Sdim	(((uint64_t)s) << 32) | (((uint64_t)c1) << 24) | ((uint64_t)c2))
87234285Sdim
88234285Sdimextern uint32_t fw2400_code01[];
89234285Sdimextern uint32_t fw2400_length01;
90234285Sdimextern uint32_t fw2400_addr01;
91234285Sdimextern uint32_t fw2400_code02[];
92239462Sdimextern uint32_t fw2400_length02;
93239462Sdimextern uint32_t fw2400_addr02;
94239462Sdim
95239462Sdimextern uint32_t fw2500_code01[];
96239462Sdimextern uint32_t fw2500_length01;
97239462Sdimextern uint32_t fw2500_addr01;
98239462Sdimextern uint32_t fw2500_code02[];
99239462Sdimextern uint32_t fw2500_length02;
100234285Sdimextern uint32_t fw2500_addr02;
101239462Sdim
102239462Sdimextern uint32_t fw8100_code01[];
103239462Sdimextern uint32_t fw8100_length01;
104239462Sdimextern uint32_t fw8100_addr01;
105239462Sdimextern uint32_t fw8100_code02[];
106239462Sdimextern uint32_t fw8100_length02;
107239462Sdimextern uint32_t fw8100_addr02;
108239462Sdim
109239462Sdimtypedef enum {
110234285Sdim	MBOX_STATE_UNKNOWN = 0,
111239462Sdim	MBOX_STATE_READY,
112239462Sdim	MBOX_STATE_CMD_RUNNING,
113239462Sdim	MBOX_STATE_CMD_DONE
114239462Sdim} mbox_state_t;
115239462Sdim
116239462Sdim#define	IOCB_SIZE		64
117239462Sdim
118239462Sdim/*
119239462Sdim * These should not be constents but should be obtained from fw.
120239462Sdim */
121239462Sdim#define	QLT_MAX_LOGINS	2048
122239462Sdim#define	QLT_MAX_XCHGES	2048
123239462Sdim
124234285Sdim#define	MAX_MBOXES	32
125239462Sdim#define	MBOX_TIMEOUT	(2*1000*1000)
126239462Sdim#define	DEREG_RP_TIMEOUT	(2*1000*1000)
127239462Sdim
128239462Sdimtypedef struct {
129239462Sdim	uint16_t	to_fw[MAX_MBOXES];
130239462Sdim	uint32_t	to_fw_mask;
131239462Sdim	uint16_t	from_fw[MAX_MBOXES];
132239462Sdim	uint32_t	from_fw_mask;
133239462Sdim	stmf_data_buf_t *dbuf;
134239462Sdim} mbox_cmd_t;
135239462Sdim
136239462Sdimtypedef struct qlt_abts_cmd {
137239462Sdim	uint8_t		buf[IOCB_SIZE];
138239462Sdim} qlt_abts_cmd_t;
139239462Sdim
140239462Sdimstruct qlt_dmem_bucket;
141239462Sdim
142239462Sdim#define	QLT_INTR_FIXED	0x1
143239462Sdim#define	QLT_INTR_MSI	0x2
144239462Sdim#define	QLT_INTR_MSIX	0x4
145239462Sdim
146239462Sdimtypedef struct qlt_el_trace_desc {
147239462Sdim	kmutex_t	mutex;
148239462Sdim	uint16_t	next;
149239462Sdim	uint32_t	trace_buffer_size;
150239462Sdim	char		*trace_buffer;
151239462Sdim} qlt_el_trace_desc_t;
152234285Sdim
153239462Sdimtypedef struct qlt_state {
154239462Sdim	dev_info_t		*dip;
155239462Sdim	char			qlt_minor_name[16];
156239462Sdim	char			qlt_port_alias[16];
157239462Sdim	fct_local_port_t	*qlt_port;
158239462Sdim	struct qlt_dmem_bucket	**dmem_buckets;
159239462Sdim
160239462Sdim	int			instance;
161239462Sdim	uint8_t			qlt_state:7,
162239462Sdim				qlt_state_not_acked:1;
163239462Sdim	uint8_t			qlt_intr_enabled:1,
164239462Sdim				qlt_25xx_chip:1,
165239462Sdim				qlt_stay_offline:1,
166239462Sdim				qlt_link_up,
167239462Sdim				qlt_81xx_chip:1,
168239462Sdim				qlt_rsvd1:3;
169239462Sdim	uint8_t			cur_topology;
170239462Sdim
171239462Sdim	/* Registers */
172239462Sdim	caddr_t		regs;
173239462Sdim	ddi_acc_handle_t regs_acc_handle;
174239462Sdim	ddi_acc_handle_t pcicfg_acc_handle;
175239462Sdim
176239462Sdim	/* Interrupt stuff */
177239462Sdim	kmutex_t		intr_lock;	/* Only used by intr routine */
178239462Sdim	int			intr_sneak_counter;
179239462Sdim	ddi_intr_handle_t	*htable;
180239462Sdim	int			intr_size;
181239462Sdim	int			intr_cnt;
182239462Sdim	uint_t			intr_pri;
183239462Sdim	int			intr_cap;
184239462Sdim	int			intr_flags;
185239462Sdim
186239462Sdim	/* Queues */
187239462Sdim	ddi_dma_handle_t queue_mem_dma_handle;
188239462Sdim	ddi_acc_handle_t queue_mem_acc_handle;
189239462Sdim	caddr_t		 queue_mem_ptr;
190239462Sdim	ddi_dma_cookie_t queue_mem_cookie;
191239462Sdim
192239462Sdim	kmutex_t	req_lock;
193239462Sdim	caddr_t		req_ptr;
194239462Sdim	uint32_t	req_ndx_to_fw;
195239462Sdim	uint32_t	req_ndx_from_fw;
196239462Sdim	uint32_t	req_available;
197239462Sdim
198239462Sdim	caddr_t		resp_ptr;
199239462Sdim	uint32_t	resp_ndx_to_fw;
200239462Sdim	uint32_t	resp_ndx_from_fw;
201239462Sdim
202239462Sdim	kmutex_t	preq_lock;
203239462Sdim	caddr_t		preq_ptr;
204239462Sdim	uint32_t	preq_ndx_to_fw;
205239462Sdim	uint32_t	preq_ndx_from_fw;
206239462Sdim
207239462Sdim	kcondvar_t	rp_dereg_cv; /* for deregister cmd */
208239462Sdim	uint32_t	rp_id_in_dereg; /* remote port in deregistering */
209234285Sdim	fct_status_t	rp_dereg_status;
210234285Sdim
211234285Sdim	caddr_t		atio_ptr;
212234285Sdim	uint16_t	atio_ndx_to_fw;
213234285Sdim	uint16_t	atio_ndx_from_fw;
214234285Sdim
215234285Sdim	kmutex_t	dma_mem_lock;
216234285Sdim
217234285Sdim	/* MailBox data */
218234285Sdim	kmutex_t	mbox_lock;
219234285Sdim	kcondvar_t	mbox_cv;
220234285Sdim	mbox_state_t	mbox_io_state;
221251662Sdim	mbox_cmd_t	*mcp;
222251662Sdim	qlt_nvram_t	*nvram;
223251662Sdim
224251662Sdim	uint8_t		link_speed;	/* Cached from intr routine */
225251662Sdim	uint16_t	fw_major;
226251662Sdim	uint16_t	fw_minor;
227251662Sdim	uint16_t	fw_subminor;
228251662Sdim	uint16_t	fw_endaddrlo;
229251662Sdim	uint16_t	fw_endaddrhi;
230251662Sdim	uint16_t	fw_attr;
231251662Sdim
232251662Sdim	uint32_t	fw_addr01;
233251662Sdim	uint32_t	fw_length01;
234234285Sdim	uint32_t	*fw_code01;
235234285Sdim	uint32_t	fw_addr02;
236	uint32_t	fw_length02;
237	uint32_t	*fw_code02;
238
239	uint32_t	qlt_ioctl_flags;
240	kmutex_t	qlt_ioctl_lock;
241	caddr_t		qlt_fwdump_buf;	/* FWDUMP will use ioctl flags/lock */
242	uint32_t	qlt_change_state_flags;	/* Cached for ACK handling */
243
244	qlt_el_trace_desc_t	*el_trace_desc;
245} qlt_state_t;
246
247/*
248 * FWDUMP flags (part of IOCTL flags)
249 */
250#define	QLT_FWDUMP_INPROGRESS		0x0100	/* if it's dumping now */
251#define	QLT_FWDUMP_TRIGGERED_BY_USER	0x0200	/* if users triggered it */
252#define	QLT_FWDUMP_FETCHED_BY_USER	0x0400	/* if users have viewed it */
253#define	QLT_FWDUMP_ISVALID		0x0800
254
255/*
256 * IOCTL supporting stuff
257 */
258#define	QLT_IOCTL_FLAG_MASK		0xFF
259#define	QLT_IOCTL_FLAG_IDLE		0x00
260#define	QLT_IOCTL_FLAG_OPEN		0x01
261#define	QLT_IOCTL_FLAG_EXCL		0x02
262
263typedef struct qlt_cmd {
264	stmf_data_buf_t	*dbuf;		/* dbuf with handle 0 for SCSI cmds */
265	stmf_data_buf_t	*dbuf_rsp_iu;	/* dbuf for possible FCP_RSP IU */
266	uint32_t	fw_xchg_addr;
267	uint16_t	flags;
268	union {
269		uint16_t	resp_offset;
270		uint8_t		atio_byte3;
271	} param;
272} qlt_cmd_t;
273
274/*
275 * cmd flags
276 */
277#define	QLT_CMD_ABORTING		1
278#define	QLT_CMD_ABORTED			2
279#define	QLT_CMD_TYPE_SOLICITED		4
280
281typedef struct {
282	int	dummy;
283} qlt_remote_port_t;
284
285#define	REQUEST_QUEUE_ENTRIES	2048
286#define	RESPONSE_QUEUE_ENTRIES	2048
287#define	ATIO_QUEUE_ENTRIES	2048
288#define	PRIORITY_QUEUE_ENTRIES	128
289
290#define	REQUEST_QUEUE_OFFSET	0
291#define	RESPONSE_QUEUE_OFFSET	(REQUEST_QUEUE_OFFSET + \
292				    (REQUEST_QUEUE_ENTRIES * IOCB_SIZE))
293#define	ATIO_QUEUE_OFFSET	(RESPONSE_QUEUE_OFFSET + \
294				    (RESPONSE_QUEUE_ENTRIES * IOCB_SIZE))
295#define	PRIORITY_QUEUE_OFFSET	(ATIO_QUEUE_OFFSET + \
296				    (ATIO_QUEUE_ENTRIES * IOCB_SIZE))
297#define	MBOX_DMA_MEM_SIZE	4096
298#define	MBOX_DMA_MEM_OFFSET		(PRIORITY_QUEUE_OFFSET + \
299				    (PRIORITY_QUEUE_ENTRIES * IOCB_SIZE))
300#define	TOTAL_DMA_MEM_SIZE	(MBOX_DMA_MEM_OFFSET + MBOX_DMA_MEM_SIZE)
301
302#define	QLT_MAX_ITERATIONS_PER_INTR	32
303
304#define	REG_RD16(qlt, addr) \
305	ddi_get16(qlt->regs_acc_handle, (uint16_t *)(qlt->regs + addr))
306#define	REG_RD32(qlt, addr) \
307	ddi_get32(qlt->regs_acc_handle, (uint32_t *)(qlt->regs + addr))
308#define	REG_WR16(qlt, addr, data) \
309	ddi_put16(qlt->regs_acc_handle, (uint16_t *)(qlt->regs + addr), \
310	(uint16_t)(data))
311#define	REG_WR32(qlt, addr, data) \
312	ddi_put32(qlt->regs_acc_handle, (uint32_t *)(qlt->regs + addr), \
313	(uint32_t)(data))
314#define	PCICFG_RD16(qlt, addr) \
315	pci_config_get16(qlt->pcicfg_acc_handle, (off_t)(addr))
316#define	PCICFG_RD32(qlt, addr) \
317	pci_config_get32(qlt->pcicfg_acc_handle, (off_t)(addr))
318#define	PCICFG_WR16(qlt, addr, data) \
319	pci_config_put16(qlt->pcicfg_acc_handle, (off_t)(addr), \
320		(uint16_t)(data))
321#define	QMEM_RD16(qlt, addr) \
322	ddi_get16(qlt->queue_mem_acc_handle, (uint16_t *)(addr))
323#define	DMEM_RD16(qlt, addr) LE_16((uint16_t)(*((uint16_t *)(addr))))
324#define	QMEM_RD32(qlt, addr) \
325	ddi_get32(qlt->queue_mem_acc_handle, (uint32_t *)(addr))
326#define	DMEM_RD32(qlt, addr) LE_32((uint32_t)(*((uint32_t *)(addr))))
327/*
328 * #define	QMEM_RD64(qlt, addr) \
329 *	ddi_get64(qlt->queue_mem_acc_handle, (uint64_t *)(addr))
330 */
331#define	QMEM_WR16(qlt, addr, data) \
332	ddi_put16(qlt->queue_mem_acc_handle, (uint16_t *)(addr), \
333	(uint16_t)(data))
334#define	DMEM_WR16(qlt, addr, data) (*((uint16_t *)(addr)) = \
335	(uint16_t)LE_16((uint16_t)(data)))
336#define	QMEM_WR32(qlt, addr, data) \
337	ddi_put32(qlt->queue_mem_acc_handle, (uint32_t *)(addr), \
338	(uint32_t)(data))
339#define	DMEM_WR32(qlt, addr, data) (*((uint32_t *)(addr)) = \
340						LE_32((uint32_t)(data)))
341
342/*
343 * [QD]MEM is always little endian so the [QD]MEM_WR64 macro works for
344 * both sparc and x86.
345 */
346#define	QMEM_WR64(qlt, addr, data) \
347	QMEM_WR32(qlt, addr, (data & 0xffffffff)), \
348	QMEM_WR32(qlt, (addr)+4, ((uint64_t)data) >> 32)
349
350#define	DMEM_WR64(qlt, addr, data) \
351	DMEM_WR32(qlt, addr, (data & 0xffffffff)), \
352	DMEM_WR32(qlt, (addr)+4, ((uint64_t)data) >> 32)
353
354/*
355 * Structure used to associate values with strings which describe them.
356 */
357typedef struct string_table_entry {
358	uint32_t value;
359	char    *string;
360} string_table_t;
361
362char *prop_text(int prop_status);
363char *value2string(string_table_t *entry, int value, int delimiter);
364
365#define	PROP_STATUS_DELIMITER	((uint32_t)0xFFFF)
366
367#define	DDI_PROP_STATUS()					\
368{								\
369	{DDI_PROP_SUCCESS, "DDI_PROP_SUCCESS"},			\
370	{DDI_PROP_NOT_FOUND, "DDI_PROP_NOT_FOUND"},		\
371	{DDI_PROP_UNDEFINED, "DDI_PROP_UNDEFINED"},		\
372	{DDI_PROP_NO_MEMORY, "DDI_PROP_NO_MEMORY"},		\
373	{DDI_PROP_INVAL_ARG, "DDI_PROP_INVAL_ARG"},		\
374	{DDI_PROP_BUF_TOO_SMALL, "DDI_PROP_BUF_TOO_SMALL"},	\
375	{DDI_PROP_CANNOT_DECODE, "DDI_PROP_CANNOT_DECODE"},	\
376	{DDI_PROP_CANNOT_ENCODE, "DDI_PROP_CANNOT_ENCODE"},	\
377	{DDI_PROP_END_OF_DATA, "DDI_PROP_END_OF_DATA"},		\
378	{PROP_STATUS_DELIMITER, "DDI_PROP_UNKNOWN"}		\
379}
380
381#ifndef TRUE
382#define	TRUE	B_TRUE
383#endif
384
385#ifndef FALSE
386#define	FALSE	B_FALSE
387#endif
388
389/* Little endian machine correction defines. */
390#ifdef _LITTLE_ENDIAN
391#define	LITTLE_ENDIAN_16(x)
392#define	LITTLE_ENDIAN_24(x)
393#define	LITTLE_ENDIAN_32(x)
394#define	LITTLE_ENDIAN_64(x)
395#define	LITTLE_ENDIAN(bp, bytes)
396#define	BIG_ENDIAN_16(x)	qlt_chg_endian((uint8_t *)x, 2)
397#define	BIG_ENDIAN_24(x)	qlt_chg_endian((uint8_t *)x, 3)
398#define	BIG_ENDIAN_32(x)	qlt_chg_endian((uint8_t *)x, 4)
399#define	BIG_ENDIAN_64(x)	qlt_chg_endian((uint8_t *)x, 8)
400#define	BIG_ENDIAN(bp, bytes)	qlt_chg_endian((uint8_t *)bp, bytes)
401#endif /* _LITTLE_ENDIAN */
402
403/* Big endian machine correction defines. */
404#ifdef _BIG_ENDIAN
405#define	LITTLE_ENDIAN_16(x)		qlt_chg_endian((uint8_t *)x, 2)
406#define	LITTLE_ENDIAN_24(x)		qlt_chg_endian((uint8_t *)x, 3)
407#define	LITTLE_ENDIAN_32(x)		qlt_chg_endian((uint8_t *)x, 4)
408#define	LITTLE_ENDIAN_64(x)		qlt_chg_endian((uint8_t *)x, 8)
409#define	LITTLE_ENDIAN(bp, bytes)	qlt_chg_endian((uint8_t *)bp, bytes)
410#define	BIG_ENDIAN_16(x)
411#define	BIG_ENDIAN_24(x)
412#define	BIG_ENDIAN_32(x)
413#define	BIG_ENDIAN_64(x)
414#define	BIG_ENDIAN(bp, bytes)
415#endif /* _BIG_ENDIAN */
416
417void	qlt_chg_endian(uint8_t *, size_t);
418
419void qlt_el_msg(qlt_state_t *qlt, const char *fn, int ce, ...);
420void qlt_dump_el_trace_buffer(qlt_state_t *qlt);
421#define	EL(qlt, ...) 	qlt_el_msg(qlt, __func__, CE_CONT, __VA_ARGS__);
422#define	EL_TRACE_BUF_SIZE	8192
423#define	EL_BUFFER_RESERVE	256
424#define	DEBUG_STK_DEPTH		24
425#define	EL_TRACE_BUF_SIZE	8192
426
427#ifdef	__cplusplus
428}
429#endif
430
431#endif /* _QLT_H */
432