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
32 extern "C" {
33 #endif
34 
35 /*
36  * Qlogic logging
37  */
38 extern 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 
81 extern uint32_t fw2400_code01[];
82 extern uint32_t fw2400_length01;
83 extern uint32_t fw2400_addr01;
84 extern uint32_t fw2400_code02[];
85 extern uint32_t fw2400_length02;
86 extern uint32_t fw2400_addr02;
87 
88 extern uint32_t fw2500_code01[];
89 extern uint32_t fw2500_length01;
90 extern uint32_t fw2500_addr01;
91 extern uint32_t fw2500_code02[];
92 extern uint32_t fw2500_length02;
93 extern uint32_t fw2500_addr02;
94 
95 typedef 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 
114 typedef 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 
122 typedef struct qlt_abts_cmd {
123 	uint8_t		buf[IOCB_SIZE];
124 } qlt_abts_cmd_t;
125 
126 struct qlt_dmem_bucket;
127 
128 #define	QLT_INTR_FIXED	0x1
129 #define	QLT_INTR_MSI	0x2
130 #define	QLT_INTR_MSIX	0x4
131 
132 typedef 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 
239 typedef 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 
257 typedef 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