xref: /freebsd/sys/dev/qlxgbe/ql_hw.c (revision 69718b786d3943ea9a99eeeb5f5f6162f11c78b7)
1 /*
2  * Copyright (c) 2013-2016 Qlogic Corporation
3  * All rights reserved.
4  *
5  *  Redistribution and use in source and binary forms, with or without
6  *  modification, are permitted provided that the following conditions
7  *  are met:
8  *
9  *  1. Redistributions of source code must retain the above copyright
10  *     notice, this list of conditions and the following disclaimer.
11  *  2. Redistributions in binary form must reproduce the above copyright
12  *     notice, this list of conditions and the following disclaimer in the
13  *     documentation and/or other materials provided with the distribution.
14  *
15  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25  *  POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 /*
29  * File: ql_hw.c
30  * Author : David C Somayajulu, Qlogic Corporation, Aliso Viejo, CA 92656.
31  * Content: Contains Hardware dependent functions
32  */
33 
34 #include <sys/cdefs.h>
35 __FBSDID("$FreeBSD$");
36 
37 #include "ql_os.h"
38 #include "ql_hw.h"
39 #include "ql_def.h"
40 #include "ql_inline.h"
41 #include "ql_ver.h"
42 #include "ql_glbl.h"
43 #include "ql_dbg.h"
44 #include "ql_minidump.h"
45 
46 /*
47  * Static Functions
48  */
49 
50 static void qla_del_rcv_cntxt(qla_host_t *ha);
51 static int qla_init_rcv_cntxt(qla_host_t *ha);
52 static void qla_del_xmt_cntxt(qla_host_t *ha);
53 static int qla_init_xmt_cntxt(qla_host_t *ha);
54 static void qla_hw_tx_done_locked(qla_host_t *ha, uint32_t txr_idx);
55 static int qla_mbx_cmd(qla_host_t *ha, uint32_t *h_mbox, uint32_t n_hmbox,
56 	uint32_t *fw_mbox, uint32_t n_fwmbox, uint32_t no_pause);
57 static int qla_config_intr_cntxt(qla_host_t *ha, uint32_t start_idx,
58 	uint32_t num_intrs, uint32_t create);
59 static int qla_config_rss(qla_host_t *ha, uint16_t cntxt_id);
60 static int qla_config_intr_coalesce(qla_host_t *ha, uint16_t cntxt_id,
61 	int tenable, int rcv);
62 static int qla_set_mac_rcv_mode(qla_host_t *ha, uint32_t mode);
63 static int qla_link_event_req(qla_host_t *ha, uint16_t cntxt_id);
64 
65 static int qla_tx_tso(qla_host_t *ha, struct mbuf *mp, q80_tx_cmd_t *tx_cmd,
66 		uint8_t *hdr);
67 static int qla_hw_add_all_mcast(qla_host_t *ha);
68 static int qla_hw_del_all_mcast(qla_host_t *ha);
69 static int qla_add_rcv_rings(qla_host_t *ha, uint32_t sds_idx, uint32_t nsds);
70 
71 static int qla_init_nic_func(qla_host_t *ha);
72 static int qla_stop_nic_func(qla_host_t *ha);
73 static int qla_query_fw_dcbx_caps(qla_host_t *ha);
74 static int qla_set_port_config(qla_host_t *ha, uint32_t cfg_bits);
75 static int qla_get_port_config(qla_host_t *ha, uint32_t *cfg_bits);
76 static void qla_get_quick_stats(qla_host_t *ha);
77 static int qla_set_cam_search_mode(qla_host_t *ha, uint32_t search_mode);
78 static int qla_get_cam_search_mode(qla_host_t *ha);
79 
80 static void ql_minidump_free(qla_host_t *ha);
81 
82 
83 static int
84 qla_sysctl_get_drvr_stats(SYSCTL_HANDLER_ARGS)
85 {
86         int err = 0, ret;
87         qla_host_t *ha;
88 	uint32_t i;
89 
90         err = sysctl_handle_int(oidp, &ret, 0, req);
91 
92         if (err || !req->newptr)
93                 return (err);
94 
95         if (ret == 1) {
96 
97                 ha = (qla_host_t *)arg1;
98 
99 		for (i = 0; i < ha->hw.num_sds_rings; i++) {
100 
101 			device_printf(ha->pci_dev,
102 				"%s: sds_ring[%d] = %p\n", __func__,i,
103 				(void *)ha->hw.sds[i].intr_count);
104 
105 			device_printf(ha->pci_dev,
106 				"%s: sds_ring[%d].spurious_intr_count = %p\n",
107 				__func__,
108 				i, (void *)ha->hw.sds[i].spurious_intr_count);
109 
110 			device_printf(ha->pci_dev,
111 				"%s: sds_ring[%d].rx_free = %d\n", __func__,i,
112 				ha->hw.sds[i].rx_free);
113 		}
114 
115 		for (i = 0; i < ha->hw.num_tx_rings; i++)
116 			device_printf(ha->pci_dev,
117 				"%s: tx[%d] = %p\n", __func__,i,
118 				(void *)ha->tx_ring[i].count);
119 
120 		for (i = 0; i < ha->hw.num_rds_rings; i++)
121 			device_printf(ha->pci_dev,
122 				"%s: rds_ring[%d] = %p\n", __func__,i,
123 				(void *)ha->hw.rds[i].count);
124 
125 		device_printf(ha->pci_dev, "%s: lro_pkt_count = %p\n", __func__,
126 			(void *)ha->lro_pkt_count);
127 
128 		device_printf(ha->pci_dev, "%s: lro_bytes = %p\n", __func__,
129 			(void *)ha->lro_bytes);
130 
131 #ifdef QL_ENABLE_ISCSI_TLV
132 		device_printf(ha->pci_dev, "%s: iscsi_pkts = %p\n", __func__,
133 			(void *)ha->hw.iscsi_pkt_count);
134 #endif /* #ifdef QL_ENABLE_ISCSI_TLV */
135 
136 	}
137 	return (err);
138 }
139 
140 static int
141 qla_sysctl_get_quick_stats(SYSCTL_HANDLER_ARGS)
142 {
143 	int err, ret = 0;
144 	qla_host_t *ha;
145 
146 	err = sysctl_handle_int(oidp, &ret, 0, req);
147 
148 	if (err || !req->newptr)
149 		return (err);
150 
151 	if (ret == 1) {
152 		ha = (qla_host_t *)arg1;
153 		qla_get_quick_stats(ha);
154 	}
155 	return (err);
156 }
157 
158 #ifdef QL_DBG
159 
160 static void
161 qla_stop_pegs(qla_host_t *ha)
162 {
163         uint32_t val = 1;
164 
165         ql_rdwr_indreg32(ha, Q8_CRB_PEG_0, &val, 0);
166         ql_rdwr_indreg32(ha, Q8_CRB_PEG_1, &val, 0);
167         ql_rdwr_indreg32(ha, Q8_CRB_PEG_2, &val, 0);
168         ql_rdwr_indreg32(ha, Q8_CRB_PEG_3, &val, 0);
169         ql_rdwr_indreg32(ha, Q8_CRB_PEG_4, &val, 0);
170         device_printf(ha->pci_dev, "%s PEGS HALTED!!!!!\n", __func__);
171 }
172 
173 static int
174 qla_sysctl_stop_pegs(SYSCTL_HANDLER_ARGS)
175 {
176 	int err, ret = 0;
177 	qla_host_t *ha;
178 
179 	err = sysctl_handle_int(oidp, &ret, 0, req);
180 
181 
182 	if (err || !req->newptr)
183 		return (err);
184 
185 	if (ret == 1) {
186 		ha = (qla_host_t *)arg1;
187 		(void)QLA_LOCK(ha, __func__, 0);
188 		qla_stop_pegs(ha);
189 		QLA_UNLOCK(ha, __func__);
190 	}
191 
192 	return err;
193 }
194 #endif /* #ifdef QL_DBG */
195 
196 static int
197 qla_validate_set_port_cfg_bit(uint32_t bits)
198 {
199         if ((bits & 0xF) > 1)
200                 return (-1);
201 
202         if (((bits >> 4) & 0xF) > 2)
203                 return (-1);
204 
205         if (((bits >> 8) & 0xF) > 2)
206                 return (-1);
207 
208         return (0);
209 }
210 
211 static int
212 qla_sysctl_port_cfg(SYSCTL_HANDLER_ARGS)
213 {
214         int err, ret = 0;
215         qla_host_t *ha;
216         uint32_t cfg_bits;
217 
218         err = sysctl_handle_int(oidp, &ret, 0, req);
219 
220         if (err || !req->newptr)
221                 return (err);
222 
223         if ((qla_validate_set_port_cfg_bit((uint32_t)ret) == 0)) {
224 
225                 ha = (qla_host_t *)arg1;
226 
227                 err = qla_get_port_config(ha, &cfg_bits);
228 
229                 if (err)
230                         goto qla_sysctl_set_port_cfg_exit;
231 
232                 if (ret & 0x1) {
233                         cfg_bits |= Q8_PORT_CFG_BITS_DCBX_ENABLE;
234                 } else {
235                         cfg_bits &= ~Q8_PORT_CFG_BITS_DCBX_ENABLE;
236                 }
237 
238                 ret = ret >> 4;
239                 cfg_bits &= ~Q8_PORT_CFG_BITS_PAUSE_CFG_MASK;
240 
241                 if ((ret & 0xF) == 0) {
242                         cfg_bits |= Q8_PORT_CFG_BITS_PAUSE_DISABLED;
243                 } else if ((ret & 0xF) == 1){
244                         cfg_bits |= Q8_PORT_CFG_BITS_PAUSE_STD;
245                 } else {
246                         cfg_bits |= Q8_PORT_CFG_BITS_PAUSE_PPM;
247                 }
248 
249                 ret = ret >> 4;
250                 cfg_bits &= ~Q8_PORT_CFG_BITS_STDPAUSE_DIR_MASK;
251 
252                 if (ret == 0) {
253                         cfg_bits |= Q8_PORT_CFG_BITS_STDPAUSE_XMT_RCV;
254                 } else if (ret == 1){
255                         cfg_bits |= Q8_PORT_CFG_BITS_STDPAUSE_XMT;
256                 } else {
257                         cfg_bits |= Q8_PORT_CFG_BITS_STDPAUSE_RCV;
258                 }
259 
260                 err = qla_set_port_config(ha, cfg_bits);
261         } else {
262                 ha = (qla_host_t *)arg1;
263 
264                 err = qla_get_port_config(ha, &cfg_bits);
265         }
266 
267 qla_sysctl_set_port_cfg_exit:
268         return err;
269 }
270 
271 static int
272 qla_sysctl_set_cam_search_mode(SYSCTL_HANDLER_ARGS)
273 {
274 	int err, ret = 0;
275 	qla_host_t *ha;
276 
277 	err = sysctl_handle_int(oidp, &ret, 0, req);
278 
279 	if (err || !req->newptr)
280 		return (err);
281 
282 	ha = (qla_host_t *)arg1;
283 
284 	if ((ret == Q8_HW_CONFIG_CAM_SEARCH_MODE_INTERNAL) ||
285 		(ret == Q8_HW_CONFIG_CAM_SEARCH_MODE_AUTO)) {
286 		err = qla_set_cam_search_mode(ha, (uint32_t)ret);
287 	} else {
288 		device_printf(ha->pci_dev, "%s: ret = %d\n", __func__, ret);
289 	}
290 
291 	return (err);
292 }
293 
294 static int
295 qla_sysctl_get_cam_search_mode(SYSCTL_HANDLER_ARGS)
296 {
297 	int err, ret = 0;
298 	qla_host_t *ha;
299 
300 	err = sysctl_handle_int(oidp, &ret, 0, req);
301 
302 	if (err || !req->newptr)
303 		return (err);
304 
305 	ha = (qla_host_t *)arg1;
306 	err = qla_get_cam_search_mode(ha);
307 
308 	return (err);
309 }
310 
311 
312 /*
313  * Name: ql_hw_add_sysctls
314  * Function: Add P3Plus specific sysctls
315  */
316 void
317 ql_hw_add_sysctls(qla_host_t *ha)
318 {
319         device_t	dev;
320 
321         dev = ha->pci_dev;
322 
323 	ha->hw.num_sds_rings = MAX_SDS_RINGS;
324 	ha->hw.num_rds_rings = MAX_RDS_RINGS;
325 	ha->hw.num_tx_rings = NUM_TX_RINGS;
326 
327 	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
328 		SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
329 		OID_AUTO, "num_rds_rings", CTLFLAG_RD, &ha->hw.num_rds_rings,
330 		ha->hw.num_rds_rings, "Number of Rcv Descriptor Rings");
331 
332         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
333                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
334                 OID_AUTO, "num_sds_rings", CTLFLAG_RD, &ha->hw.num_sds_rings,
335 		ha->hw.num_sds_rings, "Number of Status Descriptor Rings");
336 
337         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
338                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
339                 OID_AUTO, "num_tx_rings", CTLFLAG_RD, &ha->hw.num_tx_rings,
340 		ha->hw.num_tx_rings, "Number of Transmit Rings");
341 
342         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
343                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
344                 OID_AUTO, "tx_ring_index", CTLFLAG_RW, &ha->txr_idx,
345 		ha->txr_idx, "Tx Ring Used");
346 
347 	SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
348 		SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
349 		OID_AUTO, "drvr_stats", CTLTYPE_INT | CTLFLAG_RW,
350 		(void *)ha, 0,
351 		qla_sysctl_get_drvr_stats, "I", "Driver Maintained Statistics");
352 
353         SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
354                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
355                 OID_AUTO, "quick_stats", CTLTYPE_INT | CTLFLAG_RW,
356                 (void *)ha, 0,
357                 qla_sysctl_get_quick_stats, "I", "Quick Statistics");
358 
359         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
360                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
361                 OID_AUTO, "max_tx_segs", CTLFLAG_RD, &ha->hw.max_tx_segs,
362 		ha->hw.max_tx_segs, "Max # of Segments in a non-TSO pkt");
363 
364 	ha->hw.sds_cidx_thres = 32;
365         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
366                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
367                 OID_AUTO, "sds_cidx_thres", CTLFLAG_RW, &ha->hw.sds_cidx_thres,
368 		ha->hw.sds_cidx_thres,
369 		"Number of SDS entries to process before updating"
370 		" SDS Ring Consumer Index");
371 
372 	ha->hw.rds_pidx_thres = 32;
373         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
374                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
375                 OID_AUTO, "rds_pidx_thres", CTLFLAG_RW, &ha->hw.rds_pidx_thres,
376 		ha->hw.rds_pidx_thres,
377 		"Number of Rcv Rings Entries to post before updating"
378 		" RDS Ring Producer Index");
379 
380         ha->hw.rcv_intr_coalesce = (3 << 16) | 256;
381         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
382                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
383                 OID_AUTO, "rcv_intr_coalesce", CTLFLAG_RW,
384                 &ha->hw.rcv_intr_coalesce,
385                 ha->hw.rcv_intr_coalesce,
386                 "Rcv Intr Coalescing Parameters\n"
387                 "\tbits 15:0 max packets\n"
388                 "\tbits 31:16 max micro-seconds to wait\n"
389                 "\tplease run\n"
390                 "\tifconfig <if> down && ifconfig <if> up\n"
391                 "\tto take effect \n");
392 
393         ha->hw.xmt_intr_coalesce = (64 << 16) | 64;
394         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
395                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
396                 OID_AUTO, "xmt_intr_coalesce", CTLFLAG_RW,
397                 &ha->hw.xmt_intr_coalesce,
398                 ha->hw.xmt_intr_coalesce,
399                 "Xmt Intr Coalescing Parameters\n"
400                 "\tbits 15:0 max packets\n"
401                 "\tbits 31:16 max micro-seconds to wait\n"
402                 "\tplease run\n"
403                 "\tifconfig <if> down && ifconfig <if> up\n"
404                 "\tto take effect \n");
405 
406         SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
407                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
408                 OID_AUTO, "port_cfg", CTLTYPE_INT | CTLFLAG_RW,
409                 (void *)ha, 0,
410                 qla_sysctl_port_cfg, "I",
411                         "Set Port Configuration if values below "
412                         "otherwise Get Port Configuration\n"
413                         "\tBits 0-3 ; 1 = DCBX Enable; 0 = DCBX Disable\n"
414                         "\tBits 4-7 : 0 = no pause; 1 = std ; 2 = ppm \n"
415                         "\tBits 8-11: std pause cfg; 0 = xmt and rcv;"
416                         " 1 = xmt only; 2 = rcv only;\n"
417                 );
418 
419 	SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
420 		SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
421 		OID_AUTO, "set_cam_search_mode", CTLTYPE_INT | CTLFLAG_RW,
422 		(void *)ha, 0,
423 		qla_sysctl_set_cam_search_mode, "I",
424 			"Set CAM Search Mode"
425 			"\t 1 = search mode internal\n"
426 			"\t 2 = search mode auto\n");
427 
428 	SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
429 		SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
430 		OID_AUTO, "get_cam_search_mode", CTLTYPE_INT | CTLFLAG_RW,
431 		(void *)ha, 0,
432 		qla_sysctl_get_cam_search_mode, "I",
433 			"Get CAM Search Mode"
434 			"\t 1 = search mode internal\n"
435 			"\t 2 = search mode auto\n");
436 
437         ha->hw.enable_9kb = 1;
438 
439         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
440                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
441                 OID_AUTO, "enable_9kb", CTLFLAG_RW, &ha->hw.enable_9kb,
442                 ha->hw.enable_9kb, "Enable 9Kbyte Buffers when MTU = 9000");
443 
444 	ha->hw.mdump_active = 0;
445         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
446                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
447                 OID_AUTO, "minidump_active", CTLFLAG_RW, &ha->hw.mdump_active,
448 		ha->hw.mdump_active,
449 		"Minidump retrieval is Active");
450 
451 	ha->hw.mdump_done = 0;
452         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
453                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
454                 OID_AUTO, "mdump_done", CTLFLAG_RW,
455 		&ha->hw.mdump_done, ha->hw.mdump_done,
456 		"Minidump has been done and available for retrieval");
457 
458 	ha->hw.mdump_capture_mask = 0xF;
459         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
460                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
461                 OID_AUTO, "minidump_capture_mask", CTLFLAG_RW,
462 		&ha->hw.mdump_capture_mask, ha->hw.mdump_capture_mask,
463 		"Minidump capture mask");
464 #ifdef QL_DBG
465 
466 	ha->err_inject = 0;
467         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
468                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
469                 OID_AUTO, "err_inject",
470                 CTLFLAG_RW, &ha->err_inject, ha->err_inject,
471                 "Error to be injected\n"
472                 "\t\t\t 0: No Errors\n"
473                 "\t\t\t 1: rcv: rxb struct invalid\n"
474                 "\t\t\t 2: rcv: mp == NULL\n"
475                 "\t\t\t 3: lro: rxb struct invalid\n"
476                 "\t\t\t 4: lro: mp == NULL\n"
477                 "\t\t\t 5: rcv: num handles invalid\n"
478                 "\t\t\t 6: reg: indirect reg rd_wr failure\n"
479                 "\t\t\t 7: ocm: offchip memory rd_wr failure\n"
480                 "\t\t\t 8: mbx: mailbox command failure\n"
481                 "\t\t\t 9: heartbeat failure\n"
482                 "\t\t\t A: temperature failure\n"
483 		"\t\t\t 11: m_getcl or m_getjcl failure\n" );
484 
485 	SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
486                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
487                 OID_AUTO, "peg_stop", CTLTYPE_INT | CTLFLAG_RW,
488                 (void *)ha, 0,
489                 qla_sysctl_stop_pegs, "I", "Peg Stop");
490 
491 #endif /* #ifdef QL_DBG */
492 
493         ha->hw.user_pri_nic = 0;
494         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
495                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
496                 OID_AUTO, "user_pri_nic", CTLFLAG_RW, &ha->hw.user_pri_nic,
497                 ha->hw.user_pri_nic,
498                 "VLAN Tag User Priority for Normal Ethernet Packets");
499 
500         ha->hw.user_pri_iscsi = 4;
501         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
502                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
503                 OID_AUTO, "user_pri_iscsi", CTLFLAG_RW, &ha->hw.user_pri_iscsi,
504                 ha->hw.user_pri_iscsi,
505                 "VLAN Tag User Priority for iSCSI Packets");
506 
507 }
508 
509 void
510 ql_hw_link_status(qla_host_t *ha)
511 {
512 	device_printf(ha->pci_dev, "cable_oui\t\t 0x%08x\n", ha->hw.cable_oui);
513 
514 	if (ha->hw.link_up) {
515 		device_printf(ha->pci_dev, "link Up\n");
516 	} else {
517 		device_printf(ha->pci_dev, "link Down\n");
518 	}
519 
520 	if (ha->hw.flags.fduplex) {
521 		device_printf(ha->pci_dev, "Full Duplex\n");
522 	} else {
523 		device_printf(ha->pci_dev, "Half Duplex\n");
524 	}
525 
526 	if (ha->hw.flags.autoneg) {
527 		device_printf(ha->pci_dev, "Auto Negotiation Enabled\n");
528 	} else {
529 		device_printf(ha->pci_dev, "Auto Negotiation Disabled\n");
530 	}
531 
532 	switch (ha->hw.link_speed) {
533 	case 0x710:
534 		device_printf(ha->pci_dev, "link speed\t\t 10Gps\n");
535 		break;
536 
537 	case 0x3E8:
538 		device_printf(ha->pci_dev, "link speed\t\t 1Gps\n");
539 		break;
540 
541 	case 0x64:
542 		device_printf(ha->pci_dev, "link speed\t\t 100Mbps\n");
543 		break;
544 
545 	default:
546 		device_printf(ha->pci_dev, "link speed\t\t Unknown\n");
547 		break;
548 	}
549 
550 	switch (ha->hw.module_type) {
551 
552 	case 0x01:
553 		device_printf(ha->pci_dev, "Module Type 10GBase-LRM\n");
554 		break;
555 
556 	case 0x02:
557 		device_printf(ha->pci_dev, "Module Type 10GBase-LR\n");
558 		break;
559 
560 	case 0x03:
561 		device_printf(ha->pci_dev, "Module Type 10GBase-SR\n");
562 		break;
563 
564 	case 0x04:
565 		device_printf(ha->pci_dev,
566 			"Module Type 10GE Passive Copper(Compliant)[%d m]\n",
567 			ha->hw.cable_length);
568 		break;
569 
570 	case 0x05:
571 		device_printf(ha->pci_dev, "Module Type 10GE Active"
572 			" Limiting Copper(Compliant)[%d m]\n",
573 			ha->hw.cable_length);
574 		break;
575 
576 	case 0x06:
577 		device_printf(ha->pci_dev,
578 			"Module Type 10GE Passive Copper"
579 			" (Legacy, Best Effort)[%d m]\n",
580 			ha->hw.cable_length);
581 		break;
582 
583 	case 0x07:
584 		device_printf(ha->pci_dev, "Module Type 1000Base-SX\n");
585 		break;
586 
587 	case 0x08:
588 		device_printf(ha->pci_dev, "Module Type 1000Base-LX\n");
589 		break;
590 
591 	case 0x09:
592 		device_printf(ha->pci_dev, "Module Type 1000Base-CX\n");
593 		break;
594 
595 	case 0x0A:
596 		device_printf(ha->pci_dev, "Module Type 1000Base-T\n");
597 		break;
598 
599 	case 0x0B:
600 		device_printf(ha->pci_dev, "Module Type 1GE Passive Copper"
601 			"(Legacy, Best Effort)\n");
602 		break;
603 
604 	default:
605 		device_printf(ha->pci_dev, "Unknown Module Type 0x%x\n",
606 			ha->hw.module_type);
607 		break;
608 	}
609 
610 	if (ha->hw.link_faults == 1)
611 		device_printf(ha->pci_dev, "SFP Power Fault\n");
612 }
613 
614 /*
615  * Name: ql_free_dma
616  * Function: Frees the DMA'able memory allocated in ql_alloc_dma()
617  */
618 void
619 ql_free_dma(qla_host_t *ha)
620 {
621 	uint32_t i;
622 
623         if (ha->hw.dma_buf.flags.sds_ring) {
624 		for (i = 0; i < ha->hw.num_sds_rings; i++) {
625 			ql_free_dmabuf(ha, &ha->hw.dma_buf.sds_ring[i]);
626 		}
627         	ha->hw.dma_buf.flags.sds_ring = 0;
628 	}
629 
630         if (ha->hw.dma_buf.flags.rds_ring) {
631 		for (i = 0; i < ha->hw.num_rds_rings; i++) {
632 			ql_free_dmabuf(ha, &ha->hw.dma_buf.rds_ring[i]);
633 		}
634         	ha->hw.dma_buf.flags.rds_ring = 0;
635 	}
636 
637         if (ha->hw.dma_buf.flags.tx_ring) {
638 		ql_free_dmabuf(ha, &ha->hw.dma_buf.tx_ring);
639         	ha->hw.dma_buf.flags.tx_ring = 0;
640 	}
641 	ql_minidump_free(ha);
642 }
643 
644 /*
645  * Name: ql_alloc_dma
646  * Function: Allocates DMA'able memory for Tx/Rx Rings, Tx/Rx Contexts.
647  */
648 int
649 ql_alloc_dma(qla_host_t *ha)
650 {
651         device_t                dev;
652 	uint32_t		i, j, size, tx_ring_size;
653 	qla_hw_t		*hw;
654 	qla_hw_tx_cntxt_t	*tx_cntxt;
655 	uint8_t			*vaddr;
656 	bus_addr_t		paddr;
657 
658         dev = ha->pci_dev;
659 
660         QL_DPRINT2(ha, (dev, "%s: enter\n", __func__));
661 
662 	hw = &ha->hw;
663 	/*
664 	 * Allocate Transmit Ring
665 	 */
666 	tx_ring_size = (sizeof(q80_tx_cmd_t) * NUM_TX_DESCRIPTORS);
667 	size = (tx_ring_size * ha->hw.num_tx_rings);
668 
669 	hw->dma_buf.tx_ring.alignment = 8;
670 	hw->dma_buf.tx_ring.size = size + PAGE_SIZE;
671 
672         if (ql_alloc_dmabuf(ha, &hw->dma_buf.tx_ring)) {
673                 device_printf(dev, "%s: tx ring alloc failed\n", __func__);
674                 goto ql_alloc_dma_exit;
675         }
676 
677 	vaddr = (uint8_t *)hw->dma_buf.tx_ring.dma_b;
678 	paddr = hw->dma_buf.tx_ring.dma_addr;
679 
680 	for (i = 0; i < ha->hw.num_tx_rings; i++) {
681 		tx_cntxt = (qla_hw_tx_cntxt_t *)&hw->tx_cntxt[i];
682 
683 		tx_cntxt->tx_ring_base = (q80_tx_cmd_t *)vaddr;
684 		tx_cntxt->tx_ring_paddr = paddr;
685 
686 		vaddr += tx_ring_size;
687 		paddr += tx_ring_size;
688 	}
689 
690 	for (i = 0; i < ha->hw.num_tx_rings; i++) {
691 		tx_cntxt = (qla_hw_tx_cntxt_t *)&hw->tx_cntxt[i];
692 
693 		tx_cntxt->tx_cons = (uint32_t *)vaddr;
694 		tx_cntxt->tx_cons_paddr = paddr;
695 
696 		vaddr += sizeof (uint32_t);
697 		paddr += sizeof (uint32_t);
698 	}
699 
700         ha->hw.dma_buf.flags.tx_ring = 1;
701 
702 	QL_DPRINT2(ha, (dev, "%s: tx_ring phys %p virt %p\n",
703 		__func__, (void *)(hw->dma_buf.tx_ring.dma_addr),
704 		hw->dma_buf.tx_ring.dma_b));
705 	/*
706 	 * Allocate Receive Descriptor Rings
707 	 */
708 
709 	for (i = 0; i < hw->num_rds_rings; i++) {
710 
711 		hw->dma_buf.rds_ring[i].alignment = 8;
712 		hw->dma_buf.rds_ring[i].size =
713 			(sizeof(q80_recv_desc_t)) * NUM_RX_DESCRIPTORS;
714 
715 		if (ql_alloc_dmabuf(ha, &hw->dma_buf.rds_ring[i])) {
716 			device_printf(dev, "%s: rds ring[%d] alloc failed\n",
717 				__func__, i);
718 
719 			for (j = 0; j < i; j++)
720 				ql_free_dmabuf(ha, &hw->dma_buf.rds_ring[j]);
721 
722 			goto ql_alloc_dma_exit;
723 		}
724 		QL_DPRINT4(ha, (dev, "%s: rx_ring[%d] phys %p virt %p\n",
725 			__func__, i, (void *)(hw->dma_buf.rds_ring[i].dma_addr),
726 			hw->dma_buf.rds_ring[i].dma_b));
727 	}
728 
729 	hw->dma_buf.flags.rds_ring = 1;
730 
731 	/*
732 	 * Allocate Status Descriptor Rings
733 	 */
734 
735 	for (i = 0; i < hw->num_sds_rings; i++) {
736 		hw->dma_buf.sds_ring[i].alignment = 8;
737 		hw->dma_buf.sds_ring[i].size =
738 			(sizeof(q80_stat_desc_t)) * NUM_STATUS_DESCRIPTORS;
739 
740 		if (ql_alloc_dmabuf(ha, &hw->dma_buf.sds_ring[i])) {
741 			device_printf(dev, "%s: sds ring alloc failed\n",
742 				__func__);
743 
744 			for (j = 0; j < i; j++)
745 				ql_free_dmabuf(ha, &hw->dma_buf.sds_ring[j]);
746 
747 			goto ql_alloc_dma_exit;
748 		}
749 		QL_DPRINT4(ha, (dev, "%s: sds_ring[%d] phys %p virt %p\n",
750 			__func__, i,
751 			(void *)(hw->dma_buf.sds_ring[i].dma_addr),
752 			hw->dma_buf.sds_ring[i].dma_b));
753 	}
754 	for (i = 0; i < hw->num_sds_rings; i++) {
755 		hw->sds[i].sds_ring_base =
756 			(q80_stat_desc_t *)hw->dma_buf.sds_ring[i].dma_b;
757 	}
758 
759 	hw->dma_buf.flags.sds_ring = 1;
760 
761 	return 0;
762 
763 ql_alloc_dma_exit:
764 	ql_free_dma(ha);
765 	return -1;
766 }
767 
768 #define Q8_MBX_MSEC_DELAY	5000
769 
770 static int
771 qla_mbx_cmd(qla_host_t *ha, uint32_t *h_mbox, uint32_t n_hmbox,
772 	uint32_t *fw_mbox, uint32_t n_fwmbox, uint32_t no_pause)
773 {
774 	uint32_t i;
775 	uint32_t data;
776 	int ret = 0;
777 
778 	if (QL_ERR_INJECT(ha, INJCT_MBX_CMD_FAILURE)) {
779 		ret = -3;
780 		ha->qla_initiate_recovery = 1;
781 		goto exit_qla_mbx_cmd;
782 	}
783 
784 	if (no_pause)
785 		i = 1000;
786 	else
787 		i = Q8_MBX_MSEC_DELAY;
788 
789 	while (i) {
790 		data = READ_REG32(ha, Q8_HOST_MBOX_CNTRL);
791 		if (data == 0)
792 			break;
793 		if (no_pause) {
794 			DELAY(1000);
795 		} else {
796 			qla_mdelay(__func__, 1);
797 		}
798 		i--;
799 	}
800 
801 	if (i == 0) {
802 		device_printf(ha->pci_dev, "%s: host_mbx_cntrl 0x%08x\n",
803 			__func__, data);
804 		ret = -1;
805 		ha->qla_initiate_recovery = 1;
806 		goto exit_qla_mbx_cmd;
807 	}
808 
809 	for (i = 0; i < n_hmbox; i++) {
810 		WRITE_REG32(ha, (Q8_HOST_MBOX0 + (i << 2)), *h_mbox);
811 		h_mbox++;
812 	}
813 
814 	WRITE_REG32(ha, Q8_HOST_MBOX_CNTRL, 0x1);
815 
816 
817 	i = Q8_MBX_MSEC_DELAY;
818 	while (i) {
819 		data = READ_REG32(ha, Q8_FW_MBOX_CNTRL);
820 
821 		if ((data & 0x3) == 1) {
822 			data = READ_REG32(ha, Q8_FW_MBOX0);
823 			if ((data & 0xF000) != 0x8000)
824 				break;
825 		}
826 		if (no_pause) {
827 			DELAY(1000);
828 		} else {
829 			qla_mdelay(__func__, 1);
830 		}
831 		i--;
832 	}
833 	if (i == 0) {
834 		device_printf(ha->pci_dev, "%s: fw_mbx_cntrl 0x%08x\n",
835 			__func__, data);
836 		ret = -2;
837 		ha->qla_initiate_recovery = 1;
838 		goto exit_qla_mbx_cmd;
839 	}
840 
841 	for (i = 0; i < n_fwmbox; i++) {
842 		*fw_mbox++ = READ_REG32(ha, (Q8_FW_MBOX0 + (i << 2)));
843 	}
844 
845 	WRITE_REG32(ha, Q8_FW_MBOX_CNTRL, 0x0);
846 	WRITE_REG32(ha, ha->hw.mbx_intr_mask_offset, 0x0);
847 
848 exit_qla_mbx_cmd:
849 	return (ret);
850 }
851 
852 int
853 qla_get_nic_partition(qla_host_t *ha, uint32_t *supports_9kb,
854 	uint32_t *num_rcvq)
855 {
856 	uint32_t *mbox, err;
857 	device_t dev = ha->pci_dev;
858 
859 	bzero(ha->hw.mbox, (sizeof (uint32_t) * Q8_NUM_MBOX));
860 
861 	mbox = ha->hw.mbox;
862 
863 	mbox[0] = Q8_MBX_GET_NIC_PARTITION | (0x2 << 16) | (0x2 << 29);
864 
865 	if (qla_mbx_cmd(ha, mbox, 2, mbox, 19, 0)) {
866 		device_printf(dev, "%s: failed0\n", __func__);
867 		return (-1);
868 	}
869 	err = mbox[0] >> 25;
870 
871 	if (supports_9kb != NULL) {
872 		if (mbox[16] & 0x80) /* bit 7 of mbox 16 */
873 			*supports_9kb = 1;
874 		else
875 			*supports_9kb = 0;
876 	}
877 
878 	if (num_rcvq != NULL)
879 		*num_rcvq =  ((mbox[6] >> 16) & 0xFFFF);
880 
881 	if ((err != 1) && (err != 0)) {
882 		device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
883 		return (-1);
884 	}
885 	return 0;
886 }
887 
888 static int
889 qla_config_intr_cntxt(qla_host_t *ha, uint32_t start_idx, uint32_t num_intrs,
890 	uint32_t create)
891 {
892 	uint32_t i, err;
893 	device_t dev = ha->pci_dev;
894 	q80_config_intr_t *c_intr;
895 	q80_config_intr_rsp_t *c_intr_rsp;
896 
897 	c_intr = (q80_config_intr_t *)ha->hw.mbox;
898 	bzero(c_intr, (sizeof (q80_config_intr_t)));
899 
900 	c_intr->opcode = Q8_MBX_CONFIG_INTR;
901 
902 	c_intr->count_version = (sizeof (q80_config_intr_t) >> 2);
903 	c_intr->count_version |= Q8_MBX_CMD_VERSION;
904 
905 	c_intr->nentries = num_intrs;
906 
907 	for (i = 0; i < num_intrs; i++) {
908 		if (create) {
909 			c_intr->intr[i].cmd_type = Q8_MBX_CONFIG_INTR_CREATE;
910 			c_intr->intr[i].msix_index = start_idx + 1 + i;
911 		} else {
912 			c_intr->intr[i].cmd_type = Q8_MBX_CONFIG_INTR_DELETE;
913 			c_intr->intr[i].msix_index =
914 				ha->hw.intr_id[(start_idx + i)];
915 		}
916 
917 		c_intr->intr[i].cmd_type |= Q8_MBX_CONFIG_INTR_TYPE_MSI_X;
918 	}
919 
920 	if (qla_mbx_cmd(ha, (uint32_t *)c_intr,
921 		(sizeof (q80_config_intr_t) >> 2),
922 		ha->hw.mbox, (sizeof (q80_config_intr_rsp_t) >> 2), 0)) {
923 		device_printf(dev, "%s: failed0\n", __func__);
924 		return (-1);
925 	}
926 
927 	c_intr_rsp = (q80_config_intr_rsp_t *)ha->hw.mbox;
928 
929 	err = Q8_MBX_RSP_STATUS(c_intr_rsp->regcnt_status);
930 
931 	if (err) {
932 		device_printf(dev, "%s: failed1 [0x%08x, %d]\n", __func__, err,
933 			c_intr_rsp->nentries);
934 
935 		for (i = 0; i < c_intr_rsp->nentries; i++) {
936 			device_printf(dev, "%s: [%d]:[0x%x 0x%x 0x%x]\n",
937 				__func__, i,
938 				c_intr_rsp->intr[i].status,
939 				c_intr_rsp->intr[i].intr_id,
940 				c_intr_rsp->intr[i].intr_src);
941 		}
942 
943 		return (-1);
944 	}
945 
946 	for (i = 0; ((i < num_intrs) && create); i++) {
947 		if (!c_intr_rsp->intr[i].status) {
948 			ha->hw.intr_id[(start_idx + i)] =
949 				c_intr_rsp->intr[i].intr_id;
950 			ha->hw.intr_src[(start_idx + i)] =
951 				c_intr_rsp->intr[i].intr_src;
952 		}
953 	}
954 
955 	return (0);
956 }
957 
958 /*
959  * Name: qla_config_rss
960  * Function: Configure RSS for the context/interface.
961  */
962 static const uint64_t rss_key[] = { 0xbeac01fa6a42b73bULL,
963 			0x8030f20c77cb2da3ULL,
964 			0xae7b30b4d0ca2bcbULL, 0x43a38fb04167253dULL,
965 			0x255b0ec26d5a56daULL };
966 
967 static int
968 qla_config_rss(qla_host_t *ha, uint16_t cntxt_id)
969 {
970 	q80_config_rss_t	*c_rss;
971 	q80_config_rss_rsp_t	*c_rss_rsp;
972 	uint32_t		err, i;
973 	device_t		dev = ha->pci_dev;
974 
975 	c_rss = (q80_config_rss_t *)ha->hw.mbox;
976 	bzero(c_rss, (sizeof (q80_config_rss_t)));
977 
978 	c_rss->opcode = Q8_MBX_CONFIG_RSS;
979 
980 	c_rss->count_version = (sizeof (q80_config_rss_t) >> 2);
981 	c_rss->count_version |= Q8_MBX_CMD_VERSION;
982 
983 	c_rss->hash_type = (Q8_MBX_RSS_HASH_TYPE_IPV4_TCP_IP |
984 				Q8_MBX_RSS_HASH_TYPE_IPV6_TCP_IP);
985 	//c_rss->hash_type = (Q8_MBX_RSS_HASH_TYPE_IPV4_TCP |
986 	//			Q8_MBX_RSS_HASH_TYPE_IPV6_TCP);
987 
988 	c_rss->flags = Q8_MBX_RSS_FLAGS_ENABLE_RSS;
989 	c_rss->flags |= Q8_MBX_RSS_FLAGS_USE_IND_TABLE;
990 
991 	c_rss->indtbl_mask = Q8_MBX_RSS_INDTBL_MASK;
992 
993 	c_rss->indtbl_mask |= Q8_MBX_RSS_FLAGS_MULTI_RSS_VALID;
994 	c_rss->flags |= Q8_MBX_RSS_FLAGS_TYPE_CRSS;
995 
996 	c_rss->cntxt_id = cntxt_id;
997 
998 	for (i = 0; i < 5; i++) {
999 		c_rss->rss_key[i] = rss_key[i];
1000 	}
1001 
1002 	if (qla_mbx_cmd(ha, (uint32_t *)c_rss,
1003 		(sizeof (q80_config_rss_t) >> 2),
1004 		ha->hw.mbox, (sizeof(q80_config_rss_rsp_t) >> 2), 0)) {
1005 		device_printf(dev, "%s: failed0\n", __func__);
1006 		return (-1);
1007 	}
1008 	c_rss_rsp = (q80_config_rss_rsp_t *)ha->hw.mbox;
1009 
1010 	err = Q8_MBX_RSP_STATUS(c_rss_rsp->regcnt_status);
1011 
1012 	if (err) {
1013 		device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
1014 		return (-1);
1015 	}
1016 	return 0;
1017 }
1018 
1019 static int
1020 qla_set_rss_ind_table(qla_host_t *ha, uint32_t start_idx, uint32_t count,
1021         uint16_t cntxt_id, uint8_t *ind_table)
1022 {
1023         q80_config_rss_ind_table_t      *c_rss_ind;
1024         q80_config_rss_ind_table_rsp_t  *c_rss_ind_rsp;
1025         uint32_t                        err;
1026         device_t                        dev = ha->pci_dev;
1027 
1028 	if ((count > Q8_RSS_IND_TBL_SIZE) ||
1029 		((start_idx + count - 1) > Q8_RSS_IND_TBL_MAX_IDX)) {
1030 		device_printf(dev, "%s: illegal count [%d, %d]\n", __func__,
1031 			start_idx, count);
1032 		return (-1);
1033 	}
1034 
1035         c_rss_ind = (q80_config_rss_ind_table_t *)ha->hw.mbox;
1036         bzero(c_rss_ind, sizeof (q80_config_rss_ind_table_t));
1037 
1038         c_rss_ind->opcode = Q8_MBX_CONFIG_RSS_TABLE;
1039         c_rss_ind->count_version = (sizeof (q80_config_rss_ind_table_t) >> 2);
1040         c_rss_ind->count_version |= Q8_MBX_CMD_VERSION;
1041 
1042 	c_rss_ind->start_idx = start_idx;
1043 	c_rss_ind->end_idx = start_idx + count - 1;
1044 	c_rss_ind->cntxt_id = cntxt_id;
1045 	bcopy(ind_table, c_rss_ind->ind_table, count);
1046 
1047 	if (qla_mbx_cmd(ha, (uint32_t *)c_rss_ind,
1048 		(sizeof (q80_config_rss_ind_table_t) >> 2), ha->hw.mbox,
1049 		(sizeof(q80_config_rss_ind_table_rsp_t) >> 2), 0)) {
1050 		device_printf(dev, "%s: failed0\n", __func__);
1051 		return (-1);
1052 	}
1053 
1054 	c_rss_ind_rsp = (q80_config_rss_ind_table_rsp_t *)ha->hw.mbox;
1055 	err = Q8_MBX_RSP_STATUS(c_rss_ind_rsp->regcnt_status);
1056 
1057 	if (err) {
1058 		device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
1059 		return (-1);
1060 	}
1061 	return 0;
1062 }
1063 
1064 /*
1065  * Name: qla_config_intr_coalesce
1066  * Function: Configure Interrupt Coalescing.
1067  */
1068 static int
1069 qla_config_intr_coalesce(qla_host_t *ha, uint16_t cntxt_id, int tenable,
1070 	int rcv)
1071 {
1072 	q80_config_intr_coalesc_t	*intrc;
1073 	q80_config_intr_coalesc_rsp_t	*intrc_rsp;
1074 	uint32_t			err, i;
1075 	device_t			dev = ha->pci_dev;
1076 
1077 	intrc = (q80_config_intr_coalesc_t *)ha->hw.mbox;
1078 	bzero(intrc, (sizeof (q80_config_intr_coalesc_t)));
1079 
1080 	intrc->opcode = Q8_MBX_CONFIG_INTR_COALESCE;
1081 	intrc->count_version = (sizeof (q80_config_intr_coalesc_t) >> 2);
1082 	intrc->count_version |= Q8_MBX_CMD_VERSION;
1083 
1084 	if (rcv) {
1085 		intrc->flags = Q8_MBX_INTRC_FLAGS_RCV;
1086 		intrc->max_pkts = ha->hw.rcv_intr_coalesce & 0xFFFF;
1087 		intrc->max_mswait = (ha->hw.rcv_intr_coalesce >> 16) & 0xFFFF;
1088 	} else {
1089 		intrc->flags = Q8_MBX_INTRC_FLAGS_XMT;
1090 		intrc->max_pkts = ha->hw.xmt_intr_coalesce & 0xFFFF;
1091 		intrc->max_mswait = (ha->hw.xmt_intr_coalesce >> 16) & 0xFFFF;
1092 	}
1093 
1094 	intrc->cntxt_id = cntxt_id;
1095 
1096 	if (tenable) {
1097 		intrc->flags |= Q8_MBX_INTRC_FLAGS_PERIODIC;
1098 		intrc->timer_type = Q8_MBX_INTRC_TIMER_PERIODIC;
1099 
1100 		for (i = 0; i < ha->hw.num_sds_rings; i++) {
1101 			intrc->sds_ring_mask |= (1 << i);
1102 		}
1103 		intrc->ms_timeout = 1000;
1104 	}
1105 
1106 	if (qla_mbx_cmd(ha, (uint32_t *)intrc,
1107 		(sizeof (q80_config_intr_coalesc_t) >> 2),
1108 		ha->hw.mbox, (sizeof(q80_config_intr_coalesc_rsp_t) >> 2), 0)) {
1109 		device_printf(dev, "%s: failed0\n", __func__);
1110 		return (-1);
1111 	}
1112 	intrc_rsp = (q80_config_intr_coalesc_rsp_t *)ha->hw.mbox;
1113 
1114 	err = Q8_MBX_RSP_STATUS(intrc_rsp->regcnt_status);
1115 
1116 	if (err) {
1117 		device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
1118 		return (-1);
1119 	}
1120 
1121 	return 0;
1122 }
1123 
1124 
1125 /*
1126  * Name: qla_config_mac_addr
1127  * Function: binds a MAC address to the context/interface.
1128  *	Can be unicast, multicast or broadcast.
1129  */
1130 static int
1131 qla_config_mac_addr(qla_host_t *ha, uint8_t *mac_addr, uint32_t add_mac,
1132 	uint32_t num_mac)
1133 {
1134 	q80_config_mac_addr_t		*cmac;
1135 	q80_config_mac_addr_rsp_t	*cmac_rsp;
1136 	uint32_t			err;
1137 	device_t			dev = ha->pci_dev;
1138 	int				i;
1139 	uint8_t				*mac_cpy = mac_addr;
1140 
1141 	if (num_mac > Q8_MAX_MAC_ADDRS) {
1142 		device_printf(dev, "%s: %s num_mac [0x%x] > Q8_MAX_MAC_ADDRS\n",
1143 			__func__, (add_mac ? "Add" : "Del"), num_mac);
1144 		return (-1);
1145 	}
1146 
1147 	cmac = (q80_config_mac_addr_t *)ha->hw.mbox;
1148 	bzero(cmac, (sizeof (q80_config_mac_addr_t)));
1149 
1150 	cmac->opcode = Q8_MBX_CONFIG_MAC_ADDR;
1151 	cmac->count_version = sizeof (q80_config_mac_addr_t) >> 2;
1152 	cmac->count_version |= Q8_MBX_CMD_VERSION;
1153 
1154 	if (add_mac)
1155 		cmac->cmd = Q8_MBX_CMAC_CMD_ADD_MAC_ADDR;
1156 	else
1157 		cmac->cmd = Q8_MBX_CMAC_CMD_DEL_MAC_ADDR;
1158 
1159 	cmac->cmd |= Q8_MBX_CMAC_CMD_CAM_INGRESS;
1160 
1161 	cmac->nmac_entries = num_mac;
1162 	cmac->cntxt_id = ha->hw.rcv_cntxt_id;
1163 
1164 	for (i = 0; i < num_mac; i++) {
1165 		bcopy(mac_addr, cmac->mac_addr[i].addr, Q8_ETHER_ADDR_LEN);
1166 		mac_addr = mac_addr + ETHER_ADDR_LEN;
1167 	}
1168 
1169 	if (qla_mbx_cmd(ha, (uint32_t *)cmac,
1170 		(sizeof (q80_config_mac_addr_t) >> 2),
1171 		ha->hw.mbox, (sizeof(q80_config_mac_addr_rsp_t) >> 2), 1)) {
1172 		device_printf(dev, "%s: %s failed0\n", __func__,
1173 			(add_mac ? "Add" : "Del"));
1174 		return (-1);
1175 	}
1176 	cmac_rsp = (q80_config_mac_addr_rsp_t *)ha->hw.mbox;
1177 
1178 	err = Q8_MBX_RSP_STATUS(cmac_rsp->regcnt_status);
1179 
1180 	if (err) {
1181 		device_printf(dev, "%s: %s failed1 [0x%08x]\n", __func__,
1182 			(add_mac ? "Add" : "Del"), err);
1183 		for (i = 0; i < num_mac; i++) {
1184 			device_printf(dev, "%s: %02x:%02x:%02x:%02x:%02x:%02x\n",
1185 				__func__, mac_cpy[0], mac_cpy[1], mac_cpy[2],
1186 				mac_cpy[3], mac_cpy[4], mac_cpy[5]);
1187 			mac_cpy += ETHER_ADDR_LEN;
1188 		}
1189 		return (-1);
1190 	}
1191 
1192 	return 0;
1193 }
1194 
1195 
1196 /*
1197  * Name: qla_set_mac_rcv_mode
1198  * Function: Enable/Disable AllMulticast and Promiscous Modes.
1199  */
1200 static int
1201 qla_set_mac_rcv_mode(qla_host_t *ha, uint32_t mode)
1202 {
1203 	q80_config_mac_rcv_mode_t	*rcv_mode;
1204 	uint32_t			err;
1205 	q80_config_mac_rcv_mode_rsp_t	*rcv_mode_rsp;
1206 	device_t			dev = ha->pci_dev;
1207 
1208 	rcv_mode = (q80_config_mac_rcv_mode_t *)ha->hw.mbox;
1209 	bzero(rcv_mode, (sizeof (q80_config_mac_rcv_mode_t)));
1210 
1211 	rcv_mode->opcode = Q8_MBX_CONFIG_MAC_RX_MODE;
1212 	rcv_mode->count_version = sizeof (q80_config_mac_rcv_mode_t) >> 2;
1213 	rcv_mode->count_version |= Q8_MBX_CMD_VERSION;
1214 
1215 	rcv_mode->mode = mode;
1216 
1217 	rcv_mode->cntxt_id = ha->hw.rcv_cntxt_id;
1218 
1219 	if (qla_mbx_cmd(ha, (uint32_t *)rcv_mode,
1220 		(sizeof (q80_config_mac_rcv_mode_t) >> 2),
1221 		ha->hw.mbox, (sizeof(q80_config_mac_rcv_mode_rsp_t) >> 2), 1)) {
1222 		device_printf(dev, "%s: failed0\n", __func__);
1223 		return (-1);
1224 	}
1225 	rcv_mode_rsp = (q80_config_mac_rcv_mode_rsp_t *)ha->hw.mbox;
1226 
1227 	err = Q8_MBX_RSP_STATUS(rcv_mode_rsp->regcnt_status);
1228 
1229 	if (err) {
1230 		device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
1231 		return (-1);
1232 	}
1233 
1234 	return 0;
1235 }
1236 
1237 int
1238 ql_set_promisc(qla_host_t *ha)
1239 {
1240 	int ret;
1241 
1242 	ha->hw.mac_rcv_mode |= Q8_MBX_MAC_RCV_PROMISC_ENABLE;
1243 	ret = qla_set_mac_rcv_mode(ha, ha->hw.mac_rcv_mode);
1244 	return (ret);
1245 }
1246 
1247 void
1248 qla_reset_promisc(qla_host_t *ha)
1249 {
1250 	ha->hw.mac_rcv_mode &= ~Q8_MBX_MAC_RCV_PROMISC_ENABLE;
1251 	(void)qla_set_mac_rcv_mode(ha, ha->hw.mac_rcv_mode);
1252 }
1253 
1254 int
1255 ql_set_allmulti(qla_host_t *ha)
1256 {
1257 	int ret;
1258 
1259 	ha->hw.mac_rcv_mode |= Q8_MBX_MAC_ALL_MULTI_ENABLE;
1260 	ret = qla_set_mac_rcv_mode(ha, ha->hw.mac_rcv_mode);
1261 	return (ret);
1262 }
1263 
1264 void
1265 qla_reset_allmulti(qla_host_t *ha)
1266 {
1267 	ha->hw.mac_rcv_mode &= ~Q8_MBX_MAC_ALL_MULTI_ENABLE;
1268 	(void)qla_set_mac_rcv_mode(ha, ha->hw.mac_rcv_mode);
1269 }
1270 
1271 /*
1272  * Name: ql_set_max_mtu
1273  * Function:
1274  *	Sets the maximum transfer unit size for the specified rcv context.
1275  */
1276 int
1277 ql_set_max_mtu(qla_host_t *ha, uint32_t mtu, uint16_t cntxt_id)
1278 {
1279 	device_t		dev;
1280 	q80_set_max_mtu_t	*max_mtu;
1281 	q80_set_max_mtu_rsp_t	*max_mtu_rsp;
1282 	uint32_t		err;
1283 
1284 	dev = ha->pci_dev;
1285 
1286 	max_mtu = (q80_set_max_mtu_t *)ha->hw.mbox;
1287 	bzero(max_mtu, (sizeof (q80_set_max_mtu_t)));
1288 
1289 	max_mtu->opcode = Q8_MBX_SET_MAX_MTU;
1290 	max_mtu->count_version = (sizeof (q80_set_max_mtu_t) >> 2);
1291 	max_mtu->count_version |= Q8_MBX_CMD_VERSION;
1292 
1293 	max_mtu->cntxt_id = cntxt_id;
1294 	max_mtu->mtu = mtu;
1295 
1296         if (qla_mbx_cmd(ha, (uint32_t *)max_mtu,
1297 		(sizeof (q80_set_max_mtu_t) >> 2),
1298                 ha->hw.mbox, (sizeof (q80_set_max_mtu_rsp_t) >> 2), 1)) {
1299                 device_printf(dev, "%s: failed\n", __func__);
1300                 return -1;
1301         }
1302 
1303 	max_mtu_rsp = (q80_set_max_mtu_rsp_t *)ha->hw.mbox;
1304 
1305         err = Q8_MBX_RSP_STATUS(max_mtu_rsp->regcnt_status);
1306 
1307         if (err) {
1308                 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
1309         }
1310 
1311 	return 0;
1312 }
1313 
1314 static int
1315 qla_link_event_req(qla_host_t *ha, uint16_t cntxt_id)
1316 {
1317 	device_t		dev;
1318 	q80_link_event_t	*lnk;
1319 	q80_link_event_rsp_t	*lnk_rsp;
1320 	uint32_t		err;
1321 
1322 	dev = ha->pci_dev;
1323 
1324 	lnk = (q80_link_event_t *)ha->hw.mbox;
1325 	bzero(lnk, (sizeof (q80_link_event_t)));
1326 
1327 	lnk->opcode = Q8_MBX_LINK_EVENT_REQ;
1328 	lnk->count_version = (sizeof (q80_link_event_t) >> 2);
1329 	lnk->count_version |= Q8_MBX_CMD_VERSION;
1330 
1331 	lnk->cntxt_id = cntxt_id;
1332 	lnk->cmd = Q8_LINK_EVENT_CMD_ENABLE_ASYNC;
1333 
1334         if (qla_mbx_cmd(ha, (uint32_t *)lnk, (sizeof (q80_link_event_t) >> 2),
1335                 ha->hw.mbox, (sizeof (q80_link_event_rsp_t) >> 2), 0)) {
1336                 device_printf(dev, "%s: failed\n", __func__);
1337                 return -1;
1338         }
1339 
1340 	lnk_rsp = (q80_link_event_rsp_t *)ha->hw.mbox;
1341 
1342         err = Q8_MBX_RSP_STATUS(lnk_rsp->regcnt_status);
1343 
1344         if (err) {
1345                 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
1346         }
1347 
1348 	return 0;
1349 }
1350 
1351 static int
1352 qla_config_fw_lro(qla_host_t *ha, uint16_t cntxt_id)
1353 {
1354 	device_t		dev;
1355 	q80_config_fw_lro_t	*fw_lro;
1356 	q80_config_fw_lro_rsp_t	*fw_lro_rsp;
1357 	uint32_t		err;
1358 
1359 	dev = ha->pci_dev;
1360 
1361 	fw_lro = (q80_config_fw_lro_t *)ha->hw.mbox;
1362 	bzero(fw_lro, sizeof(q80_config_fw_lro_t));
1363 
1364 	fw_lro->opcode = Q8_MBX_CONFIG_FW_LRO;
1365 	fw_lro->count_version = (sizeof (q80_config_fw_lro_t) >> 2);
1366 	fw_lro->count_version |= Q8_MBX_CMD_VERSION;
1367 
1368 	fw_lro->flags |= Q8_MBX_FW_LRO_IPV4 | Q8_MBX_FW_LRO_IPV4_WO_DST_IP_CHK;
1369 	fw_lro->flags |= Q8_MBX_FW_LRO_IPV6 | Q8_MBX_FW_LRO_IPV6_WO_DST_IP_CHK;
1370 
1371 	fw_lro->cntxt_id = cntxt_id;
1372 
1373 	if (qla_mbx_cmd(ha, (uint32_t *)fw_lro,
1374 		(sizeof (q80_config_fw_lro_t) >> 2),
1375 		ha->hw.mbox, (sizeof (q80_config_fw_lro_rsp_t) >> 2), 0)) {
1376 		device_printf(dev, "%s: failed\n", __func__);
1377 		return -1;
1378 	}
1379 
1380 	fw_lro_rsp = (q80_config_fw_lro_rsp_t *)ha->hw.mbox;
1381 
1382 	err = Q8_MBX_RSP_STATUS(fw_lro_rsp->regcnt_status);
1383 
1384 	if (err) {
1385 		device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
1386 	}
1387 
1388 	return 0;
1389 }
1390 
1391 static int
1392 qla_set_cam_search_mode(qla_host_t *ha, uint32_t search_mode)
1393 {
1394 	device_t                dev;
1395 	q80_hw_config_t         *hw_config;
1396 	q80_hw_config_rsp_t     *hw_config_rsp;
1397 	uint32_t                err;
1398 
1399 	dev = ha->pci_dev;
1400 
1401 	hw_config = (q80_hw_config_t *)ha->hw.mbox;
1402 	bzero(hw_config, sizeof (q80_hw_config_t));
1403 
1404 	hw_config->opcode = Q8_MBX_HW_CONFIG;
1405 	hw_config->count_version = Q8_HW_CONFIG_SET_CAM_SEARCH_MODE_COUNT;
1406 	hw_config->count_version |= Q8_MBX_CMD_VERSION;
1407 
1408 	hw_config->cmd = Q8_HW_CONFIG_SET_CAM_SEARCH_MODE;
1409 
1410 	hw_config->u.set_cam_search_mode.mode = search_mode;
1411 
1412 	if (qla_mbx_cmd(ha, (uint32_t *)hw_config,
1413 		(sizeof (q80_hw_config_t) >> 2),
1414 		ha->hw.mbox, (sizeof (q80_hw_config_rsp_t) >> 2), 0)) {
1415 		device_printf(dev, "%s: failed\n", __func__);
1416 		return -1;
1417 	}
1418 	hw_config_rsp = (q80_hw_config_rsp_t *)ha->hw.mbox;
1419 
1420 	err = Q8_MBX_RSP_STATUS(hw_config_rsp->regcnt_status);
1421 
1422 	if (err) {
1423 		device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
1424 	}
1425 
1426 	return 0;
1427 }
1428 
1429 static int
1430 qla_get_cam_search_mode(qla_host_t *ha)
1431 {
1432 	device_t                dev;
1433 	q80_hw_config_t         *hw_config;
1434 	q80_hw_config_rsp_t     *hw_config_rsp;
1435 	uint32_t                err;
1436 
1437 	dev = ha->pci_dev;
1438 
1439 	hw_config = (q80_hw_config_t *)ha->hw.mbox;
1440 	bzero(hw_config, sizeof (q80_hw_config_t));
1441 
1442 	hw_config->opcode = Q8_MBX_HW_CONFIG;
1443 	hw_config->count_version = Q8_HW_CONFIG_GET_CAM_SEARCH_MODE_COUNT;
1444 	hw_config->count_version |= Q8_MBX_CMD_VERSION;
1445 
1446 	hw_config->cmd = Q8_HW_CONFIG_GET_CAM_SEARCH_MODE;
1447 
1448 	if (qla_mbx_cmd(ha, (uint32_t *)hw_config,
1449 		(sizeof (q80_hw_config_t) >> 2),
1450 		ha->hw.mbox, (sizeof (q80_hw_config_rsp_t) >> 2), 0)) {
1451 		device_printf(dev, "%s: failed\n", __func__);
1452 		return -1;
1453 	}
1454 	hw_config_rsp = (q80_hw_config_rsp_t *)ha->hw.mbox;
1455 
1456 	err = Q8_MBX_RSP_STATUS(hw_config_rsp->regcnt_status);
1457 
1458 	if (err) {
1459 		device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
1460 	} else {
1461 		device_printf(dev, "%s: cam search mode [0x%08x]\n", __func__,
1462 			hw_config_rsp->u.get_cam_search_mode.mode);
1463 	}
1464 
1465 	return 0;
1466 }
1467 
1468 
1469 
1470 static void
1471 qla_xmt_stats(qla_host_t *ha, q80_xmt_stats_t *xstat, int i)
1472 {
1473 	device_t dev = ha->pci_dev;
1474 
1475 	if (i < ha->hw.num_tx_rings) {
1476 		device_printf(dev, "%s[%d]: total_bytes\t\t%" PRIu64 "\n",
1477 			__func__, i, xstat->total_bytes);
1478 		device_printf(dev, "%s[%d]: total_pkts\t\t%" PRIu64 "\n",
1479 			__func__, i, xstat->total_pkts);
1480 		device_printf(dev, "%s[%d]: errors\t\t%" PRIu64 "\n",
1481 			__func__, i, xstat->errors);
1482 		device_printf(dev, "%s[%d]: pkts_dropped\t%" PRIu64 "\n",
1483 			__func__, i, xstat->pkts_dropped);
1484 		device_printf(dev, "%s[%d]: switch_pkts\t\t%" PRIu64 "\n",
1485 			__func__, i, xstat->switch_pkts);
1486 		device_printf(dev, "%s[%d]: num_buffers\t\t%" PRIu64 "\n",
1487 			__func__, i, xstat->num_buffers);
1488 	} else {
1489 		device_printf(dev, "%s: total_bytes\t\t\t%" PRIu64 "\n",
1490 			__func__, xstat->total_bytes);
1491 		device_printf(dev, "%s: total_pkts\t\t\t%" PRIu64 "\n",
1492 			__func__, xstat->total_pkts);
1493 		device_printf(dev, "%s: errors\t\t\t%" PRIu64 "\n",
1494 			__func__, xstat->errors);
1495 		device_printf(dev, "%s: pkts_dropped\t\t\t%" PRIu64 "\n",
1496 			__func__, xstat->pkts_dropped);
1497 		device_printf(dev, "%s: switch_pkts\t\t\t%" PRIu64 "\n",
1498 			__func__, xstat->switch_pkts);
1499 		device_printf(dev, "%s: num_buffers\t\t\t%" PRIu64 "\n",
1500 			__func__, xstat->num_buffers);
1501 	}
1502 }
1503 
1504 static void
1505 qla_rcv_stats(qla_host_t *ha, q80_rcv_stats_t *rstat)
1506 {
1507 	device_t dev = ha->pci_dev;
1508 
1509 	device_printf(dev, "%s: total_bytes\t\t\t%" PRIu64 "\n", __func__,
1510 		rstat->total_bytes);
1511 	device_printf(dev, "%s: total_pkts\t\t\t%" PRIu64 "\n", __func__,
1512 		rstat->total_pkts);
1513 	device_printf(dev, "%s: lro_pkt_count\t\t%" PRIu64 "\n", __func__,
1514 		rstat->lro_pkt_count);
1515 	device_printf(dev, "%s: sw_pkt_count\t\t\t%" PRIu64 "\n", __func__,
1516 		rstat->sw_pkt_count);
1517 	device_printf(dev, "%s: ip_chksum_err\t\t%" PRIu64 "\n", __func__,
1518 		rstat->ip_chksum_err);
1519 	device_printf(dev, "%s: pkts_wo_acntxts\t\t%" PRIu64 "\n", __func__,
1520 		rstat->pkts_wo_acntxts);
1521 	device_printf(dev, "%s: pkts_dropped_no_sds_card\t%" PRIu64 "\n",
1522 		__func__, rstat->pkts_dropped_no_sds_card);
1523 	device_printf(dev, "%s: pkts_dropped_no_sds_host\t%" PRIu64 "\n",
1524 		__func__, rstat->pkts_dropped_no_sds_host);
1525 	device_printf(dev, "%s: oversized_pkts\t\t%" PRIu64 "\n", __func__,
1526 		rstat->oversized_pkts);
1527 	device_printf(dev, "%s: pkts_dropped_no_rds\t\t%" PRIu64 "\n",
1528 		__func__, rstat->pkts_dropped_no_rds);
1529 	device_printf(dev, "%s: unxpctd_mcast_pkts\t\t%" PRIu64 "\n",
1530 		__func__, rstat->unxpctd_mcast_pkts);
1531 	device_printf(dev, "%s: re1_fbq_error\t\t%" PRIu64 "\n", __func__,
1532 		rstat->re1_fbq_error);
1533 	device_printf(dev, "%s: invalid_mac_addr\t\t%" PRIu64 "\n", __func__,
1534 		rstat->invalid_mac_addr);
1535 	device_printf(dev, "%s: rds_prime_trys\t\t%" PRIu64 "\n", __func__,
1536 		rstat->rds_prime_trys);
1537 	device_printf(dev, "%s: rds_prime_success\t\t%" PRIu64 "\n", __func__,
1538 		rstat->rds_prime_success);
1539 	device_printf(dev, "%s: lro_flows_added\t\t%" PRIu64 "\n", __func__,
1540 		rstat->lro_flows_added);
1541 	device_printf(dev, "%s: lro_flows_deleted\t\t%" PRIu64 "\n", __func__,
1542 		rstat->lro_flows_deleted);
1543 	device_printf(dev, "%s: lro_flows_active\t\t%" PRIu64 "\n", __func__,
1544 		rstat->lro_flows_active);
1545 	device_printf(dev, "%s: pkts_droped_unknown\t\t%" PRIu64 "\n",
1546 		__func__, rstat->pkts_droped_unknown);
1547 }
1548 
1549 static void
1550 qla_mac_stats(qla_host_t *ha, q80_mac_stats_t *mstat)
1551 {
1552 	device_t dev = ha->pci_dev;
1553 
1554 	device_printf(dev, "%s: xmt_frames\t\t\t%" PRIu64 "\n", __func__,
1555 		mstat->xmt_frames);
1556 	device_printf(dev, "%s: xmt_bytes\t\t\t%" PRIu64 "\n", __func__,
1557 		mstat->xmt_bytes);
1558 	device_printf(dev, "%s: xmt_mcast_pkts\t\t%" PRIu64 "\n", __func__,
1559 		mstat->xmt_mcast_pkts);
1560 	device_printf(dev, "%s: xmt_bcast_pkts\t\t%" PRIu64 "\n", __func__,
1561 		mstat->xmt_bcast_pkts);
1562 	device_printf(dev, "%s: xmt_pause_frames\t\t%" PRIu64 "\n", __func__,
1563 		mstat->xmt_pause_frames);
1564 	device_printf(dev, "%s: xmt_cntrl_pkts\t\t%" PRIu64 "\n", __func__,
1565 		mstat->xmt_cntrl_pkts);
1566 	device_printf(dev, "%s: xmt_pkt_lt_64bytes\t\t%" PRIu64 "\n",
1567 		__func__, mstat->xmt_pkt_lt_64bytes);
1568 	device_printf(dev, "%s: xmt_pkt_lt_127bytes\t\t%" PRIu64 "\n",
1569 		__func__, mstat->xmt_pkt_lt_127bytes);
1570 	device_printf(dev, "%s: xmt_pkt_lt_255bytes\t\t%" PRIu64 "\n",
1571 		__func__, mstat->xmt_pkt_lt_255bytes);
1572 	device_printf(dev, "%s: xmt_pkt_lt_511bytes\t\t%" PRIu64 "\n",
1573 		__func__, mstat->xmt_pkt_lt_511bytes);
1574 	device_printf(dev, "%s: xmt_pkt_lt_1023bytes\t\t%" PRIu64 "\n",
1575 		__func__, mstat->xmt_pkt_lt_1023bytes);
1576 	device_printf(dev, "%s: xmt_pkt_lt_1518bytes\t\t%" PRIu64 "\n",
1577 		__func__, mstat->xmt_pkt_lt_1518bytes);
1578 	device_printf(dev, "%s: xmt_pkt_gt_1518bytes\t\t%" PRIu64 "\n",
1579 		__func__, mstat->xmt_pkt_gt_1518bytes);
1580 
1581 	device_printf(dev, "%s: rcv_frames\t\t\t%" PRIu64 "\n", __func__,
1582 		mstat->rcv_frames);
1583 	device_printf(dev, "%s: rcv_bytes\t\t\t%" PRIu64 "\n", __func__,
1584 		mstat->rcv_bytes);
1585 	device_printf(dev, "%s: rcv_mcast_pkts\t\t%" PRIu64 "\n", __func__,
1586 		mstat->rcv_mcast_pkts);
1587 	device_printf(dev, "%s: rcv_bcast_pkts\t\t%" PRIu64 "\n", __func__,
1588 		mstat->rcv_bcast_pkts);
1589 	device_printf(dev, "%s: rcv_pause_frames\t\t%" PRIu64 "\n", __func__,
1590 		mstat->rcv_pause_frames);
1591 	device_printf(dev, "%s: rcv_cntrl_pkts\t\t%" PRIu64 "\n", __func__,
1592 		mstat->rcv_cntrl_pkts);
1593 	device_printf(dev, "%s: rcv_pkt_lt_64bytes\t\t%" PRIu64 "\n",
1594 		__func__, mstat->rcv_pkt_lt_64bytes);
1595 	device_printf(dev, "%s: rcv_pkt_lt_127bytes\t\t%" PRIu64 "\n",
1596 		__func__, mstat->rcv_pkt_lt_127bytes);
1597 	device_printf(dev, "%s: rcv_pkt_lt_255bytes\t\t%" PRIu64 "\n",
1598 		__func__, mstat->rcv_pkt_lt_255bytes);
1599 	device_printf(dev, "%s: rcv_pkt_lt_511bytes\t\t%" PRIu64 "\n",
1600 		__func__, mstat->rcv_pkt_lt_511bytes);
1601 	device_printf(dev, "%s: rcv_pkt_lt_1023bytes\t\t%" PRIu64 "\n",
1602 		__func__, mstat->rcv_pkt_lt_1023bytes);
1603 	device_printf(dev, "%s: rcv_pkt_lt_1518bytes\t\t%" PRIu64 "\n",
1604 		__func__, mstat->rcv_pkt_lt_1518bytes);
1605 	device_printf(dev, "%s: rcv_pkt_gt_1518bytes\t\t%" PRIu64 "\n",
1606 		__func__, mstat->rcv_pkt_gt_1518bytes);
1607 
1608 	device_printf(dev, "%s: rcv_len_error\t\t%" PRIu64 "\n", __func__,
1609 		mstat->rcv_len_error);
1610 	device_printf(dev, "%s: rcv_len_small\t\t%" PRIu64 "\n", __func__,
1611 		mstat->rcv_len_small);
1612 	device_printf(dev, "%s: rcv_len_large\t\t%" PRIu64 "\n", __func__,
1613 		mstat->rcv_len_large);
1614 	device_printf(dev, "%s: rcv_jabber\t\t\t%" PRIu64 "\n", __func__,
1615 		mstat->rcv_jabber);
1616 	device_printf(dev, "%s: rcv_dropped\t\t\t%" PRIu64 "\n", __func__,
1617 		mstat->rcv_dropped);
1618 	device_printf(dev, "%s: fcs_error\t\t\t%" PRIu64 "\n", __func__,
1619 		mstat->fcs_error);
1620 	device_printf(dev, "%s: align_error\t\t\t%" PRIu64 "\n", __func__,
1621 		mstat->align_error);
1622 }
1623 
1624 
1625 static int
1626 qla_get_hw_stats(qla_host_t *ha, uint32_t cmd, uint32_t rsp_size)
1627 {
1628 	device_t		dev;
1629 	q80_get_stats_t		*stat;
1630 	q80_get_stats_rsp_t	*stat_rsp;
1631 	uint32_t		err;
1632 
1633 	dev = ha->pci_dev;
1634 
1635 	stat = (q80_get_stats_t *)ha->hw.mbox;
1636 	bzero(stat, (sizeof (q80_get_stats_t)));
1637 
1638 	stat->opcode = Q8_MBX_GET_STATS;
1639 	stat->count_version = 2;
1640 	stat->count_version |= Q8_MBX_CMD_VERSION;
1641 
1642 	stat->cmd = cmd;
1643 
1644         if (qla_mbx_cmd(ha, (uint32_t *)stat, 2,
1645                 ha->hw.mbox, (rsp_size >> 2), 0)) {
1646                 device_printf(dev, "%s: failed\n", __func__);
1647                 return -1;
1648         }
1649 
1650 	stat_rsp = (q80_get_stats_rsp_t *)ha->hw.mbox;
1651 
1652         err = Q8_MBX_RSP_STATUS(stat_rsp->regcnt_status);
1653 
1654         if (err) {
1655                 return -1;
1656         }
1657 
1658 	return 0;
1659 }
1660 
1661 void
1662 ql_get_stats(qla_host_t *ha)
1663 {
1664 	q80_get_stats_rsp_t	*stat_rsp;
1665 	q80_mac_stats_t		*mstat;
1666 	q80_xmt_stats_t		*xstat;
1667 	q80_rcv_stats_t		*rstat;
1668 	uint32_t		cmd;
1669 	int			i;
1670 
1671 	stat_rsp = (q80_get_stats_rsp_t *)ha->hw.mbox;
1672 	/*
1673 	 * Get MAC Statistics
1674 	 */
1675 	cmd = Q8_GET_STATS_CMD_TYPE_MAC;
1676 //	cmd |= Q8_GET_STATS_CMD_CLEAR;
1677 
1678 	cmd |= ((ha->pci_func & 0x1) << 16);
1679 
1680 	if (qla_get_hw_stats(ha, cmd, sizeof (q80_get_stats_rsp_t)) == 0) {
1681 		mstat = (q80_mac_stats_t *)&stat_rsp->u.mac;
1682 		qla_mac_stats(ha, mstat);
1683 	} else {
1684                 device_printf(ha->pci_dev, "%s: mac failed [0x%08x]\n",
1685 			__func__, ha->hw.mbox[0]);
1686 	}
1687 	/*
1688 	 * Get RCV Statistics
1689 	 */
1690 	cmd = Q8_GET_STATS_CMD_RCV | Q8_GET_STATS_CMD_TYPE_CNTXT;
1691 //	cmd |= Q8_GET_STATS_CMD_CLEAR;
1692 	cmd |= (ha->hw.rcv_cntxt_id << 16);
1693 
1694 	if (qla_get_hw_stats(ha, cmd, sizeof (q80_get_stats_rsp_t)) == 0) {
1695 		rstat = (q80_rcv_stats_t *)&stat_rsp->u.rcv;
1696 		qla_rcv_stats(ha, rstat);
1697 	} else {
1698                 device_printf(ha->pci_dev, "%s: rcv failed [0x%08x]\n",
1699 			__func__, ha->hw.mbox[0]);
1700 	}
1701 	/*
1702 	 * Get XMT Statistics
1703 	 */
1704 	for (i = 0 ; i < ha->hw.num_tx_rings; i++) {
1705 		cmd = Q8_GET_STATS_CMD_XMT | Q8_GET_STATS_CMD_TYPE_CNTXT;
1706 //		cmd |= Q8_GET_STATS_CMD_CLEAR;
1707 		cmd |= (ha->hw.tx_cntxt[i].tx_cntxt_id << 16);
1708 
1709 		if (qla_get_hw_stats(ha, cmd, sizeof(q80_get_stats_rsp_t))
1710 			== 0) {
1711 			xstat = (q80_xmt_stats_t *)&stat_rsp->u.xmt;
1712 			qla_xmt_stats(ha, xstat, i);
1713 		} else {
1714 			device_printf(ha->pci_dev, "%s: xmt failed [0x%08x]\n",
1715 				__func__, ha->hw.mbox[0]);
1716 		}
1717 	}
1718 	return;
1719 }
1720 
1721 static void
1722 qla_get_quick_stats(qla_host_t *ha)
1723 {
1724 	q80_get_mac_rcv_xmt_stats_rsp_t *stat_rsp;
1725 	q80_mac_stats_t         *mstat;
1726 	q80_xmt_stats_t         *xstat;
1727 	q80_rcv_stats_t         *rstat;
1728 	uint32_t                cmd;
1729 
1730 	stat_rsp = (q80_get_mac_rcv_xmt_stats_rsp_t *)ha->hw.mbox;
1731 
1732 	cmd = Q8_GET_STATS_CMD_TYPE_ALL;
1733 //      cmd |= Q8_GET_STATS_CMD_CLEAR;
1734 
1735 //      cmd |= ((ha->pci_func & 0x3) << 16);
1736 	cmd |= (0xFFFF << 16);
1737 
1738 	if (qla_get_hw_stats(ha, cmd,
1739 			sizeof (q80_get_mac_rcv_xmt_stats_rsp_t)) == 0) {
1740 
1741 		mstat = (q80_mac_stats_t *)&stat_rsp->mac;
1742 		rstat = (q80_rcv_stats_t *)&stat_rsp->rcv;
1743 		xstat = (q80_xmt_stats_t *)&stat_rsp->xmt;
1744 		qla_mac_stats(ha, mstat);
1745 		qla_rcv_stats(ha, rstat);
1746 		qla_xmt_stats(ha, xstat, ha->hw.num_tx_rings);
1747 	} else {
1748 		device_printf(ha->pci_dev, "%s: failed [0x%08x]\n",
1749 			__func__, ha->hw.mbox[0]);
1750 	}
1751 	return;
1752 }
1753 
1754 /*
1755  * Name: qla_tx_tso
1756  * Function: Checks if the packet to be transmitted is a candidate for
1757  *	Large TCP Segment Offload. If yes, the appropriate fields in the Tx
1758  *	Ring Structure are plugged in.
1759  */
1760 static int
1761 qla_tx_tso(qla_host_t *ha, struct mbuf *mp, q80_tx_cmd_t *tx_cmd, uint8_t *hdr)
1762 {
1763 	struct ether_vlan_header *eh;
1764 	struct ip *ip = NULL;
1765 	struct ip6_hdr *ip6 = NULL;
1766 	struct tcphdr *th = NULL;
1767 	uint32_t ehdrlen,  hdrlen, ip_hlen, tcp_hlen, tcp_opt_off;
1768 	uint16_t etype, opcode, offload = 1;
1769 	device_t dev;
1770 
1771 	dev = ha->pci_dev;
1772 
1773 
1774 	eh = mtod(mp, struct ether_vlan_header *);
1775 
1776 	if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
1777 		ehdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
1778 		etype = ntohs(eh->evl_proto);
1779 	} else {
1780 		ehdrlen = ETHER_HDR_LEN;
1781 		etype = ntohs(eh->evl_encap_proto);
1782 	}
1783 
1784 	hdrlen = 0;
1785 
1786 	switch (etype) {
1787 		case ETHERTYPE_IP:
1788 
1789 			tcp_opt_off = ehdrlen + sizeof(struct ip) +
1790 					sizeof(struct tcphdr);
1791 
1792 			if (mp->m_len < tcp_opt_off) {
1793 				m_copydata(mp, 0, tcp_opt_off, hdr);
1794 				ip = (struct ip *)(hdr + ehdrlen);
1795 			} else {
1796 				ip = (struct ip *)(mp->m_data + ehdrlen);
1797 			}
1798 
1799 			ip_hlen = ip->ip_hl << 2;
1800 			opcode = Q8_TX_CMD_OP_XMT_TCP_LSO;
1801 
1802 
1803 			if ((ip->ip_p != IPPROTO_TCP) ||
1804 				(ip_hlen != sizeof (struct ip))){
1805 				/* IP Options are not supported */
1806 
1807 				offload = 0;
1808 			} else
1809 				th = (struct tcphdr *)((caddr_t)ip + ip_hlen);
1810 
1811 		break;
1812 
1813 		case ETHERTYPE_IPV6:
1814 
1815 			tcp_opt_off = ehdrlen + sizeof(struct ip6_hdr) +
1816 					sizeof (struct tcphdr);
1817 
1818 			if (mp->m_len < tcp_opt_off) {
1819 				m_copydata(mp, 0, tcp_opt_off, hdr);
1820 				ip6 = (struct ip6_hdr *)(hdr + ehdrlen);
1821 			} else {
1822 				ip6 = (struct ip6_hdr *)(mp->m_data + ehdrlen);
1823 			}
1824 
1825 			ip_hlen = sizeof(struct ip6_hdr);
1826 			opcode = Q8_TX_CMD_OP_XMT_TCP_LSO_IPV6;
1827 
1828 			if (ip6->ip6_nxt != IPPROTO_TCP) {
1829 				//device_printf(dev, "%s: ipv6\n", __func__);
1830 				offload = 0;
1831 			} else
1832 				th = (struct tcphdr *)((caddr_t)ip6 + ip_hlen);
1833 		break;
1834 
1835 		default:
1836 			QL_DPRINT8(ha, (dev, "%s: type!=ip\n", __func__));
1837 			offload = 0;
1838 		break;
1839 	}
1840 
1841 	if (!offload)
1842 		return (-1);
1843 
1844 	tcp_hlen = th->th_off << 2;
1845 	hdrlen = ehdrlen + ip_hlen + tcp_hlen;
1846 
1847         if (mp->m_len < hdrlen) {
1848                 if (mp->m_len < tcp_opt_off) {
1849                         if (tcp_hlen > sizeof(struct tcphdr)) {
1850                                 m_copydata(mp, tcp_opt_off,
1851                                         (tcp_hlen - sizeof(struct tcphdr)),
1852                                         &hdr[tcp_opt_off]);
1853                         }
1854                 } else {
1855                         m_copydata(mp, 0, hdrlen, hdr);
1856                 }
1857         }
1858 
1859 	tx_cmd->mss = mp->m_pkthdr.tso_segsz;
1860 
1861 	tx_cmd->flags_opcode = opcode ;
1862 	tx_cmd->tcp_hdr_off = ip_hlen + ehdrlen;
1863 	tx_cmd->total_hdr_len = hdrlen;
1864 
1865 	/* Check for Multicast least significant bit of MSB == 1 */
1866 	if (eh->evl_dhost[0] & 0x01) {
1867 		tx_cmd->flags_opcode |= Q8_TX_CMD_FLAGS_MULTICAST;
1868 	}
1869 
1870 	if (mp->m_len < hdrlen) {
1871 		printf("%d\n", hdrlen);
1872 		return (1);
1873 	}
1874 
1875 	return (0);
1876 }
1877 
1878 /*
1879  * Name: qla_tx_chksum
1880  * Function: Checks if the packet to be transmitted is a candidate for
1881  *	TCP/UDP Checksum offload. If yes, the appropriate fields in the Tx
1882  *	Ring Structure are plugged in.
1883  */
1884 static int
1885 qla_tx_chksum(qla_host_t *ha, struct mbuf *mp, uint32_t *op_code,
1886 	uint32_t *tcp_hdr_off)
1887 {
1888 	struct ether_vlan_header *eh;
1889 	struct ip *ip;
1890 	struct ip6_hdr *ip6;
1891 	uint32_t ehdrlen, ip_hlen;
1892 	uint16_t etype, opcode, offload = 1;
1893 	device_t dev;
1894 	uint8_t buf[sizeof(struct ip6_hdr)];
1895 
1896 	dev = ha->pci_dev;
1897 
1898 	*op_code = 0;
1899 
1900 	if ((mp->m_pkthdr.csum_flags & (CSUM_TCP|CSUM_UDP)) == 0)
1901 		return (-1);
1902 
1903 	eh = mtod(mp, struct ether_vlan_header *);
1904 
1905 	if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
1906 		ehdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
1907 		etype = ntohs(eh->evl_proto);
1908 	} else {
1909 		ehdrlen = ETHER_HDR_LEN;
1910 		etype = ntohs(eh->evl_encap_proto);
1911 	}
1912 
1913 
1914 	switch (etype) {
1915 		case ETHERTYPE_IP:
1916 			ip = (struct ip *)(mp->m_data + ehdrlen);
1917 
1918 			ip_hlen = sizeof (struct ip);
1919 
1920 			if (mp->m_len < (ehdrlen + ip_hlen)) {
1921 				m_copydata(mp, ehdrlen, sizeof(struct ip), buf);
1922 				ip = (struct ip *)buf;
1923 			}
1924 
1925 			if (ip->ip_p == IPPROTO_TCP)
1926 				opcode = Q8_TX_CMD_OP_XMT_TCP_CHKSUM;
1927 			else if (ip->ip_p == IPPROTO_UDP)
1928 				opcode = Q8_TX_CMD_OP_XMT_UDP_CHKSUM;
1929 			else {
1930 				//device_printf(dev, "%s: ipv4\n", __func__);
1931 				offload = 0;
1932 			}
1933 		break;
1934 
1935 		case ETHERTYPE_IPV6:
1936 			ip6 = (struct ip6_hdr *)(mp->m_data + ehdrlen);
1937 
1938 			ip_hlen = sizeof(struct ip6_hdr);
1939 
1940 			if (mp->m_len < (ehdrlen + ip_hlen)) {
1941 				m_copydata(mp, ehdrlen, sizeof (struct ip6_hdr),
1942 					buf);
1943 				ip6 = (struct ip6_hdr *)buf;
1944 			}
1945 
1946 			if (ip6->ip6_nxt == IPPROTO_TCP)
1947 				opcode = Q8_TX_CMD_OP_XMT_TCP_CHKSUM_IPV6;
1948 			else if (ip6->ip6_nxt == IPPROTO_UDP)
1949 				opcode = Q8_TX_CMD_OP_XMT_UDP_CHKSUM_IPV6;
1950 			else {
1951 				//device_printf(dev, "%s: ipv6\n", __func__);
1952 				offload = 0;
1953 			}
1954 		break;
1955 
1956 		default:
1957 			offload = 0;
1958 		break;
1959 	}
1960 	if (!offload)
1961 		return (-1);
1962 
1963 	*op_code = opcode;
1964 	*tcp_hdr_off = (ip_hlen + ehdrlen);
1965 
1966 	return (0);
1967 }
1968 
1969 #define QLA_TX_MIN_FREE 2
1970 /*
1971  * Name: ql_hw_send
1972  * Function: Transmits a packet. It first checks if the packet is a
1973  *	candidate for Large TCP Segment Offload and then for UDP/TCP checksum
1974  *	offload. If either of these creteria are not met, it is transmitted
1975  *	as a regular ethernet frame.
1976  */
1977 int
1978 ql_hw_send(qla_host_t *ha, bus_dma_segment_t *segs, int nsegs,
1979 	uint32_t tx_idx, struct mbuf *mp, uint32_t txr_idx, uint32_t iscsi_pdu)
1980 {
1981 	struct ether_vlan_header *eh;
1982 	qla_hw_t *hw = &ha->hw;
1983 	q80_tx_cmd_t *tx_cmd, tso_cmd;
1984 	bus_dma_segment_t *c_seg;
1985 	uint32_t num_tx_cmds, hdr_len = 0;
1986 	uint32_t total_length = 0, bytes, tx_cmd_count = 0, txr_next;
1987 	device_t dev;
1988 	int i, ret;
1989 	uint8_t *src = NULL, *dst = NULL;
1990 	uint8_t frame_hdr[QL_FRAME_HDR_SIZE];
1991 	uint32_t op_code = 0;
1992 	uint32_t tcp_hdr_off = 0;
1993 
1994 	dev = ha->pci_dev;
1995 
1996 	/*
1997 	 * Always make sure there is atleast one empty slot in the tx_ring
1998 	 * tx_ring is considered full when there only one entry available
1999 	 */
2000         num_tx_cmds = (nsegs + (Q8_TX_CMD_MAX_SEGMENTS - 1)) >> 2;
2001 
2002 	total_length = mp->m_pkthdr.len;
2003 	if (total_length > QLA_MAX_TSO_FRAME_SIZE) {
2004 		device_printf(dev, "%s: total length exceeds maxlen(%d)\n",
2005 			__func__, total_length);
2006 		return (-1);
2007 	}
2008 	eh = mtod(mp, struct ether_vlan_header *);
2009 
2010 	if (mp->m_pkthdr.csum_flags & CSUM_TSO) {
2011 
2012 		bzero((void *)&tso_cmd, sizeof(q80_tx_cmd_t));
2013 
2014 		src = frame_hdr;
2015 		ret = qla_tx_tso(ha, mp, &tso_cmd, src);
2016 
2017 		if (!(ret & ~1)) {
2018 			/* find the additional tx_cmd descriptors required */
2019 
2020 			if (mp->m_flags & M_VLANTAG)
2021 				tso_cmd.total_hdr_len += ETHER_VLAN_ENCAP_LEN;
2022 
2023 			hdr_len = tso_cmd.total_hdr_len;
2024 
2025 			bytes = sizeof(q80_tx_cmd_t) - Q8_TX_CMD_TSO_ALIGN;
2026 			bytes = QL_MIN(bytes, hdr_len);
2027 
2028 			num_tx_cmds++;
2029 			hdr_len -= bytes;
2030 
2031 			while (hdr_len) {
2032 				bytes = QL_MIN((sizeof(q80_tx_cmd_t)), hdr_len);
2033 				hdr_len -= bytes;
2034 				num_tx_cmds++;
2035 			}
2036 			hdr_len = tso_cmd.total_hdr_len;
2037 
2038 			if (ret == 0)
2039 				src = (uint8_t *)eh;
2040 		} else
2041 			return (EINVAL);
2042 	} else {
2043 		(void)qla_tx_chksum(ha, mp, &op_code, &tcp_hdr_off);
2044 	}
2045 
2046 	if (iscsi_pdu)
2047 		ha->hw.iscsi_pkt_count++;
2048 
2049 	if (hw->tx_cntxt[txr_idx].txr_free <= (num_tx_cmds + QLA_TX_MIN_FREE)) {
2050 		qla_hw_tx_done_locked(ha, txr_idx);
2051 		if (hw->tx_cntxt[txr_idx].txr_free <=
2052 				(num_tx_cmds + QLA_TX_MIN_FREE)) {
2053         		QL_DPRINT8(ha, (dev, "%s: (hw->txr_free <= "
2054 				"(num_tx_cmds + QLA_TX_MIN_FREE))\n",
2055 				__func__));
2056 			return (-1);
2057 		}
2058 	}
2059 
2060 	tx_cmd = &hw->tx_cntxt[txr_idx].tx_ring_base[tx_idx];
2061 
2062         if (!(mp->m_pkthdr.csum_flags & CSUM_TSO)) {
2063 
2064                 if (nsegs > ha->hw.max_tx_segs)
2065                         ha->hw.max_tx_segs = nsegs;
2066 
2067                 bzero((void *)tx_cmd, sizeof(q80_tx_cmd_t));
2068 
2069                 if (op_code) {
2070                         tx_cmd->flags_opcode = op_code;
2071                         tx_cmd->tcp_hdr_off = tcp_hdr_off;
2072 
2073                 } else {
2074                         tx_cmd->flags_opcode = Q8_TX_CMD_OP_XMT_ETHER;
2075                 }
2076 	} else {
2077 		bcopy(&tso_cmd, tx_cmd, sizeof(q80_tx_cmd_t));
2078 		ha->tx_tso_frames++;
2079 	}
2080 
2081 	if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
2082         	tx_cmd->flags_opcode |= Q8_TX_CMD_FLAGS_VLAN_TAGGED;
2083 
2084 		if (iscsi_pdu)
2085 			eh->evl_tag |= ha->hw.user_pri_iscsi << 13;
2086 
2087 	} else if (mp->m_flags & M_VLANTAG) {
2088 
2089 		if (hdr_len) { /* TSO */
2090 			tx_cmd->flags_opcode |= (Q8_TX_CMD_FLAGS_VLAN_TAGGED |
2091 						Q8_TX_CMD_FLAGS_HW_VLAN_ID);
2092 			tx_cmd->tcp_hdr_off += ETHER_VLAN_ENCAP_LEN;
2093 		} else
2094 			tx_cmd->flags_opcode |= Q8_TX_CMD_FLAGS_HW_VLAN_ID;
2095 
2096 		ha->hw_vlan_tx_frames++;
2097 		tx_cmd->vlan_tci = mp->m_pkthdr.ether_vtag;
2098 
2099 		if (iscsi_pdu) {
2100 			tx_cmd->vlan_tci |= ha->hw.user_pri_iscsi << 13;
2101 			mp->m_pkthdr.ether_vtag = tx_cmd->vlan_tci;
2102 		}
2103 	}
2104 
2105 
2106         tx_cmd->n_bufs = (uint8_t)nsegs;
2107         tx_cmd->data_len_lo = (uint8_t)(total_length & 0xFF);
2108         tx_cmd->data_len_hi = qla_host_to_le16(((uint16_t)(total_length >> 8)));
2109 	tx_cmd->cntxtid = Q8_TX_CMD_PORT_CNXTID(ha->pci_func);
2110 
2111 	c_seg = segs;
2112 
2113 	while (1) {
2114 		for (i = 0; ((i < Q8_TX_CMD_MAX_SEGMENTS) && nsegs); i++) {
2115 
2116 			switch (i) {
2117 			case 0:
2118 				tx_cmd->buf1_addr = c_seg->ds_addr;
2119 				tx_cmd->buf1_len = c_seg->ds_len;
2120 				break;
2121 
2122 			case 1:
2123 				tx_cmd->buf2_addr = c_seg->ds_addr;
2124 				tx_cmd->buf2_len = c_seg->ds_len;
2125 				break;
2126 
2127 			case 2:
2128 				tx_cmd->buf3_addr = c_seg->ds_addr;
2129 				tx_cmd->buf3_len = c_seg->ds_len;
2130 				break;
2131 
2132 			case 3:
2133 				tx_cmd->buf4_addr = c_seg->ds_addr;
2134 				tx_cmd->buf4_len = c_seg->ds_len;
2135 				break;
2136 			}
2137 
2138 			c_seg++;
2139 			nsegs--;
2140 		}
2141 
2142 		txr_next = hw->tx_cntxt[txr_idx].txr_next =
2143 			(hw->tx_cntxt[txr_idx].txr_next + 1) &
2144 				(NUM_TX_DESCRIPTORS - 1);
2145 		tx_cmd_count++;
2146 
2147 		if (!nsegs)
2148 			break;
2149 
2150 		tx_cmd = &hw->tx_cntxt[txr_idx].tx_ring_base[txr_next];
2151 		bzero((void *)tx_cmd, sizeof(q80_tx_cmd_t));
2152 	}
2153 
2154 	if (mp->m_pkthdr.csum_flags & CSUM_TSO) {
2155 
2156 		/* TSO : Copy the header in the following tx cmd descriptors */
2157 
2158 		txr_next = hw->tx_cntxt[txr_idx].txr_next;
2159 
2160 		tx_cmd = &hw->tx_cntxt[txr_idx].tx_ring_base[txr_next];
2161 		bzero((void *)tx_cmd, sizeof(q80_tx_cmd_t));
2162 
2163 		bytes = sizeof(q80_tx_cmd_t) - Q8_TX_CMD_TSO_ALIGN;
2164 		bytes = QL_MIN(bytes, hdr_len);
2165 
2166 		dst = (uint8_t *)tx_cmd + Q8_TX_CMD_TSO_ALIGN;
2167 
2168 		if (mp->m_flags & M_VLANTAG) {
2169 			/* first copy the src/dst MAC addresses */
2170 			bcopy(src, dst, (ETHER_ADDR_LEN * 2));
2171 			dst += (ETHER_ADDR_LEN * 2);
2172 			src += (ETHER_ADDR_LEN * 2);
2173 
2174 			*((uint16_t *)dst) = htons(ETHERTYPE_VLAN);
2175 			dst += 2;
2176 			*((uint16_t *)dst) = htons(mp->m_pkthdr.ether_vtag);
2177 			dst += 2;
2178 
2179 			/* bytes left in src header */
2180 			hdr_len -= ((ETHER_ADDR_LEN * 2) +
2181 					ETHER_VLAN_ENCAP_LEN);
2182 
2183 			/* bytes left in TxCmd Entry */
2184 			bytes -= ((ETHER_ADDR_LEN * 2) + ETHER_VLAN_ENCAP_LEN);
2185 
2186 
2187 			bcopy(src, dst, bytes);
2188 			src += bytes;
2189 			hdr_len -= bytes;
2190 		} else {
2191 			bcopy(src, dst, bytes);
2192 			src += bytes;
2193 			hdr_len -= bytes;
2194 		}
2195 
2196 		txr_next = hw->tx_cntxt[txr_idx].txr_next =
2197 				(hw->tx_cntxt[txr_idx].txr_next + 1) &
2198 					(NUM_TX_DESCRIPTORS - 1);
2199 		tx_cmd_count++;
2200 
2201 		while (hdr_len) {
2202 			tx_cmd = &hw->tx_cntxt[txr_idx].tx_ring_base[txr_next];
2203 			bzero((void *)tx_cmd, sizeof(q80_tx_cmd_t));
2204 
2205 			bytes = QL_MIN((sizeof(q80_tx_cmd_t)), hdr_len);
2206 
2207 			bcopy(src, tx_cmd, bytes);
2208 			src += bytes;
2209 			hdr_len -= bytes;
2210 
2211 			txr_next = hw->tx_cntxt[txr_idx].txr_next =
2212 				(hw->tx_cntxt[txr_idx].txr_next + 1) &
2213 					(NUM_TX_DESCRIPTORS - 1);
2214 			tx_cmd_count++;
2215 		}
2216 	}
2217 
2218 	hw->tx_cntxt[txr_idx].txr_free =
2219 		hw->tx_cntxt[txr_idx].txr_free - tx_cmd_count;
2220 
2221 	QL_UPDATE_TX_PRODUCER_INDEX(ha, hw->tx_cntxt[txr_idx].txr_next,\
2222 		txr_idx);
2223        	QL_DPRINT8(ha, (dev, "%s: return\n", __func__));
2224 
2225 	return (0);
2226 }
2227 
2228 
2229 
2230 #define Q8_CONFIG_IND_TBL_SIZE	32 /* < Q8_RSS_IND_TBL_SIZE and power of 2 */
2231 static int
2232 qla_config_rss_ind_table(qla_host_t *ha)
2233 {
2234 	uint32_t i, count;
2235 	uint8_t rss_ind_tbl[Q8_CONFIG_IND_TBL_SIZE];
2236 
2237 
2238 	for (i = 0; i < Q8_CONFIG_IND_TBL_SIZE; i++) {
2239 		rss_ind_tbl[i] = i % ha->hw.num_sds_rings;
2240 	}
2241 
2242 	for (i = 0; i <= Q8_RSS_IND_TBL_MAX_IDX ;
2243 		i = i + Q8_CONFIG_IND_TBL_SIZE) {
2244 
2245 		if ((i + Q8_CONFIG_IND_TBL_SIZE) > Q8_RSS_IND_TBL_MAX_IDX) {
2246 			count = Q8_RSS_IND_TBL_MAX_IDX - i + 1;
2247 		} else {
2248 			count = Q8_CONFIG_IND_TBL_SIZE;
2249 		}
2250 
2251 		if (qla_set_rss_ind_table(ha, i, count, ha->hw.rcv_cntxt_id,
2252 			rss_ind_tbl))
2253 			return (-1);
2254 	}
2255 
2256 	return (0);
2257 }
2258 
2259 /*
2260  * Name: ql_del_hw_if
2261  * Function: Destroys the hardware specific entities corresponding to an
2262  *	Ethernet Interface
2263  */
2264 void
2265 ql_del_hw_if(qla_host_t *ha)
2266 {
2267 	uint32_t i;
2268 	uint32_t num_msix;
2269 
2270 	(void)qla_stop_nic_func(ha);
2271 
2272 	qla_del_rcv_cntxt(ha);
2273 
2274 	qla_del_xmt_cntxt(ha);
2275 
2276 	if (ha->hw.flags.init_intr_cnxt) {
2277 		for (i = 0; i < ha->hw.num_sds_rings; ) {
2278 
2279 			if ((i + Q8_MAX_INTR_VECTORS) < ha->hw.num_sds_rings)
2280 				num_msix = Q8_MAX_INTR_VECTORS;
2281 			else
2282 				num_msix = ha->hw.num_sds_rings - i;
2283 			qla_config_intr_cntxt(ha, i, num_msix, 0);
2284 
2285 			i += num_msix;
2286 		}
2287 
2288 		ha->hw.flags.init_intr_cnxt = 0;
2289 	}
2290 
2291 	return;
2292 }
2293 
2294 void
2295 qla_confirm_9kb_enable(qla_host_t *ha)
2296 {
2297 	uint32_t supports_9kb = 0;
2298 
2299 	ha->hw.mbx_intr_mask_offset = READ_REG32(ha, Q8_MBOX_INT_MASK_MSIX);
2300 
2301 	/* Use MSI-X vector 0; Enable Firmware Mailbox Interrupt */
2302 	WRITE_REG32(ha, Q8_MBOX_INT_ENABLE, BIT_2);
2303 	WRITE_REG32(ha, ha->hw.mbx_intr_mask_offset, 0x0);
2304 
2305 	qla_get_nic_partition(ha, &supports_9kb, NULL);
2306 
2307 	if (!supports_9kb)
2308 		ha->hw.enable_9kb = 0;
2309 
2310 	return;
2311 }
2312 
2313 
2314 /*
2315  * Name: ql_init_hw_if
2316  * Function: Creates the hardware specific entities corresponding to an
2317  *	Ethernet Interface - Transmit and Receive Contexts. Sets the MAC Address
2318  *	corresponding to the interface. Enables LRO if allowed.
2319  */
2320 int
2321 ql_init_hw_if(qla_host_t *ha)
2322 {
2323 	device_t	dev;
2324 	uint32_t	i;
2325 	uint8_t		bcast_mac[6];
2326 	qla_rdesc_t	*rdesc;
2327 	uint32_t	num_msix;
2328 
2329 	dev = ha->pci_dev;
2330 
2331 	for (i = 0; i < ha->hw.num_sds_rings; i++) {
2332 		bzero(ha->hw.dma_buf.sds_ring[i].dma_b,
2333 			ha->hw.dma_buf.sds_ring[i].size);
2334 	}
2335 
2336 	for (i = 0; i < ha->hw.num_sds_rings; ) {
2337 
2338 		if ((i + Q8_MAX_INTR_VECTORS) < ha->hw.num_sds_rings)
2339 			num_msix = Q8_MAX_INTR_VECTORS;
2340 		else
2341 			num_msix = ha->hw.num_sds_rings - i;
2342 
2343 		if (qla_config_intr_cntxt(ha, i, num_msix, 1)) {
2344 
2345 			if (i > 0) {
2346 
2347 				num_msix = i;
2348 
2349 				for (i = 0; i < num_msix; ) {
2350 					qla_config_intr_cntxt(ha, i,
2351 						Q8_MAX_INTR_VECTORS, 0);
2352 					i += Q8_MAX_INTR_VECTORS;
2353 				}
2354 			}
2355 			return (-1);
2356 		}
2357 
2358 		i = i + num_msix;
2359 	}
2360 
2361         ha->hw.flags.init_intr_cnxt = 1;
2362 
2363 	/*
2364 	 * Create Receive Context
2365 	 */
2366 	if (qla_init_rcv_cntxt(ha)) {
2367 		return (-1);
2368 	}
2369 
2370 	for (i = 0; i < ha->hw.num_rds_rings; i++) {
2371 		rdesc = &ha->hw.rds[i];
2372 		rdesc->rx_next = NUM_RX_DESCRIPTORS - 2;
2373 		rdesc->rx_in = 0;
2374 		/* Update the RDS Producer Indices */
2375 		QL_UPDATE_RDS_PRODUCER_INDEX(ha, rdesc->prod_std,\
2376 			rdesc->rx_next);
2377 	}
2378 
2379 
2380 	/*
2381 	 * Create Transmit Context
2382 	 */
2383 	if (qla_init_xmt_cntxt(ha)) {
2384 		qla_del_rcv_cntxt(ha);
2385 		return (-1);
2386 	}
2387 	ha->hw.max_tx_segs = 0;
2388 
2389 	if (qla_config_mac_addr(ha, ha->hw.mac_addr, 1, 1))
2390 		return(-1);
2391 
2392 	ha->hw.flags.unicast_mac = 1;
2393 
2394 	bcast_mac[0] = 0xFF; bcast_mac[1] = 0xFF; bcast_mac[2] = 0xFF;
2395 	bcast_mac[3] = 0xFF; bcast_mac[4] = 0xFF; bcast_mac[5] = 0xFF;
2396 
2397 	if (qla_config_mac_addr(ha, bcast_mac, 1, 1))
2398 		return (-1);
2399 
2400 	ha->hw.flags.bcast_mac = 1;
2401 
2402 	/*
2403 	 * program any cached multicast addresses
2404 	 */
2405 	if (qla_hw_add_all_mcast(ha))
2406 		return (-1);
2407 
2408 	if (qla_config_rss(ha, ha->hw.rcv_cntxt_id))
2409 		return (-1);
2410 
2411 	if (qla_config_rss_ind_table(ha))
2412 		return (-1);
2413 
2414 	if (qla_config_intr_coalesce(ha, ha->hw.rcv_cntxt_id, 0, 1))
2415 		return (-1);
2416 
2417 	if (qla_link_event_req(ha, ha->hw.rcv_cntxt_id))
2418 		return (-1);
2419 
2420 	if (qla_config_fw_lro(ha, ha->hw.rcv_cntxt_id))
2421 		return (-1);
2422 
2423         if (qla_init_nic_func(ha))
2424                 return (-1);
2425 
2426         if (qla_query_fw_dcbx_caps(ha))
2427                 return (-1);
2428 
2429 	for (i = 0; i < ha->hw.num_sds_rings; i++)
2430 		QL_ENABLE_INTERRUPTS(ha, i);
2431 
2432 	return (0);
2433 }
2434 
2435 static int
2436 qla_map_sds_to_rds(qla_host_t *ha, uint32_t start_idx, uint32_t num_idx)
2437 {
2438         device_t                dev = ha->pci_dev;
2439         q80_rq_map_sds_to_rds_t *map_rings;
2440 	q80_rsp_map_sds_to_rds_t *map_rings_rsp;
2441         uint32_t                i, err;
2442         qla_hw_t                *hw = &ha->hw;
2443 
2444         map_rings = (q80_rq_map_sds_to_rds_t *)ha->hw.mbox;
2445         bzero(map_rings, sizeof(q80_rq_map_sds_to_rds_t));
2446 
2447         map_rings->opcode = Q8_MBX_MAP_SDS_TO_RDS;
2448         map_rings->count_version = (sizeof (q80_rq_map_sds_to_rds_t) >> 2);
2449         map_rings->count_version |= Q8_MBX_CMD_VERSION;
2450 
2451         map_rings->cntxt_id = hw->rcv_cntxt_id;
2452         map_rings->num_rings = num_idx;
2453 
2454 	for (i = 0; i < num_idx; i++) {
2455 		map_rings->sds_rds[i].sds_ring = i + start_idx;
2456 		map_rings->sds_rds[i].rds_ring = i + start_idx;
2457 	}
2458 
2459         if (qla_mbx_cmd(ha, (uint32_t *)map_rings,
2460                 (sizeof (q80_rq_map_sds_to_rds_t) >> 2),
2461                 ha->hw.mbox, (sizeof(q80_rsp_add_rcv_rings_t) >> 2), 0)) {
2462                 device_printf(dev, "%s: failed0\n", __func__);
2463                 return (-1);
2464         }
2465 
2466         map_rings_rsp = (q80_rsp_map_sds_to_rds_t *)ha->hw.mbox;
2467 
2468         err = Q8_MBX_RSP_STATUS(map_rings_rsp->regcnt_status);
2469 
2470         if (err) {
2471                 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
2472                 return (-1);
2473         }
2474 
2475         return (0);
2476 }
2477 
2478 /*
2479  * Name: qla_init_rcv_cntxt
2480  * Function: Creates the Receive Context.
2481  */
2482 static int
2483 qla_init_rcv_cntxt(qla_host_t *ha)
2484 {
2485 	q80_rq_rcv_cntxt_t	*rcntxt;
2486 	q80_rsp_rcv_cntxt_t	*rcntxt_rsp;
2487 	q80_stat_desc_t		*sdesc;
2488 	int			i, j;
2489         qla_hw_t		*hw = &ha->hw;
2490 	device_t		dev;
2491 	uint32_t		err;
2492 	uint32_t		rcntxt_sds_rings;
2493 	uint32_t		rcntxt_rds_rings;
2494 	uint32_t		max_idx;
2495 
2496 	dev = ha->pci_dev;
2497 
2498 	/*
2499 	 * Create Receive Context
2500 	 */
2501 
2502 	for (i = 0; i < hw->num_sds_rings; i++) {
2503 		sdesc = (q80_stat_desc_t *)&hw->sds[i].sds_ring_base[0];
2504 
2505 		for (j = 0; j < NUM_STATUS_DESCRIPTORS; j++) {
2506 			sdesc->data[0] = 1ULL;
2507 			sdesc->data[1] = 1ULL;
2508 		}
2509 	}
2510 
2511 	rcntxt_sds_rings = hw->num_sds_rings;
2512 	if (hw->num_sds_rings > MAX_RCNTXT_SDS_RINGS)
2513 		rcntxt_sds_rings = MAX_RCNTXT_SDS_RINGS;
2514 
2515 	rcntxt_rds_rings = hw->num_rds_rings;
2516 
2517 	if (hw->num_rds_rings > MAX_RDS_RING_SETS)
2518 		rcntxt_rds_rings = MAX_RDS_RING_SETS;
2519 
2520 	rcntxt = (q80_rq_rcv_cntxt_t *)ha->hw.mbox;
2521 	bzero(rcntxt, (sizeof (q80_rq_rcv_cntxt_t)));
2522 
2523 	rcntxt->opcode = Q8_MBX_CREATE_RX_CNTXT;
2524 	rcntxt->count_version = (sizeof (q80_rq_rcv_cntxt_t) >> 2);
2525 	rcntxt->count_version |= Q8_MBX_CMD_VERSION;
2526 
2527 	rcntxt->cap0 = Q8_RCV_CNTXT_CAP0_BASEFW |
2528 			Q8_RCV_CNTXT_CAP0_LRO |
2529 			Q8_RCV_CNTXT_CAP0_HW_LRO |
2530 			Q8_RCV_CNTXT_CAP0_RSS |
2531 			Q8_RCV_CNTXT_CAP0_SGL_LRO;
2532 
2533 	if (ha->hw.enable_9kb)
2534 		rcntxt->cap0 |= Q8_RCV_CNTXT_CAP0_SINGLE_JUMBO;
2535 	else
2536 		rcntxt->cap0 |= Q8_RCV_CNTXT_CAP0_SGL_JUMBO;
2537 
2538 	if (ha->hw.num_rds_rings > 1) {
2539 		rcntxt->nrds_sets_rings = rcntxt_rds_rings | (1 << 5);
2540 		rcntxt->cap0 |= Q8_RCV_CNTXT_CAP0_MULTI_RDS;
2541 	} else
2542 		rcntxt->nrds_sets_rings = 0x1 | (1 << 5);
2543 
2544 	rcntxt->nsds_rings = rcntxt_sds_rings;
2545 
2546 	rcntxt->rds_producer_mode = Q8_RCV_CNTXT_RDS_PROD_MODE_UNIQUE;
2547 
2548 	rcntxt->rcv_vpid = 0;
2549 
2550 	for (i = 0; i <  rcntxt_sds_rings; i++) {
2551 		rcntxt->sds[i].paddr =
2552 			qla_host_to_le64(hw->dma_buf.sds_ring[i].dma_addr);
2553 		rcntxt->sds[i].size =
2554 			qla_host_to_le32(NUM_STATUS_DESCRIPTORS);
2555 		if (ha->msix_count == 2) {
2556 			rcntxt->sds[i].intr_id =
2557 				qla_host_to_le16(hw->intr_id[0]);
2558 			rcntxt->sds[i].intr_src_bit = qla_host_to_le16((i));
2559 		} else {
2560 			rcntxt->sds[i].intr_id =
2561 				qla_host_to_le16(hw->intr_id[i]);
2562 			rcntxt->sds[i].intr_src_bit = qla_host_to_le16(0);
2563 		}
2564 	}
2565 
2566 	for (i = 0; i <  rcntxt_rds_rings; i++) {
2567 		rcntxt->rds[i].paddr_std =
2568 			qla_host_to_le64(hw->dma_buf.rds_ring[i].dma_addr);
2569 
2570 		if (ha->hw.enable_9kb)
2571 			rcntxt->rds[i].std_bsize =
2572 				qla_host_to_le64(MJUM9BYTES);
2573 		else
2574 			rcntxt->rds[i].std_bsize = qla_host_to_le64(MCLBYTES);
2575 
2576 		rcntxt->rds[i].std_nentries =
2577 			qla_host_to_le32(NUM_RX_DESCRIPTORS);
2578 	}
2579 
2580         if (qla_mbx_cmd(ha, (uint32_t *)rcntxt,
2581 		(sizeof (q80_rq_rcv_cntxt_t) >> 2),
2582                 ha->hw.mbox, (sizeof(q80_rsp_rcv_cntxt_t) >> 2), 0)) {
2583                 device_printf(dev, "%s: failed0\n", __func__);
2584                 return (-1);
2585         }
2586 
2587         rcntxt_rsp = (q80_rsp_rcv_cntxt_t *)ha->hw.mbox;
2588 
2589         err = Q8_MBX_RSP_STATUS(rcntxt_rsp->regcnt_status);
2590 
2591         if (err) {
2592                 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
2593                 return (-1);
2594         }
2595 
2596 	for (i = 0; i <  rcntxt_sds_rings; i++) {
2597 		hw->sds[i].sds_consumer = rcntxt_rsp->sds_cons[i];
2598 	}
2599 
2600 	for (i = 0; i <  rcntxt_rds_rings; i++) {
2601 		hw->rds[i].prod_std = rcntxt_rsp->rds[i].prod_std;
2602 	}
2603 
2604 	hw->rcv_cntxt_id = rcntxt_rsp->cntxt_id;
2605 
2606 	ha->hw.flags.init_rx_cnxt = 1;
2607 
2608 	if (hw->num_sds_rings > MAX_RCNTXT_SDS_RINGS) {
2609 
2610 		for (i = MAX_RCNTXT_SDS_RINGS; i < hw->num_sds_rings;) {
2611 
2612 			if ((i + MAX_RCNTXT_SDS_RINGS) < hw->num_sds_rings)
2613 				max_idx = MAX_RCNTXT_SDS_RINGS;
2614 			else
2615 				max_idx = hw->num_sds_rings - i;
2616 
2617 			err = qla_add_rcv_rings(ha, i, max_idx);
2618 			if (err)
2619 				return -1;
2620 
2621 			i += max_idx;
2622 		}
2623 	}
2624 
2625 	if (hw->num_rds_rings > 1) {
2626 
2627 		for (i = 0; i < hw->num_rds_rings; ) {
2628 
2629 			if ((i + MAX_SDS_TO_RDS_MAP) < hw->num_rds_rings)
2630 				max_idx = MAX_SDS_TO_RDS_MAP;
2631 			else
2632 				max_idx = hw->num_rds_rings - i;
2633 
2634 			err = qla_map_sds_to_rds(ha, i, max_idx);
2635 			if (err)
2636 				return -1;
2637 
2638 			i += max_idx;
2639 		}
2640 	}
2641 
2642 	return (0);
2643 }
2644 
2645 static int
2646 qla_add_rcv_rings(qla_host_t *ha, uint32_t sds_idx, uint32_t nsds)
2647 {
2648 	device_t		dev = ha->pci_dev;
2649 	q80_rq_add_rcv_rings_t	*add_rcv;
2650 	q80_rsp_add_rcv_rings_t	*add_rcv_rsp;
2651 	uint32_t		i,j, err;
2652         qla_hw_t		*hw = &ha->hw;
2653 
2654 	add_rcv = (q80_rq_add_rcv_rings_t *)ha->hw.mbox;
2655 	bzero(add_rcv, sizeof (q80_rq_add_rcv_rings_t));
2656 
2657 	add_rcv->opcode = Q8_MBX_ADD_RX_RINGS;
2658 	add_rcv->count_version = (sizeof (q80_rq_add_rcv_rings_t) >> 2);
2659 	add_rcv->count_version |= Q8_MBX_CMD_VERSION;
2660 
2661 	add_rcv->nrds_sets_rings = nsds | (1 << 5);
2662 	add_rcv->nsds_rings = nsds;
2663 	add_rcv->cntxt_id = hw->rcv_cntxt_id;
2664 
2665         for (i = 0; i <  nsds; i++) {
2666 
2667 		j = i + sds_idx;
2668 
2669                 add_rcv->sds[i].paddr =
2670                         qla_host_to_le64(hw->dma_buf.sds_ring[j].dma_addr);
2671 
2672                 add_rcv->sds[i].size =
2673                         qla_host_to_le32(NUM_STATUS_DESCRIPTORS);
2674 
2675                 if (ha->msix_count == 2) {
2676                         add_rcv->sds[i].intr_id =
2677                                 qla_host_to_le16(hw->intr_id[0]);
2678                         add_rcv->sds[i].intr_src_bit = qla_host_to_le16(j);
2679                 } else {
2680                         add_rcv->sds[i].intr_id =
2681                                 qla_host_to_le16(hw->intr_id[j]);
2682                         add_rcv->sds[i].intr_src_bit = qla_host_to_le16(0);
2683                 }
2684 
2685         }
2686         for (i = 0; (i <  nsds); i++) {
2687                 j = i + sds_idx;
2688 
2689                 add_rcv->rds[i].paddr_std =
2690                         qla_host_to_le64(hw->dma_buf.rds_ring[j].dma_addr);
2691 
2692 		if (ha->hw.enable_9kb)
2693 			add_rcv->rds[i].std_bsize =
2694 				qla_host_to_le64(MJUM9BYTES);
2695 		else
2696                 	add_rcv->rds[i].std_bsize = qla_host_to_le64(MCLBYTES);
2697 
2698                 add_rcv->rds[i].std_nentries =
2699                         qla_host_to_le32(NUM_RX_DESCRIPTORS);
2700         }
2701 
2702 
2703         if (qla_mbx_cmd(ha, (uint32_t *)add_rcv,
2704 		(sizeof (q80_rq_add_rcv_rings_t) >> 2),
2705                 ha->hw.mbox, (sizeof(q80_rsp_add_rcv_rings_t) >> 2), 0)) {
2706                 device_printf(dev, "%s: failed0\n", __func__);
2707                 return (-1);
2708         }
2709 
2710         add_rcv_rsp = (q80_rsp_add_rcv_rings_t *)ha->hw.mbox;
2711 
2712         err = Q8_MBX_RSP_STATUS(add_rcv_rsp->regcnt_status);
2713 
2714         if (err) {
2715                 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
2716                 return (-1);
2717         }
2718 
2719 	for (i = 0; i < nsds; i++) {
2720 		hw->sds[(i + sds_idx)].sds_consumer = add_rcv_rsp->sds_cons[i];
2721 	}
2722 
2723 	for (i = 0; i < nsds; i++) {
2724 		hw->rds[(i + sds_idx)].prod_std = add_rcv_rsp->rds[i].prod_std;
2725 	}
2726 
2727 	return (0);
2728 }
2729 
2730 /*
2731  * Name: qla_del_rcv_cntxt
2732  * Function: Destroys the Receive Context.
2733  */
2734 static void
2735 qla_del_rcv_cntxt(qla_host_t *ha)
2736 {
2737 	device_t			dev = ha->pci_dev;
2738 	q80_rcv_cntxt_destroy_t		*rcntxt;
2739 	q80_rcv_cntxt_destroy_rsp_t	*rcntxt_rsp;
2740 	uint32_t			err;
2741 	uint8_t				bcast_mac[6];
2742 
2743 	if (!ha->hw.flags.init_rx_cnxt)
2744 		return;
2745 
2746 	if (qla_hw_del_all_mcast(ha))
2747 		return;
2748 
2749 	if (ha->hw.flags.bcast_mac) {
2750 
2751 		bcast_mac[0] = 0xFF; bcast_mac[1] = 0xFF; bcast_mac[2] = 0xFF;
2752 		bcast_mac[3] = 0xFF; bcast_mac[4] = 0xFF; bcast_mac[5] = 0xFF;
2753 
2754 		if (qla_config_mac_addr(ha, bcast_mac, 0, 1))
2755 			return;
2756 		ha->hw.flags.bcast_mac = 0;
2757 
2758 	}
2759 
2760 	if (ha->hw.flags.unicast_mac) {
2761 		if (qla_config_mac_addr(ha, ha->hw.mac_addr, 0, 1))
2762 			return;
2763 		ha->hw.flags.unicast_mac = 0;
2764 	}
2765 
2766 	rcntxt = (q80_rcv_cntxt_destroy_t *)ha->hw.mbox;
2767 	bzero(rcntxt, (sizeof (q80_rcv_cntxt_destroy_t)));
2768 
2769 	rcntxt->opcode = Q8_MBX_DESTROY_RX_CNTXT;
2770 	rcntxt->count_version = (sizeof (q80_rcv_cntxt_destroy_t) >> 2);
2771 	rcntxt->count_version |= Q8_MBX_CMD_VERSION;
2772 
2773 	rcntxt->cntxt_id = ha->hw.rcv_cntxt_id;
2774 
2775         if (qla_mbx_cmd(ha, (uint32_t *)rcntxt,
2776 		(sizeof (q80_rcv_cntxt_destroy_t) >> 2),
2777                 ha->hw.mbox, (sizeof(q80_rcv_cntxt_destroy_rsp_t) >> 2), 0)) {
2778                 device_printf(dev, "%s: failed0\n", __func__);
2779                 return;
2780         }
2781         rcntxt_rsp = (q80_rcv_cntxt_destroy_rsp_t *)ha->hw.mbox;
2782 
2783         err = Q8_MBX_RSP_STATUS(rcntxt_rsp->regcnt_status);
2784 
2785         if (err) {
2786                 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
2787         }
2788 
2789 	ha->hw.flags.init_rx_cnxt = 0;
2790 	return;
2791 }
2792 
2793 /*
2794  * Name: qla_init_xmt_cntxt
2795  * Function: Creates the Transmit Context.
2796  */
2797 static int
2798 qla_init_xmt_cntxt_i(qla_host_t *ha, uint32_t txr_idx)
2799 {
2800 	device_t		dev;
2801         qla_hw_t		*hw = &ha->hw;
2802 	q80_rq_tx_cntxt_t	*tcntxt;
2803 	q80_rsp_tx_cntxt_t	*tcntxt_rsp;
2804 	uint32_t		err;
2805 	qla_hw_tx_cntxt_t       *hw_tx_cntxt;
2806 
2807 	hw_tx_cntxt = &hw->tx_cntxt[txr_idx];
2808 
2809 	dev = ha->pci_dev;
2810 
2811 	/*
2812 	 * Create Transmit Context
2813 	 */
2814 	tcntxt = (q80_rq_tx_cntxt_t *)ha->hw.mbox;
2815 	bzero(tcntxt, (sizeof (q80_rq_tx_cntxt_t)));
2816 
2817 	tcntxt->opcode = Q8_MBX_CREATE_TX_CNTXT;
2818 	tcntxt->count_version = (sizeof (q80_rq_tx_cntxt_t) >> 2);
2819 	tcntxt->count_version |= Q8_MBX_CMD_VERSION;
2820 
2821 #ifdef QL_ENABLE_ISCSI_TLV
2822 
2823 	tcntxt->cap0 = Q8_TX_CNTXT_CAP0_BASEFW | Q8_TX_CNTXT_CAP0_LSO |
2824 				Q8_TX_CNTXT_CAP0_TC;
2825 
2826 	if (txr_idx >= (ha->hw.num_tx_rings >> 1)) {
2827 		tcntxt->traffic_class = 1;
2828 	}
2829 
2830 #else
2831 
2832 	tcntxt->cap0 = Q8_TX_CNTXT_CAP0_BASEFW | Q8_TX_CNTXT_CAP0_LSO;
2833 
2834 #endif /* #ifdef QL_ENABLE_ISCSI_TLV */
2835 
2836 	tcntxt->ntx_rings = 1;
2837 
2838 	tcntxt->tx_ring[0].paddr =
2839 		qla_host_to_le64(hw_tx_cntxt->tx_ring_paddr);
2840 	tcntxt->tx_ring[0].tx_consumer =
2841 		qla_host_to_le64(hw_tx_cntxt->tx_cons_paddr);
2842 	tcntxt->tx_ring[0].nentries = qla_host_to_le16(NUM_TX_DESCRIPTORS);
2843 
2844 	tcntxt->tx_ring[0].intr_id = qla_host_to_le16(hw->intr_id[0]);
2845 	tcntxt->tx_ring[0].intr_src_bit = qla_host_to_le16(0);
2846 
2847 
2848 	hw_tx_cntxt->txr_free = NUM_TX_DESCRIPTORS;
2849 	hw_tx_cntxt->txr_next = hw_tx_cntxt->txr_comp = 0;
2850 
2851         if (qla_mbx_cmd(ha, (uint32_t *)tcntxt,
2852 		(sizeof (q80_rq_tx_cntxt_t) >> 2),
2853                 ha->hw.mbox,
2854 		(sizeof(q80_rsp_tx_cntxt_t) >> 2), 0)) {
2855                 device_printf(dev, "%s: failed0\n", __func__);
2856                 return (-1);
2857         }
2858         tcntxt_rsp = (q80_rsp_tx_cntxt_t *)ha->hw.mbox;
2859 
2860         err = Q8_MBX_RSP_STATUS(tcntxt_rsp->regcnt_status);
2861 
2862         if (err) {
2863                 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
2864 		return -1;
2865         }
2866 
2867 	hw_tx_cntxt->tx_prod_reg = tcntxt_rsp->tx_ring[0].prod_index;
2868 	hw_tx_cntxt->tx_cntxt_id = tcntxt_rsp->tx_ring[0].cntxt_id;
2869 
2870 	if (qla_config_intr_coalesce(ha, hw_tx_cntxt->tx_cntxt_id, 0, 0))
2871 		return (-1);
2872 
2873 	return (0);
2874 }
2875 
2876 
2877 /*
2878  * Name: qla_del_xmt_cntxt
2879  * Function: Destroys the Transmit Context.
2880  */
2881 static int
2882 qla_del_xmt_cntxt_i(qla_host_t *ha, uint32_t txr_idx)
2883 {
2884 	device_t			dev = ha->pci_dev;
2885 	q80_tx_cntxt_destroy_t		*tcntxt;
2886 	q80_tx_cntxt_destroy_rsp_t	*tcntxt_rsp;
2887 	uint32_t			err;
2888 
2889 	tcntxt = (q80_tx_cntxt_destroy_t *)ha->hw.mbox;
2890 	bzero(tcntxt, (sizeof (q80_tx_cntxt_destroy_t)));
2891 
2892 	tcntxt->opcode = Q8_MBX_DESTROY_TX_CNTXT;
2893 	tcntxt->count_version = (sizeof (q80_tx_cntxt_destroy_t) >> 2);
2894 	tcntxt->count_version |= Q8_MBX_CMD_VERSION;
2895 
2896 	tcntxt->cntxt_id = ha->hw.tx_cntxt[txr_idx].tx_cntxt_id;
2897 
2898         if (qla_mbx_cmd(ha, (uint32_t *)tcntxt,
2899 		(sizeof (q80_tx_cntxt_destroy_t) >> 2),
2900                 ha->hw.mbox, (sizeof (q80_tx_cntxt_destroy_rsp_t) >> 2), 0)) {
2901                 device_printf(dev, "%s: failed0\n", __func__);
2902                 return (-1);
2903         }
2904         tcntxt_rsp = (q80_tx_cntxt_destroy_rsp_t *)ha->hw.mbox;
2905 
2906         err = Q8_MBX_RSP_STATUS(tcntxt_rsp->regcnt_status);
2907 
2908         if (err) {
2909                 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
2910 		return (-1);
2911         }
2912 
2913 	return (0);
2914 }
2915 static void
2916 qla_del_xmt_cntxt(qla_host_t *ha)
2917 {
2918 	uint32_t i;
2919 
2920 	if (!ha->hw.flags.init_tx_cnxt)
2921 		return;
2922 
2923 	for (i = 0; i < ha->hw.num_tx_rings; i++) {
2924 		if (qla_del_xmt_cntxt_i(ha, i))
2925 			break;
2926 	}
2927 	ha->hw.flags.init_tx_cnxt = 0;
2928 }
2929 
2930 static int
2931 qla_init_xmt_cntxt(qla_host_t *ha)
2932 {
2933 	uint32_t i, j;
2934 
2935 	for (i = 0; i < ha->hw.num_tx_rings; i++) {
2936 		if (qla_init_xmt_cntxt_i(ha, i) != 0) {
2937 			for (j = 0; j < i; j++)
2938 				qla_del_xmt_cntxt_i(ha, j);
2939 			return (-1);
2940 		}
2941 	}
2942 	ha->hw.flags.init_tx_cnxt = 1;
2943 	return (0);
2944 }
2945 
2946 static int
2947 qla_hw_all_mcast(qla_host_t *ha, uint32_t add_mcast)
2948 {
2949 	int i, nmcast;
2950 	uint32_t count = 0;
2951 	uint8_t *mcast;
2952 
2953 	nmcast = ha->hw.nmcast;
2954 
2955 	QL_DPRINT2(ha, (ha->pci_dev,
2956 		"%s:[0x%x] enter nmcast = %d \n", __func__, add_mcast, nmcast));
2957 
2958 	mcast = ha->hw.mac_addr_arr;
2959 	memset(mcast, 0, (Q8_MAX_MAC_ADDRS * ETHER_ADDR_LEN));
2960 
2961 	for (i = 0 ; ((i < Q8_MAX_NUM_MULTICAST_ADDRS) && nmcast); i++) {
2962 		if ((ha->hw.mcast[i].addr[0] != 0) ||
2963 			(ha->hw.mcast[i].addr[1] != 0) ||
2964 			(ha->hw.mcast[i].addr[2] != 0) ||
2965 			(ha->hw.mcast[i].addr[3] != 0) ||
2966 			(ha->hw.mcast[i].addr[4] != 0) ||
2967 			(ha->hw.mcast[i].addr[5] != 0)) {
2968 
2969 			bcopy(ha->hw.mcast[i].addr, mcast, ETHER_ADDR_LEN);
2970 			mcast = mcast + ETHER_ADDR_LEN;
2971 			count++;
2972 
2973 			if (count == Q8_MAX_MAC_ADDRS) {
2974 				if (qla_config_mac_addr(ha, ha->hw.mac_addr_arr,
2975 					add_mcast, count)) {
2976                 			device_printf(ha->pci_dev,
2977 						"%s: failed\n", __func__);
2978 					return (-1);
2979 				}
2980 
2981 				count = 0;
2982 				mcast = ha->hw.mac_addr_arr;
2983 				memset(mcast, 0,
2984 					(Q8_MAX_MAC_ADDRS * ETHER_ADDR_LEN));
2985 			}
2986 
2987 			nmcast--;
2988 		}
2989 	}
2990 
2991 	if (count) {
2992 		if (qla_config_mac_addr(ha, ha->hw.mac_addr_arr, add_mcast,
2993 			count)) {
2994                 	device_printf(ha->pci_dev, "%s: failed\n", __func__);
2995 			return (-1);
2996 		}
2997 	}
2998 	QL_DPRINT2(ha, (ha->pci_dev,
2999 		"%s:[0x%x] exit nmcast = %d \n", __func__, add_mcast, nmcast));
3000 
3001 	return 0;
3002 }
3003 
3004 static int
3005 qla_hw_add_all_mcast(qla_host_t *ha)
3006 {
3007 	int ret;
3008 
3009 	ret = qla_hw_all_mcast(ha, 1);
3010 
3011 	return (ret);
3012 }
3013 
3014 static int
3015 qla_hw_del_all_mcast(qla_host_t *ha)
3016 {
3017 	int ret;
3018 
3019 	ret = qla_hw_all_mcast(ha, 0);
3020 
3021 	bzero(ha->hw.mcast, (sizeof (qla_mcast_t) * Q8_MAX_NUM_MULTICAST_ADDRS));
3022 	ha->hw.nmcast = 0;
3023 
3024 	return (ret);
3025 }
3026 
3027 static int
3028 qla_hw_mac_addr_present(qla_host_t *ha, uint8_t *mta)
3029 {
3030 	int i;
3031 
3032 	for (i = 0; i < Q8_MAX_NUM_MULTICAST_ADDRS; i++) {
3033 		if (QL_MAC_CMP(ha->hw.mcast[i].addr, mta) == 0)
3034 			return (0); /* its been already added */
3035 	}
3036 	return (-1);
3037 }
3038 
3039 static int
3040 qla_hw_add_mcast(qla_host_t *ha, uint8_t *mta, uint32_t nmcast)
3041 {
3042 	int i;
3043 
3044 	for (i = 0; i < Q8_MAX_NUM_MULTICAST_ADDRS; i++) {
3045 
3046 		if ((ha->hw.mcast[i].addr[0] == 0) &&
3047 			(ha->hw.mcast[i].addr[1] == 0) &&
3048 			(ha->hw.mcast[i].addr[2] == 0) &&
3049 			(ha->hw.mcast[i].addr[3] == 0) &&
3050 			(ha->hw.mcast[i].addr[4] == 0) &&
3051 			(ha->hw.mcast[i].addr[5] == 0)) {
3052 
3053 			bcopy(mta, ha->hw.mcast[i].addr, Q8_MAC_ADDR_LEN);
3054 			ha->hw.nmcast++;
3055 
3056 			mta = mta + ETHER_ADDR_LEN;
3057 			nmcast--;
3058 
3059 			if (nmcast == 0)
3060 				break;
3061 		}
3062 
3063 	}
3064 	return 0;
3065 }
3066 
3067 static int
3068 qla_hw_del_mcast(qla_host_t *ha, uint8_t *mta, uint32_t nmcast)
3069 {
3070 	int i;
3071 
3072 	for (i = 0; i < Q8_MAX_NUM_MULTICAST_ADDRS; i++) {
3073 		if (QL_MAC_CMP(ha->hw.mcast[i].addr, mta) == 0) {
3074 
3075 			ha->hw.mcast[i].addr[0] = 0;
3076 			ha->hw.mcast[i].addr[1] = 0;
3077 			ha->hw.mcast[i].addr[2] = 0;
3078 			ha->hw.mcast[i].addr[3] = 0;
3079 			ha->hw.mcast[i].addr[4] = 0;
3080 			ha->hw.mcast[i].addr[5] = 0;
3081 
3082 			ha->hw.nmcast--;
3083 
3084 			mta = mta + ETHER_ADDR_LEN;
3085 			nmcast--;
3086 
3087 			if (nmcast == 0)
3088 				break;
3089 		}
3090 	}
3091 	return 0;
3092 }
3093 
3094 /*
3095  * Name: ql_hw_set_multi
3096  * Function: Sets the Multicast Addresses provided by the host O.S into the
3097  *	hardware (for the given interface)
3098  */
3099 int
3100 ql_hw_set_multi(qla_host_t *ha, uint8_t *mcast_addr, uint32_t mcnt,
3101 	uint32_t add_mac)
3102 {
3103 	uint8_t *mta = mcast_addr;
3104 	int i;
3105 	int ret = 0;
3106 	uint32_t count = 0;
3107 	uint8_t *mcast;
3108 
3109 	mcast = ha->hw.mac_addr_arr;
3110 	memset(mcast, 0, (Q8_MAX_MAC_ADDRS * ETHER_ADDR_LEN));
3111 
3112 	for (i = 0; i < mcnt; i++) {
3113 		if (mta[0] || mta[1] || mta[2] || mta[3] || mta[4] || mta[5]) {
3114 			if (add_mac) {
3115 				if (qla_hw_mac_addr_present(ha, mta) != 0) {
3116 					bcopy(mta, mcast, ETHER_ADDR_LEN);
3117 					mcast = mcast + ETHER_ADDR_LEN;
3118 					count++;
3119 				}
3120 			} else {
3121 				if (qla_hw_mac_addr_present(ha, mta) == 0) {
3122 					bcopy(mta, mcast, ETHER_ADDR_LEN);
3123 					mcast = mcast + ETHER_ADDR_LEN;
3124 					count++;
3125 				}
3126 			}
3127 		}
3128 		if (count == Q8_MAX_MAC_ADDRS) {
3129 			if (qla_config_mac_addr(ha, ha->hw.mac_addr_arr,
3130 				add_mac, count)) {
3131                 		device_printf(ha->pci_dev, "%s: failed\n",
3132 					__func__);
3133 				return (-1);
3134 			}
3135 
3136 			if (add_mac) {
3137 				qla_hw_add_mcast(ha, ha->hw.mac_addr_arr,
3138 					count);
3139 			} else {
3140 				qla_hw_del_mcast(ha, ha->hw.mac_addr_arr,
3141 					count);
3142 			}
3143 
3144 			count = 0;
3145 			mcast = ha->hw.mac_addr_arr;
3146 			memset(mcast, 0, (Q8_MAX_MAC_ADDRS * ETHER_ADDR_LEN));
3147 		}
3148 
3149 		mta += Q8_MAC_ADDR_LEN;
3150 	}
3151 
3152 	if (count) {
3153 		if (qla_config_mac_addr(ha, ha->hw.mac_addr_arr, add_mac,
3154 			count)) {
3155                 	device_printf(ha->pci_dev, "%s: failed\n", __func__);
3156 			return (-1);
3157 		}
3158 		if (add_mac) {
3159 			qla_hw_add_mcast(ha, ha->hw.mac_addr_arr, count);
3160 		} else {
3161 			qla_hw_del_mcast(ha, ha->hw.mac_addr_arr, count);
3162 		}
3163 	}
3164 
3165 	return (ret);
3166 }
3167 
3168 /*
3169  * Name: qla_hw_tx_done_locked
3170  * Function: Handle Transmit Completions
3171  */
3172 static void
3173 qla_hw_tx_done_locked(qla_host_t *ha, uint32_t txr_idx)
3174 {
3175 	qla_tx_buf_t *txb;
3176         qla_hw_t *hw = &ha->hw;
3177 	uint32_t comp_idx, comp_count = 0;
3178 	qla_hw_tx_cntxt_t *hw_tx_cntxt;
3179 
3180 	hw_tx_cntxt = &hw->tx_cntxt[txr_idx];
3181 
3182 	/* retrieve index of last entry in tx ring completed */
3183 	comp_idx = qla_le32_to_host(*(hw_tx_cntxt->tx_cons));
3184 
3185 	while (comp_idx != hw_tx_cntxt->txr_comp) {
3186 
3187 		txb = &ha->tx_ring[txr_idx].tx_buf[hw_tx_cntxt->txr_comp];
3188 
3189 		hw_tx_cntxt->txr_comp++;
3190 		if (hw_tx_cntxt->txr_comp == NUM_TX_DESCRIPTORS)
3191 			hw_tx_cntxt->txr_comp = 0;
3192 
3193 		comp_count++;
3194 
3195 		if (txb->m_head) {
3196 			if_inc_counter(ha->ifp, IFCOUNTER_OPACKETS, 1);
3197 
3198 			bus_dmamap_sync(ha->tx_tag, txb->map,
3199 				BUS_DMASYNC_POSTWRITE);
3200 			bus_dmamap_unload(ha->tx_tag, txb->map);
3201 			m_freem(txb->m_head);
3202 
3203 			txb->m_head = NULL;
3204 		}
3205 	}
3206 
3207 	hw_tx_cntxt->txr_free += comp_count;
3208 	return;
3209 }
3210 
3211 /*
3212  * Name: ql_hw_tx_done
3213  * Function: Handle Transmit Completions
3214  */
3215 void
3216 ql_hw_tx_done(qla_host_t *ha)
3217 {
3218 	int i;
3219 	uint32_t flag = 0;
3220 
3221 	if (!mtx_trylock(&ha->tx_lock)) {
3222        		QL_DPRINT8(ha, (ha->pci_dev,
3223 			"%s: !mtx_trylock(&ha->tx_lock)\n", __func__));
3224 		return;
3225 	}
3226 	for (i = 0; i < ha->hw.num_tx_rings; i++) {
3227 		qla_hw_tx_done_locked(ha, i);
3228 		if (ha->hw.tx_cntxt[i].txr_free <= (NUM_TX_DESCRIPTORS >> 1))
3229 			flag = 1;
3230 	}
3231 
3232 	if (!flag)
3233 		ha->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
3234 
3235 	QLA_TX_UNLOCK(ha);
3236 	return;
3237 }
3238 
3239 void
3240 ql_update_link_state(qla_host_t *ha)
3241 {
3242 	uint32_t link_state;
3243 	uint32_t prev_link_state;
3244 
3245 	if (!(ha->ifp->if_drv_flags & IFF_DRV_RUNNING)) {
3246 		ha->hw.link_up = 0;
3247 		return;
3248 	}
3249 	link_state = READ_REG32(ha, Q8_LINK_STATE);
3250 
3251 	prev_link_state =  ha->hw.link_up;
3252 
3253 	if (ha->pci_func == 0)
3254 		ha->hw.link_up = (((link_state & 0xF) == 1)? 1 : 0);
3255 	else
3256 		ha->hw.link_up = ((((link_state >> 4)& 0xF) == 1)? 1 : 0);
3257 
3258 	if (prev_link_state !=  ha->hw.link_up) {
3259 		if (ha->hw.link_up) {
3260 			if_link_state_change(ha->ifp, LINK_STATE_UP);
3261 		} else {
3262 			if_link_state_change(ha->ifp, LINK_STATE_DOWN);
3263 		}
3264 	}
3265 	return;
3266 }
3267 
3268 void
3269 ql_hw_stop_rcv(qla_host_t *ha)
3270 {
3271 	int i, done, count = 100;
3272 
3273 	ha->flags.stop_rcv = 1;
3274 
3275 	while (count) {
3276 		done = 1;
3277 		for (i = 0; i < ha->hw.num_sds_rings; i++) {
3278 			if (ha->hw.sds[i].rcv_active)
3279 				done = 0;
3280 		}
3281 		if (done)
3282 			break;
3283 		else
3284 			qla_mdelay(__func__, 10);
3285 		count--;
3286 	}
3287 	if (!count)
3288 		device_printf(ha->pci_dev, "%s: Counter expired.\n", __func__);
3289 
3290 	return;
3291 }
3292 
3293 int
3294 ql_hw_check_health(qla_host_t *ha)
3295 {
3296 	uint32_t val;
3297 
3298 	ha->hw.health_count++;
3299 
3300 	if (ha->hw.health_count < 1000)
3301 		return 0;
3302 
3303 	ha->hw.health_count = 0;
3304 
3305 	val = READ_REG32(ha, Q8_ASIC_TEMPERATURE);
3306 
3307 	if (((val & 0xFFFF) == 2) || ((val & 0xFFFF) == 3) ||
3308 		(QL_ERR_INJECT(ha, INJCT_TEMPERATURE_FAILURE))) {
3309 		device_printf(ha->pci_dev, "%s: Temperature Alert [0x%08x]\n",
3310 			__func__, val);
3311 		return -1;
3312 	}
3313 
3314 	val = READ_REG32(ha, Q8_FIRMWARE_HEARTBEAT);
3315 
3316 	if ((val != ha->hw.hbeat_value) &&
3317 		(!(QL_ERR_INJECT(ha, INJCT_HEARTBEAT_FAILURE)))) {
3318 		ha->hw.hbeat_value = val;
3319 		return 0;
3320 	}
3321 	device_printf(ha->pci_dev, "%s: Heartbeat Failue [0x%08x]\n",
3322 		__func__, val);
3323 
3324 	return -1;
3325 }
3326 
3327 static int
3328 qla_init_nic_func(qla_host_t *ha)
3329 {
3330         device_t                dev;
3331         q80_init_nic_func_t     *init_nic;
3332         q80_init_nic_func_rsp_t *init_nic_rsp;
3333         uint32_t                err;
3334 
3335         dev = ha->pci_dev;
3336 
3337         init_nic = (q80_init_nic_func_t *)ha->hw.mbox;
3338         bzero(init_nic, sizeof(q80_init_nic_func_t));
3339 
3340         init_nic->opcode = Q8_MBX_INIT_NIC_FUNC;
3341         init_nic->count_version = (sizeof (q80_init_nic_func_t) >> 2);
3342         init_nic->count_version |= Q8_MBX_CMD_VERSION;
3343 
3344         init_nic->options = Q8_INIT_NIC_REG_DCBX_CHNG_AEN;
3345         init_nic->options |= Q8_INIT_NIC_REG_SFP_CHNG_AEN;
3346         init_nic->options |= Q8_INIT_NIC_REG_IDC_AEN;
3347 
3348 //qla_dump_buf8(ha, __func__, init_nic, sizeof (q80_init_nic_func_t));
3349         if (qla_mbx_cmd(ha, (uint32_t *)init_nic,
3350                 (sizeof (q80_init_nic_func_t) >> 2),
3351                 ha->hw.mbox, (sizeof (q80_init_nic_func_rsp_t) >> 2), 0)) {
3352                 device_printf(dev, "%s: failed\n", __func__);
3353                 return -1;
3354         }
3355 
3356         init_nic_rsp = (q80_init_nic_func_rsp_t *)ha->hw.mbox;
3357 // qla_dump_buf8(ha, __func__, init_nic_rsp, sizeof (q80_init_nic_func_rsp_t));
3358 
3359         err = Q8_MBX_RSP_STATUS(init_nic_rsp->regcnt_status);
3360 
3361         if (err) {
3362                 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
3363         }
3364 
3365         return 0;
3366 }
3367 
3368 static int
3369 qla_stop_nic_func(qla_host_t *ha)
3370 {
3371         device_t                dev;
3372         q80_stop_nic_func_t     *stop_nic;
3373         q80_stop_nic_func_rsp_t *stop_nic_rsp;
3374         uint32_t                err;
3375 
3376         dev = ha->pci_dev;
3377 
3378         stop_nic = (q80_stop_nic_func_t *)ha->hw.mbox;
3379         bzero(stop_nic, sizeof(q80_stop_nic_func_t));
3380 
3381         stop_nic->opcode = Q8_MBX_STOP_NIC_FUNC;
3382         stop_nic->count_version = (sizeof (q80_stop_nic_func_t) >> 2);
3383         stop_nic->count_version |= Q8_MBX_CMD_VERSION;
3384 
3385         stop_nic->options = Q8_STOP_NIC_DEREG_DCBX_CHNG_AEN;
3386         stop_nic->options |= Q8_STOP_NIC_DEREG_SFP_CHNG_AEN;
3387 
3388 //qla_dump_buf8(ha, __func__, stop_nic, sizeof (q80_stop_nic_func_t));
3389         if (qla_mbx_cmd(ha, (uint32_t *)stop_nic,
3390                 (sizeof (q80_stop_nic_func_t) >> 2),
3391                 ha->hw.mbox, (sizeof (q80_stop_nic_func_rsp_t) >> 2), 0)) {
3392                 device_printf(dev, "%s: failed\n", __func__);
3393                 return -1;
3394         }
3395 
3396         stop_nic_rsp = (q80_stop_nic_func_rsp_t *)ha->hw.mbox;
3397 //qla_dump_buf8(ha, __func__, stop_nic_rsp, sizeof (q80_stop_nic_func_rsp_ t));
3398 
3399         err = Q8_MBX_RSP_STATUS(stop_nic_rsp->regcnt_status);
3400 
3401         if (err) {
3402                 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
3403         }
3404 
3405         return 0;
3406 }
3407 
3408 static int
3409 qla_query_fw_dcbx_caps(qla_host_t *ha)
3410 {
3411         device_t                        dev;
3412         q80_query_fw_dcbx_caps_t        *fw_dcbx;
3413         q80_query_fw_dcbx_caps_rsp_t    *fw_dcbx_rsp;
3414         uint32_t                        err;
3415 
3416         dev = ha->pci_dev;
3417 
3418         fw_dcbx = (q80_query_fw_dcbx_caps_t *)ha->hw.mbox;
3419         bzero(fw_dcbx, sizeof(q80_query_fw_dcbx_caps_t));
3420 
3421         fw_dcbx->opcode = Q8_MBX_GET_FW_DCBX_CAPS;
3422         fw_dcbx->count_version = (sizeof (q80_query_fw_dcbx_caps_t) >> 2);
3423         fw_dcbx->count_version |= Q8_MBX_CMD_VERSION;
3424 
3425         ql_dump_buf8(ha, __func__, fw_dcbx, sizeof (q80_query_fw_dcbx_caps_t));
3426         if (qla_mbx_cmd(ha, (uint32_t *)fw_dcbx,
3427                 (sizeof (q80_query_fw_dcbx_caps_t) >> 2),
3428                 ha->hw.mbox, (sizeof (q80_query_fw_dcbx_caps_rsp_t) >> 2), 0)) {
3429                 device_printf(dev, "%s: failed\n", __func__);
3430                 return -1;
3431         }
3432 
3433         fw_dcbx_rsp = (q80_query_fw_dcbx_caps_rsp_t *)ha->hw.mbox;
3434         ql_dump_buf8(ha, __func__, fw_dcbx_rsp,
3435                 sizeof (q80_query_fw_dcbx_caps_rsp_t));
3436 
3437         err = Q8_MBX_RSP_STATUS(fw_dcbx_rsp->regcnt_status);
3438 
3439         if (err) {
3440                 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
3441         }
3442 
3443         return 0;
3444 }
3445 
3446 static int
3447 qla_idc_ack(qla_host_t *ha, uint32_t aen_mb1, uint32_t aen_mb2,
3448         uint32_t aen_mb3, uint32_t aen_mb4)
3449 {
3450         device_t                dev;
3451         q80_idc_ack_t           *idc_ack;
3452         q80_idc_ack_rsp_t       *idc_ack_rsp;
3453         uint32_t                err;
3454         int                     count = 300;
3455 
3456         dev = ha->pci_dev;
3457 
3458         idc_ack = (q80_idc_ack_t *)ha->hw.mbox;
3459         bzero(idc_ack, sizeof(q80_idc_ack_t));
3460 
3461         idc_ack->opcode = Q8_MBX_IDC_ACK;
3462         idc_ack->count_version = (sizeof (q80_idc_ack_t) >> 2);
3463         idc_ack->count_version |= Q8_MBX_CMD_VERSION;
3464 
3465         idc_ack->aen_mb1 = aen_mb1;
3466         idc_ack->aen_mb2 = aen_mb2;
3467         idc_ack->aen_mb3 = aen_mb3;
3468         idc_ack->aen_mb4 = aen_mb4;
3469 
3470         ha->hw.imd_compl= 0;
3471 
3472         if (qla_mbx_cmd(ha, (uint32_t *)idc_ack,
3473                 (sizeof (q80_idc_ack_t) >> 2),
3474                 ha->hw.mbox, (sizeof (q80_idc_ack_rsp_t) >> 2), 0)) {
3475                 device_printf(dev, "%s: failed\n", __func__);
3476                 return -1;
3477         }
3478 
3479         idc_ack_rsp = (q80_idc_ack_rsp_t *)ha->hw.mbox;
3480 
3481         err = Q8_MBX_RSP_STATUS(idc_ack_rsp->regcnt_status);
3482 
3483         if (err) {
3484                 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
3485                 return(-1);
3486         }
3487 
3488         while (count && !ha->hw.imd_compl) {
3489                 qla_mdelay(__func__, 100);
3490                 count--;
3491         }
3492 
3493         if (!count)
3494                 return -1;
3495         else
3496                 device_printf(dev, "%s: count %d\n", __func__, count);
3497 
3498         return (0);
3499 }
3500 
3501 static int
3502 qla_set_port_config(qla_host_t *ha, uint32_t cfg_bits)
3503 {
3504         device_t                dev;
3505         q80_set_port_cfg_t      *pcfg;
3506         q80_set_port_cfg_rsp_t  *pfg_rsp;
3507         uint32_t                err;
3508         int                     count = 300;
3509 
3510         dev = ha->pci_dev;
3511 
3512         pcfg = (q80_set_port_cfg_t *)ha->hw.mbox;
3513         bzero(pcfg, sizeof(q80_set_port_cfg_t));
3514 
3515         pcfg->opcode = Q8_MBX_SET_PORT_CONFIG;
3516         pcfg->count_version = (sizeof (q80_set_port_cfg_t) >> 2);
3517         pcfg->count_version |= Q8_MBX_CMD_VERSION;
3518 
3519         pcfg->cfg_bits = cfg_bits;
3520 
3521         device_printf(dev, "%s: cfg_bits"
3522                 " [STD_PAUSE_DIR, PAUSE_TYPE, DCBX]"
3523                 " [0x%x, 0x%x, 0x%x]\n", __func__,
3524                 ((cfg_bits & Q8_PORT_CFG_BITS_STDPAUSE_DIR_MASK)>>20),
3525                 ((cfg_bits & Q8_PORT_CFG_BITS_PAUSE_CFG_MASK) >> 5),
3526                 ((cfg_bits & Q8_PORT_CFG_BITS_DCBX_ENABLE) ? 1: 0));
3527 
3528         ha->hw.imd_compl= 0;
3529 
3530         if (qla_mbx_cmd(ha, (uint32_t *)pcfg,
3531                 (sizeof (q80_set_port_cfg_t) >> 2),
3532                 ha->hw.mbox, (sizeof (q80_set_port_cfg_rsp_t) >> 2), 0)) {
3533                 device_printf(dev, "%s: failed\n", __func__);
3534                 return -1;
3535         }
3536 
3537         pfg_rsp = (q80_set_port_cfg_rsp_t *)ha->hw.mbox;
3538 
3539         err = Q8_MBX_RSP_STATUS(pfg_rsp->regcnt_status);
3540 
3541         if (err == Q8_MBX_RSP_IDC_INTRMD_RSP) {
3542                 while (count && !ha->hw.imd_compl) {
3543                         qla_mdelay(__func__, 100);
3544                         count--;
3545                 }
3546                 if (count) {
3547                         device_printf(dev, "%s: count %d\n", __func__, count);
3548 
3549                         err = 0;
3550                 }
3551         }
3552 
3553         if (err) {
3554                 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
3555                 return(-1);
3556         }
3557 
3558         return (0);
3559 }
3560 
3561 
3562 static int
3563 qla_get_minidump_tmplt_size(qla_host_t *ha, uint32_t *size)
3564 {
3565 	uint32_t			err;
3566 	device_t			dev = ha->pci_dev;
3567 	q80_config_md_templ_size_t	*md_size;
3568 	q80_config_md_templ_size_rsp_t	*md_size_rsp;
3569 
3570 #ifndef QL_LDFLASH_FW
3571 
3572 	ql_minidump_template_hdr_t *hdr;
3573 
3574 	hdr = (ql_minidump_template_hdr_t *)ql83xx_minidump;
3575 	*size = hdr->size_of_template;
3576 	return (0);
3577 
3578 #endif /* #ifdef QL_LDFLASH_FW */
3579 
3580 	md_size = (q80_config_md_templ_size_t *) ha->hw.mbox;
3581 	bzero(md_size, sizeof(q80_config_md_templ_size_t));
3582 
3583 	md_size->opcode = Q8_MBX_GET_MINIDUMP_TMPLT_SIZE;
3584 	md_size->count_version = (sizeof (q80_config_md_templ_size_t) >> 2);
3585 	md_size->count_version |= Q8_MBX_CMD_VERSION;
3586 
3587 	if (qla_mbx_cmd(ha, (uint32_t *) md_size,
3588 		(sizeof(q80_config_md_templ_size_t) >> 2), ha->hw.mbox,
3589 		(sizeof(q80_config_md_templ_size_rsp_t) >> 2), 0)) {
3590 
3591 		device_printf(dev, "%s: failed\n", __func__);
3592 
3593 		return (-1);
3594 	}
3595 
3596 	md_size_rsp = (q80_config_md_templ_size_rsp_t *) ha->hw.mbox;
3597 
3598 	err = Q8_MBX_RSP_STATUS(md_size_rsp->regcnt_status);
3599 
3600         if (err) {
3601 		device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
3602 		return(-1);
3603         }
3604 
3605 	*size = md_size_rsp->templ_size;
3606 
3607 	return (0);
3608 }
3609 
3610 static int
3611 qla_get_port_config(qla_host_t *ha, uint32_t *cfg_bits)
3612 {
3613         device_t                dev;
3614         q80_get_port_cfg_t      *pcfg;
3615         q80_get_port_cfg_rsp_t  *pcfg_rsp;
3616         uint32_t                err;
3617 
3618         dev = ha->pci_dev;
3619 
3620         pcfg = (q80_get_port_cfg_t *)ha->hw.mbox;
3621         bzero(pcfg, sizeof(q80_get_port_cfg_t));
3622 
3623         pcfg->opcode = Q8_MBX_GET_PORT_CONFIG;
3624         pcfg->count_version = (sizeof (q80_get_port_cfg_t) >> 2);
3625         pcfg->count_version |= Q8_MBX_CMD_VERSION;
3626 
3627         if (qla_mbx_cmd(ha, (uint32_t *)pcfg,
3628                 (sizeof (q80_get_port_cfg_t) >> 2),
3629                 ha->hw.mbox, (sizeof (q80_get_port_cfg_rsp_t) >> 2), 0)) {
3630                 device_printf(dev, "%s: failed\n", __func__);
3631                 return -1;
3632         }
3633 
3634         pcfg_rsp = (q80_get_port_cfg_rsp_t *)ha->hw.mbox;
3635 
3636         err = Q8_MBX_RSP_STATUS(pcfg_rsp->regcnt_status);
3637 
3638         if (err) {
3639                 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
3640                 return(-1);
3641         }
3642 
3643         device_printf(dev, "%s: [cfg_bits, port type]"
3644                 " [0x%08x, 0x%02x] [STD_PAUSE_DIR, PAUSE_TYPE, DCBX]"
3645                 " [0x%x, 0x%x, 0x%x]\n", __func__,
3646                 pcfg_rsp->cfg_bits, pcfg_rsp->phys_port_type,
3647                 ((pcfg_rsp->cfg_bits & Q8_PORT_CFG_BITS_STDPAUSE_DIR_MASK)>>20),
3648                 ((pcfg_rsp->cfg_bits & Q8_PORT_CFG_BITS_PAUSE_CFG_MASK) >> 5),
3649                 ((pcfg_rsp->cfg_bits & Q8_PORT_CFG_BITS_DCBX_ENABLE) ? 1: 0)
3650                 );
3651 
3652         *cfg_bits = pcfg_rsp->cfg_bits;
3653 
3654         return (0);
3655 }
3656 
3657 int
3658 qla_iscsi_pdu(qla_host_t *ha, struct mbuf *mp)
3659 {
3660         struct ether_vlan_header        *eh;
3661         uint16_t                        etype;
3662         struct ip                       *ip = NULL;
3663         struct ip6_hdr                  *ip6 = NULL;
3664         struct tcphdr                   *th = NULL;
3665         uint32_t                        hdrlen;
3666         uint32_t                        offset;
3667         uint8_t                         buf[sizeof(struct ip6_hdr)];
3668 
3669         eh = mtod(mp, struct ether_vlan_header *);
3670 
3671         if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
3672                 hdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
3673                 etype = ntohs(eh->evl_proto);
3674         } else {
3675                 hdrlen = ETHER_HDR_LEN;
3676                 etype = ntohs(eh->evl_encap_proto);
3677         }
3678 
3679 	if (etype == ETHERTYPE_IP) {
3680 
3681 		offset = (hdrlen + sizeof (struct ip));
3682 
3683 		if (mp->m_len >= offset) {
3684                         ip = (struct ip *)(mp->m_data + hdrlen);
3685 		} else {
3686 			m_copydata(mp, hdrlen, sizeof (struct ip), buf);
3687                         ip = (struct ip *)buf;
3688 		}
3689 
3690                 if (ip->ip_p == IPPROTO_TCP) {
3691 
3692 			hdrlen += ip->ip_hl << 2;
3693 			offset = hdrlen + 4;
3694 
3695 			if (mp->m_len >= offset) {
3696 				th = (struct tcphdr *)(mp->m_data + hdrlen);;
3697 			} else {
3698                                 m_copydata(mp, hdrlen, 4, buf);
3699 				th = (struct tcphdr *)buf;
3700 			}
3701                 }
3702 
3703 	} else if (etype == ETHERTYPE_IPV6) {
3704 
3705 		offset = (hdrlen + sizeof (struct ip6_hdr));
3706 
3707 		if (mp->m_len >= offset) {
3708                         ip6 = (struct ip6_hdr *)(mp->m_data + hdrlen);
3709 		} else {
3710                         m_copydata(mp, hdrlen, sizeof (struct ip6_hdr), buf);
3711                         ip6 = (struct ip6_hdr *)buf;
3712 		}
3713 
3714                 if (ip6->ip6_nxt == IPPROTO_TCP) {
3715 
3716 			hdrlen += sizeof(struct ip6_hdr);
3717 			offset = hdrlen + 4;
3718 
3719 			if (mp->m_len >= offset) {
3720 				th = (struct tcphdr *)(mp->m_data + hdrlen);;
3721 			} else {
3722 				m_copydata(mp, hdrlen, 4, buf);
3723 				th = (struct tcphdr *)buf;
3724 			}
3725                 }
3726 	}
3727 
3728         if (th != NULL) {
3729                 if ((th->th_sport == htons(3260)) ||
3730                         (th->th_dport == htons(3260)))
3731                         return 0;
3732         }
3733         return (-1);
3734 }
3735 
3736 void
3737 qla_hw_async_event(qla_host_t *ha)
3738 {
3739         switch (ha->hw.aen_mb0) {
3740         case 0x8101:
3741                 (void)qla_idc_ack(ha, ha->hw.aen_mb1, ha->hw.aen_mb2,
3742                         ha->hw.aen_mb3, ha->hw.aen_mb4);
3743 
3744                 break;
3745 
3746         default:
3747                 break;
3748         }
3749 
3750         return;
3751 }
3752 
3753 #ifdef QL_LDFLASH_FW
3754 static int
3755 ql_get_minidump_template(qla_host_t *ha)
3756 {
3757 	uint32_t			err;
3758 	device_t			dev = ha->pci_dev;
3759 	q80_config_md_templ_cmd_t	*md_templ;
3760 	q80_config_md_templ_cmd_rsp_t	*md_templ_rsp;
3761 
3762 	md_templ = (q80_config_md_templ_cmd_t *) ha->hw.mbox;
3763 	bzero(md_templ, (sizeof (q80_config_md_templ_cmd_t)));
3764 
3765 	md_templ->opcode = Q8_MBX_GET_MINIDUMP_TMPLT;
3766 	md_templ->count_version = ( sizeof(q80_config_md_templ_cmd_t) >> 2);
3767 	md_templ->count_version |= Q8_MBX_CMD_VERSION;
3768 
3769 	md_templ->buf_addr = ha->hw.dma_buf.minidump.dma_addr;
3770 	md_templ->buff_size = ha->hw.dma_buf.minidump.size;
3771 
3772 	if (qla_mbx_cmd(ha, (uint32_t *) md_templ,
3773 		(sizeof(q80_config_md_templ_cmd_t) >> 2),
3774 		 ha->hw.mbox,
3775 		(sizeof(q80_config_md_templ_cmd_rsp_t) >> 2), 0)) {
3776 
3777 		device_printf(dev, "%s: failed\n", __func__);
3778 
3779 		return (-1);
3780 	}
3781 
3782 	md_templ_rsp = (q80_config_md_templ_cmd_rsp_t *) ha->hw.mbox;
3783 
3784 	err = Q8_MBX_RSP_STATUS(md_templ_rsp->regcnt_status);
3785 
3786 	if (err) {
3787 		device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
3788 		return (-1);
3789 	}
3790 
3791 	return (0);
3792 
3793 }
3794 #endif /* #ifdef QL_LDFLASH_FW */
3795 
3796 /*
3797  * Minidump related functionality
3798  */
3799 
3800 static int ql_parse_template(qla_host_t *ha);
3801 
3802 static uint32_t ql_rdcrb(qla_host_t *ha,
3803 			ql_minidump_entry_rdcrb_t *crb_entry,
3804 			uint32_t * data_buff);
3805 
3806 static uint32_t ql_pollrd(qla_host_t *ha,
3807 			ql_minidump_entry_pollrd_t *entry,
3808 			uint32_t * data_buff);
3809 
3810 static uint32_t ql_pollrd_modify_write(qla_host_t *ha,
3811 			ql_minidump_entry_rd_modify_wr_with_poll_t *entry,
3812 			uint32_t *data_buff);
3813 
3814 static uint32_t ql_L2Cache(qla_host_t *ha,
3815 			ql_minidump_entry_cache_t *cacheEntry,
3816 			uint32_t * data_buff);
3817 
3818 static uint32_t ql_L1Cache(qla_host_t *ha,
3819 			ql_minidump_entry_cache_t *cacheEntry,
3820 			uint32_t *data_buff);
3821 
3822 static uint32_t ql_rdocm(qla_host_t *ha,
3823 			ql_minidump_entry_rdocm_t *ocmEntry,
3824 			uint32_t *data_buff);
3825 
3826 static uint32_t ql_rdmem(qla_host_t *ha,
3827 			ql_minidump_entry_rdmem_t *mem_entry,
3828 			uint32_t *data_buff);
3829 
3830 static uint32_t ql_rdrom(qla_host_t *ha,
3831 			ql_minidump_entry_rdrom_t *romEntry,
3832 			uint32_t *data_buff);
3833 
3834 static uint32_t ql_rdmux(qla_host_t *ha,
3835 			ql_minidump_entry_mux_t *muxEntry,
3836 			uint32_t *data_buff);
3837 
3838 static uint32_t ql_rdmux2(qla_host_t *ha,
3839 			ql_minidump_entry_mux2_t *muxEntry,
3840 			uint32_t *data_buff);
3841 
3842 static uint32_t ql_rdqueue(qla_host_t *ha,
3843 			ql_minidump_entry_queue_t *queueEntry,
3844 			uint32_t *data_buff);
3845 
3846 static uint32_t ql_cntrl(qla_host_t *ha,
3847 			ql_minidump_template_hdr_t *template_hdr,
3848 			ql_minidump_entry_cntrl_t *crbEntry);
3849 
3850 
3851 static uint32_t
3852 ql_minidump_size(qla_host_t *ha)
3853 {
3854 	uint32_t i, k;
3855 	uint32_t size = 0;
3856 	ql_minidump_template_hdr_t *hdr;
3857 
3858 	hdr = (ql_minidump_template_hdr_t *)ha->hw.dma_buf.minidump.dma_b;
3859 
3860 	i = 0x2;
3861 
3862 	for (k = 1; k < QL_DBG_CAP_SIZE_ARRAY_LEN; k++) {
3863 		if (i & ha->hw.mdump_capture_mask)
3864 			size += hdr->capture_size_array[k];
3865 		i = i << 1;
3866 	}
3867 	return (size);
3868 }
3869 
3870 static void
3871 ql_free_minidump_buffer(qla_host_t *ha)
3872 {
3873 	if (ha->hw.mdump_buffer != NULL) {
3874 		free(ha->hw.mdump_buffer, M_QLA83XXBUF);
3875 		ha->hw.mdump_buffer = NULL;
3876 		ha->hw.mdump_buffer_size = 0;
3877 	}
3878 	return;
3879 }
3880 
3881 static int
3882 ql_alloc_minidump_buffer(qla_host_t *ha)
3883 {
3884 	ha->hw.mdump_buffer_size = ql_minidump_size(ha);
3885 
3886 	if (!ha->hw.mdump_buffer_size)
3887 		return (-1);
3888 
3889 	ha->hw.mdump_buffer = malloc(ha->hw.mdump_buffer_size, M_QLA83XXBUF,
3890 					M_NOWAIT);
3891 
3892 	if (ha->hw.mdump_buffer == NULL)
3893 		return (-1);
3894 
3895 	return (0);
3896 }
3897 
3898 static void
3899 ql_free_minidump_template_buffer(qla_host_t *ha)
3900 {
3901 	if (ha->hw.mdump_template != NULL) {
3902 		free(ha->hw.mdump_template, M_QLA83XXBUF);
3903 		ha->hw.mdump_template = NULL;
3904 		ha->hw.mdump_template_size = 0;
3905 	}
3906 	return;
3907 }
3908 
3909 static int
3910 ql_alloc_minidump_template_buffer(qla_host_t *ha)
3911 {
3912 	ha->hw.mdump_template_size = ha->hw.dma_buf.minidump.size;
3913 
3914 	ha->hw.mdump_template = malloc(ha->hw.mdump_template_size,
3915 					M_QLA83XXBUF, M_NOWAIT);
3916 
3917 	if (ha->hw.mdump_template == NULL)
3918 		return (-1);
3919 
3920 	return (0);
3921 }
3922 
3923 static int
3924 ql_alloc_minidump_buffers(qla_host_t *ha)
3925 {
3926 	int ret;
3927 
3928 	ret = ql_alloc_minidump_template_buffer(ha);
3929 
3930 	if (ret)
3931 		return (ret);
3932 
3933 	ret = ql_alloc_minidump_buffer(ha);
3934 
3935 	if (ret)
3936 		ql_free_minidump_template_buffer(ha);
3937 
3938 	return (ret);
3939 }
3940 
3941 
3942 static uint32_t
3943 ql_validate_minidump_checksum(qla_host_t *ha)
3944 {
3945         uint64_t sum = 0;
3946 	int count;
3947 	uint32_t *template_buff;
3948 
3949 	count = ha->hw.dma_buf.minidump.size / sizeof (uint32_t);
3950 	template_buff = ha->hw.dma_buf.minidump.dma_b;
3951 
3952 	while (count-- > 0) {
3953 		sum += *template_buff++;
3954 	}
3955 
3956 	while (sum >> 32) {
3957 		sum = (sum & 0xFFFFFFFF) + (sum >> 32);
3958 	}
3959 
3960 	return (~sum);
3961 }
3962 
3963 int
3964 ql_minidump_init(qla_host_t *ha)
3965 {
3966 	int		ret = 0;
3967 	uint32_t	template_size = 0;
3968 	device_t	dev = ha->pci_dev;
3969 
3970 	/*
3971 	 * Get Minidump Template Size
3972  	 */
3973 	ret = qla_get_minidump_tmplt_size(ha, &template_size);
3974 
3975 	if (ret || (template_size == 0)) {
3976 		device_printf(dev, "%s: failed [%d, %d]\n", __func__, ret,
3977 			template_size);
3978 		return (-1);
3979 	}
3980 
3981 	/*
3982 	 * Allocate Memory for Minidump Template
3983 	 */
3984 
3985 	ha->hw.dma_buf.minidump.alignment = 8;
3986 	ha->hw.dma_buf.minidump.size = template_size;
3987 
3988 #ifdef QL_LDFLASH_FW
3989 	if (ql_alloc_dmabuf(ha, &ha->hw.dma_buf.minidump)) {
3990 
3991 		device_printf(dev, "%s: minidump dma alloc failed\n", __func__);
3992 
3993 		return (-1);
3994 	}
3995 	ha->hw.dma_buf.flags.minidump = 1;
3996 
3997 	/*
3998 	 * Retrieve Minidump Template
3999 	 */
4000 	ret = ql_get_minidump_template(ha);
4001 #else
4002 	ha->hw.dma_buf.minidump.dma_b = ql83xx_minidump;
4003 
4004 #endif /* #ifdef QL_LDFLASH_FW */
4005 
4006 	if (ret == 0) {
4007 
4008 		ret = ql_validate_minidump_checksum(ha);
4009 
4010 		if (ret == 0) {
4011 
4012 			ret = ql_alloc_minidump_buffers(ha);
4013 
4014 			if (ret == 0)
4015 		ha->hw.mdump_init = 1;
4016 			else
4017 				device_printf(dev,
4018 					"%s: ql_alloc_minidump_buffers"
4019 					" failed\n", __func__);
4020 		} else {
4021 			device_printf(dev, "%s: ql_validate_minidump_checksum"
4022 				" failed\n", __func__);
4023 		}
4024 	} else {
4025 		device_printf(dev, "%s: ql_get_minidump_template failed\n",
4026 			 __func__);
4027 	}
4028 
4029 	if (ret)
4030 		ql_minidump_free(ha);
4031 
4032 	return (ret);
4033 }
4034 
4035 static void
4036 ql_minidump_free(qla_host_t *ha)
4037 {
4038 	ha->hw.mdump_init = 0;
4039 	if (ha->hw.dma_buf.flags.minidump) {
4040 		ha->hw.dma_buf.flags.minidump = 0;
4041 		ql_free_dmabuf(ha, &ha->hw.dma_buf.minidump);
4042 	}
4043 
4044 	ql_free_minidump_template_buffer(ha);
4045 	ql_free_minidump_buffer(ha);
4046 
4047 	return;
4048 }
4049 
4050 void
4051 ql_minidump(qla_host_t *ha)
4052 {
4053 	if (!ha->hw.mdump_init)
4054 		return;
4055 
4056 	if (ha->hw.mdump_done)
4057 		return;
4058 
4059 		ha->hw.mdump_start_seq_index = ql_stop_sequence(ha);
4060 
4061 	bzero(ha->hw.mdump_buffer, ha->hw.mdump_buffer_size);
4062 	bzero(ha->hw.mdump_template, ha->hw.mdump_template_size);
4063 
4064 	bcopy(ha->hw.dma_buf.minidump.dma_b, ha->hw.mdump_template,
4065 		ha->hw.mdump_template_size);
4066 
4067 	ql_parse_template(ha);
4068 
4069 	ql_start_sequence(ha, ha->hw.mdump_start_seq_index);
4070 
4071 	ha->hw.mdump_done = 1;
4072 
4073 	return;
4074 }
4075 
4076 
4077 /*
4078  * helper routines
4079  */
4080 static void
4081 ql_entry_err_chk(ql_minidump_entry_t *entry, uint32_t esize)
4082 {
4083 	if (esize != entry->hdr.entry_capture_size) {
4084 		entry->hdr.entry_capture_size = esize;
4085 		entry->hdr.driver_flags |= QL_DBG_SIZE_ERR_FLAG;
4086 	}
4087 	return;
4088 }
4089 
4090 
4091 static int
4092 ql_parse_template(qla_host_t *ha)
4093 {
4094 	uint32_t num_of_entries, buff_level, e_cnt, esize;
4095 	uint32_t end_cnt, rv = 0;
4096 	char *dump_buff, *dbuff;
4097 	int sane_start = 0, sane_end = 0;
4098 	ql_minidump_template_hdr_t *template_hdr;
4099 	ql_minidump_entry_t *entry;
4100 	uint32_t capture_mask;
4101 	uint32_t dump_size;
4102 
4103 	/* Setup parameters */
4104 	template_hdr = (ql_minidump_template_hdr_t *)ha->hw.mdump_template;
4105 
4106 	if (template_hdr->entry_type == TLHDR)
4107 		sane_start = 1;
4108 
4109 	dump_buff = (char *) ha->hw.mdump_buffer;
4110 
4111 	num_of_entries = template_hdr->num_of_entries;
4112 
4113 	entry = (ql_minidump_entry_t *) ((char *)template_hdr
4114 			+ template_hdr->first_entry_offset );
4115 
4116 	template_hdr->saved_state_array[QL_OCM0_ADDR_INDX] =
4117 		template_hdr->ocm_window_array[ha->pci_func];
4118 	template_hdr->saved_state_array[QL_PCIE_FUNC_INDX] = ha->pci_func;
4119 
4120 	capture_mask = ha->hw.mdump_capture_mask;
4121 	dump_size = ha->hw.mdump_buffer_size;
4122 
4123 	template_hdr->driver_capture_mask = capture_mask;
4124 
4125 	QL_DPRINT80(ha, (ha->pci_dev,
4126 		"%s: sane_start = %d num_of_entries = %d "
4127 		"capture_mask = 0x%x dump_size = %d \n",
4128 		__func__, sane_start, num_of_entries, capture_mask, dump_size));
4129 
4130 	for (buff_level = 0, e_cnt = 0; e_cnt < num_of_entries; e_cnt++) {
4131 
4132 		/*
4133 		 * If the capture_mask of the entry does not match capture mask
4134 		 * skip the entry after marking the driver_flags indicator.
4135 		 */
4136 
4137 		if (!(entry->hdr.entry_capture_mask & capture_mask)) {
4138 
4139 			entry->hdr.driver_flags |= QL_DBG_SKIPPED_FLAG;
4140 			entry = (ql_minidump_entry_t *) ((char *) entry
4141 					+ entry->hdr.entry_size);
4142 			continue;
4143 		}
4144 
4145 		/*
4146 		 * This is ONLY needed in implementations where
4147 		 * the capture buffer allocated is too small to capture
4148 		 * all of the required entries for a given capture mask.
4149 		 * We need to empty the buffer contents to a file
4150 		 * if possible, before processing the next entry
4151 		 * If the buff_full_flag is set, no further capture will happen
4152 		 * and all remaining non-control entries will be skipped.
4153 		 */
4154 		if (entry->hdr.entry_capture_size != 0) {
4155 			if ((buff_level + entry->hdr.entry_capture_size) >
4156 				dump_size) {
4157 				/*  Try to recover by emptying buffer to file */
4158 				entry->hdr.driver_flags |= QL_DBG_SKIPPED_FLAG;
4159 				entry = (ql_minidump_entry_t *) ((char *) entry
4160 						+ entry->hdr.entry_size);
4161 				continue;
4162 			}
4163 		}
4164 
4165 		/*
4166 		 * Decode the entry type and process it accordingly
4167 		 */
4168 
4169 		switch (entry->hdr.entry_type) {
4170 		case RDNOP:
4171 			break;
4172 
4173 		case RDEND:
4174 			if (sane_end == 0) {
4175 				end_cnt = e_cnt;
4176 			}
4177 			sane_end++;
4178 			break;
4179 
4180 		case RDCRB:
4181 			dbuff = dump_buff + buff_level;
4182 			esize = ql_rdcrb(ha, (void *)entry, (void *)dbuff);
4183 			ql_entry_err_chk(entry, esize);
4184 			buff_level += esize;
4185 			break;
4186 
4187                 case POLLRD:
4188                         dbuff = dump_buff + buff_level;
4189                         esize = ql_pollrd(ha, (void *)entry, (void *)dbuff);
4190                         ql_entry_err_chk(entry, esize);
4191                         buff_level += esize;
4192                         break;
4193 
4194                 case POLLRDMWR:
4195                         dbuff = dump_buff + buff_level;
4196                         esize = ql_pollrd_modify_write(ha, (void *)entry,
4197 					(void *)dbuff);
4198                         ql_entry_err_chk(entry, esize);
4199                         buff_level += esize;
4200                         break;
4201 
4202 		case L2ITG:
4203 		case L2DTG:
4204 		case L2DAT:
4205 		case L2INS:
4206 			dbuff = dump_buff + buff_level;
4207 			esize = ql_L2Cache(ha, (void *)entry, (void *)dbuff);
4208 			if (esize == -1) {
4209 				entry->hdr.driver_flags |= QL_DBG_SKIPPED_FLAG;
4210 			} else {
4211 				ql_entry_err_chk(entry, esize);
4212 				buff_level += esize;
4213 			}
4214 			break;
4215 
4216 		case L1DAT:
4217 		case L1INS:
4218 			dbuff = dump_buff + buff_level;
4219 			esize = ql_L1Cache(ha, (void *)entry, (void *)dbuff);
4220 			ql_entry_err_chk(entry, esize);
4221 			buff_level += esize;
4222 			break;
4223 
4224 		case RDOCM:
4225 			dbuff = dump_buff + buff_level;
4226 			esize = ql_rdocm(ha, (void *)entry, (void *)dbuff);
4227 			ql_entry_err_chk(entry, esize);
4228 			buff_level += esize;
4229 			break;
4230 
4231 		case RDMEM:
4232 			dbuff = dump_buff + buff_level;
4233 			esize = ql_rdmem(ha, (void *)entry, (void *)dbuff);
4234 			ql_entry_err_chk(entry, esize);
4235 			buff_level += esize;
4236 			break;
4237 
4238 		case BOARD:
4239 		case RDROM:
4240 			dbuff = dump_buff + buff_level;
4241 			esize = ql_rdrom(ha, (void *)entry, (void *)dbuff);
4242 			ql_entry_err_chk(entry, esize);
4243 			buff_level += esize;
4244 			break;
4245 
4246 		case RDMUX:
4247 			dbuff = dump_buff + buff_level;
4248 			esize = ql_rdmux(ha, (void *)entry, (void *)dbuff);
4249 			ql_entry_err_chk(entry, esize);
4250 			buff_level += esize;
4251 			break;
4252 
4253                 case RDMUX2:
4254                         dbuff = dump_buff + buff_level;
4255                         esize = ql_rdmux2(ha, (void *)entry, (void *)dbuff);
4256                         ql_entry_err_chk(entry, esize);
4257                         buff_level += esize;
4258                         break;
4259 
4260 		case QUEUE:
4261 			dbuff = dump_buff + buff_level;
4262 			esize = ql_rdqueue(ha, (void *)entry, (void *)dbuff);
4263 			ql_entry_err_chk(entry, esize);
4264 			buff_level += esize;
4265 			break;
4266 
4267 		case CNTRL:
4268 			if ((rv = ql_cntrl(ha, template_hdr, (void *)entry))) {
4269 				entry->hdr.driver_flags |= QL_DBG_SKIPPED_FLAG;
4270 			}
4271 			break;
4272 		default:
4273 			entry->hdr.driver_flags |= QL_DBG_SKIPPED_FLAG;
4274 			break;
4275 		}
4276 		/*  next entry in the template */
4277 		entry = (ql_minidump_entry_t *) ((char *) entry
4278 						+ entry->hdr.entry_size);
4279 	}
4280 
4281 	if (!sane_start || (sane_end > 1)) {
4282 		device_printf(ha->pci_dev,
4283 			"\n%s: Template configuration error. Check Template\n",
4284 			__func__);
4285 	}
4286 
4287 	QL_DPRINT80(ha, (ha->pci_dev, "%s: Minidump num of entries = %d\n",
4288 		__func__, template_hdr->num_of_entries));
4289 
4290 	return 0;
4291 }
4292 
4293 /*
4294  * Read CRB operation.
4295  */
4296 static uint32_t
4297 ql_rdcrb(qla_host_t *ha, ql_minidump_entry_rdcrb_t * crb_entry,
4298 	uint32_t * data_buff)
4299 {
4300 	int loop_cnt;
4301 	int ret;
4302 	uint32_t op_count, addr, stride, value = 0;
4303 
4304 	addr = crb_entry->addr;
4305 	op_count = crb_entry->op_count;
4306 	stride = crb_entry->addr_stride;
4307 
4308 	for (loop_cnt = 0; loop_cnt < op_count; loop_cnt++) {
4309 
4310 		ret = ql_rdwr_indreg32(ha, addr, &value, 1);
4311 
4312 		if (ret)
4313 			return (0);
4314 
4315 		*data_buff++ = addr;
4316 		*data_buff++ = value;
4317 		addr = addr + stride;
4318 	}
4319 
4320 	/*
4321 	 * for testing purpose we return amount of data written
4322 	 */
4323 	return (op_count * (2 * sizeof(uint32_t)));
4324 }
4325 
4326 /*
4327  * Handle L2 Cache.
4328  */
4329 
4330 static uint32_t
4331 ql_L2Cache(qla_host_t *ha, ql_minidump_entry_cache_t *cacheEntry,
4332 	uint32_t * data_buff)
4333 {
4334 	int i, k;
4335 	int loop_cnt;
4336 	int ret;
4337 
4338 	uint32_t read_value;
4339 	uint32_t addr, read_addr, cntrl_addr, tag_reg_addr, cntl_value_w;
4340 	uint32_t tag_value, read_cnt;
4341 	volatile uint8_t cntl_value_r;
4342 	long timeout;
4343 	uint32_t data;
4344 
4345 	loop_cnt = cacheEntry->op_count;
4346 
4347 	read_addr = cacheEntry->read_addr;
4348 	cntrl_addr = cacheEntry->control_addr;
4349 	cntl_value_w = (uint32_t) cacheEntry->write_value;
4350 
4351 	tag_reg_addr = cacheEntry->tag_reg_addr;
4352 
4353 	tag_value = cacheEntry->init_tag_value;
4354 	read_cnt = cacheEntry->read_addr_cnt;
4355 
4356 	for (i = 0; i < loop_cnt; i++) {
4357 
4358 		ret = ql_rdwr_indreg32(ha, tag_reg_addr, &tag_value, 0);
4359 		if (ret)
4360 			return (0);
4361 
4362 		if (cacheEntry->write_value != 0) {
4363 
4364 			ret = ql_rdwr_indreg32(ha, cntrl_addr,
4365 					&cntl_value_w, 0);
4366 			if (ret)
4367 				return (0);
4368 		}
4369 
4370 		if (cacheEntry->poll_mask != 0) {
4371 
4372 			timeout = cacheEntry->poll_wait;
4373 
4374 			ret = ql_rdwr_indreg32(ha, cntrl_addr, &data, 1);
4375 			if (ret)
4376 				return (0);
4377 
4378 			cntl_value_r = (uint8_t)data;
4379 
4380 			while ((cntl_value_r & cacheEntry->poll_mask) != 0) {
4381 
4382 				if (timeout) {
4383 					qla_mdelay(__func__, 1);
4384 					timeout--;
4385 				} else
4386 					break;
4387 
4388 				ret = ql_rdwr_indreg32(ha, cntrl_addr,
4389 						&data, 1);
4390 				if (ret)
4391 					return (0);
4392 
4393 				cntl_value_r = (uint8_t)data;
4394 			}
4395 			if (!timeout) {
4396 				/* Report timeout error.
4397 				 * core dump capture failed
4398 				 * Skip remaining entries.
4399 				 * Write buffer out to file
4400 				 * Use driver specific fields in template header
4401 				 * to report this error.
4402 				 */
4403 				return (-1);
4404 			}
4405 		}
4406 
4407 		addr = read_addr;
4408 		for (k = 0; k < read_cnt; k++) {
4409 
4410 			ret = ql_rdwr_indreg32(ha, addr, &read_value, 1);
4411 			if (ret)
4412 				return (0);
4413 
4414 			*data_buff++ = read_value;
4415 			addr += cacheEntry->read_addr_stride;
4416 		}
4417 
4418 		tag_value += cacheEntry->tag_value_stride;
4419 	}
4420 
4421 	return (read_cnt * loop_cnt * sizeof(uint32_t));
4422 }
4423 
4424 /*
4425  * Handle L1 Cache.
4426  */
4427 
4428 static uint32_t
4429 ql_L1Cache(qla_host_t *ha,
4430 	ql_minidump_entry_cache_t *cacheEntry,
4431 	uint32_t *data_buff)
4432 {
4433 	int ret;
4434 	int i, k;
4435 	int loop_cnt;
4436 
4437 	uint32_t read_value;
4438 	uint32_t addr, read_addr, cntrl_addr, tag_reg_addr;
4439 	uint32_t tag_value, read_cnt;
4440 	uint32_t cntl_value_w;
4441 
4442 	loop_cnt = cacheEntry->op_count;
4443 
4444 	read_addr = cacheEntry->read_addr;
4445 	cntrl_addr = cacheEntry->control_addr;
4446 	cntl_value_w = (uint32_t) cacheEntry->write_value;
4447 
4448 	tag_reg_addr = cacheEntry->tag_reg_addr;
4449 
4450 	tag_value = cacheEntry->init_tag_value;
4451 	read_cnt = cacheEntry->read_addr_cnt;
4452 
4453 	for (i = 0; i < loop_cnt; i++) {
4454 
4455 		ret = ql_rdwr_indreg32(ha, tag_reg_addr, &tag_value, 0);
4456 		if (ret)
4457 			return (0);
4458 
4459 		ret = ql_rdwr_indreg32(ha, cntrl_addr, &cntl_value_w, 0);
4460 		if (ret)
4461 			return (0);
4462 
4463 		addr = read_addr;
4464 		for (k = 0; k < read_cnt; k++) {
4465 
4466 			ret = ql_rdwr_indreg32(ha, addr, &read_value, 1);
4467 			if (ret)
4468 				return (0);
4469 
4470 			*data_buff++ = read_value;
4471 			addr += cacheEntry->read_addr_stride;
4472 		}
4473 
4474 		tag_value += cacheEntry->tag_value_stride;
4475 	}
4476 
4477 	return (read_cnt * loop_cnt * sizeof(uint32_t));
4478 }
4479 
4480 /*
4481  * Reading OCM memory
4482  */
4483 
4484 static uint32_t
4485 ql_rdocm(qla_host_t *ha,
4486 	ql_minidump_entry_rdocm_t *ocmEntry,
4487 	uint32_t *data_buff)
4488 {
4489 	int i, loop_cnt;
4490 	volatile uint32_t addr;
4491 	volatile uint32_t value;
4492 
4493 	addr = ocmEntry->read_addr;
4494 	loop_cnt = ocmEntry->op_count;
4495 
4496 	for (i = 0; i < loop_cnt; i++) {
4497 		value = READ_REG32(ha, addr);
4498 		*data_buff++ = value;
4499 		addr += ocmEntry->read_addr_stride;
4500 	}
4501 	return (loop_cnt * sizeof(value));
4502 }
4503 
4504 /*
4505  * Read memory
4506  */
4507 
4508 static uint32_t
4509 ql_rdmem(qla_host_t *ha,
4510 	ql_minidump_entry_rdmem_t *mem_entry,
4511 	uint32_t *data_buff)
4512 {
4513 	int ret;
4514         int i, loop_cnt;
4515         volatile uint32_t addr;
4516 	q80_offchip_mem_val_t val;
4517 
4518         addr = mem_entry->read_addr;
4519 
4520 	/* size in bytes / 16 */
4521         loop_cnt = mem_entry->read_data_size / (sizeof(uint32_t) * 4);
4522 
4523         for (i = 0; i < loop_cnt; i++) {
4524 
4525 		ret = ql_rdwr_offchip_mem(ha, (addr & 0x0ffffffff), &val, 1);
4526 		if (ret)
4527 			return (0);
4528 
4529                 *data_buff++ = val.data_lo;
4530                 *data_buff++ = val.data_hi;
4531                 *data_buff++ = val.data_ulo;
4532                 *data_buff++ = val.data_uhi;
4533 
4534                 addr += (sizeof(uint32_t) * 4);
4535         }
4536 
4537         return (loop_cnt * (sizeof(uint32_t) * 4));
4538 }
4539 
4540 /*
4541  * Read Rom
4542  */
4543 
4544 static uint32_t
4545 ql_rdrom(qla_host_t *ha,
4546 	ql_minidump_entry_rdrom_t *romEntry,
4547 	uint32_t *data_buff)
4548 {
4549 	int ret;
4550 	int i, loop_cnt;
4551 	uint32_t addr;
4552 	uint32_t value;
4553 
4554 	addr = romEntry->read_addr;
4555 	loop_cnt = romEntry->read_data_size; /* This is size in bytes */
4556 	loop_cnt /= sizeof(value);
4557 
4558 	for (i = 0; i < loop_cnt; i++) {
4559 
4560 		ret = ql_rd_flash32(ha, addr, &value);
4561 		if (ret)
4562 			return (0);
4563 
4564 		*data_buff++ = value;
4565 		addr += sizeof(value);
4566 	}
4567 
4568 	return (loop_cnt * sizeof(value));
4569 }
4570 
4571 /*
4572  * Read MUX data
4573  */
4574 
4575 static uint32_t
4576 ql_rdmux(qla_host_t *ha,
4577 	ql_minidump_entry_mux_t *muxEntry,
4578 	uint32_t *data_buff)
4579 {
4580 	int ret;
4581 	int loop_cnt;
4582 	uint32_t read_value, sel_value;
4583 	uint32_t read_addr, select_addr;
4584 
4585 	select_addr = muxEntry->select_addr;
4586 	sel_value = muxEntry->select_value;
4587 	read_addr = muxEntry->read_addr;
4588 
4589 	for (loop_cnt = 0; loop_cnt < muxEntry->op_count; loop_cnt++) {
4590 
4591 		ret = ql_rdwr_indreg32(ha, select_addr, &sel_value, 0);
4592 		if (ret)
4593 			return (0);
4594 
4595 		ret = ql_rdwr_indreg32(ha, read_addr, &read_value, 1);
4596 		if (ret)
4597 			return (0);
4598 
4599 		*data_buff++ = sel_value;
4600 		*data_buff++ = read_value;
4601 
4602 		sel_value += muxEntry->select_value_stride;
4603 	}
4604 
4605 	return (loop_cnt * (2 * sizeof(uint32_t)));
4606 }
4607 
4608 static uint32_t
4609 ql_rdmux2(qla_host_t *ha,
4610 	ql_minidump_entry_mux2_t *muxEntry,
4611 	uint32_t *data_buff)
4612 {
4613 	int ret;
4614         int loop_cnt;
4615 
4616         uint32_t select_addr_1, select_addr_2;
4617         uint32_t select_value_1, select_value_2;
4618         uint32_t select_value_count, select_value_mask;
4619         uint32_t read_addr, read_value;
4620 
4621         select_addr_1 = muxEntry->select_addr_1;
4622         select_addr_2 = muxEntry->select_addr_2;
4623         select_value_1 = muxEntry->select_value_1;
4624         select_value_2 = muxEntry->select_value_2;
4625         select_value_count = muxEntry->select_value_count;
4626         select_value_mask  = muxEntry->select_value_mask;
4627 
4628         read_addr = muxEntry->read_addr;
4629 
4630         for (loop_cnt = 0; loop_cnt < muxEntry->select_value_count;
4631 		loop_cnt++) {
4632 
4633                 uint32_t temp_sel_val;
4634 
4635 		ret = ql_rdwr_indreg32(ha, select_addr_1, &select_value_1, 0);
4636 		if (ret)
4637 			return (0);
4638 
4639                 temp_sel_val = select_value_1 & select_value_mask;
4640 
4641 		ret = ql_rdwr_indreg32(ha, select_addr_2, &temp_sel_val, 0);
4642 		if (ret)
4643 			return (0);
4644 
4645 		ret = ql_rdwr_indreg32(ha, read_addr, &read_value, 1);
4646 		if (ret)
4647 			return (0);
4648 
4649                 *data_buff++ = temp_sel_val;
4650                 *data_buff++ = read_value;
4651 
4652 		ret = ql_rdwr_indreg32(ha, select_addr_1, &select_value_2, 0);
4653 		if (ret)
4654 			return (0);
4655 
4656                 temp_sel_val = select_value_2 & select_value_mask;
4657 
4658 		ret = ql_rdwr_indreg32(ha, select_addr_2, &temp_sel_val, 0);
4659 		if (ret)
4660 			return (0);
4661 
4662 		ret = ql_rdwr_indreg32(ha, read_addr, &read_value, 1);
4663 		if (ret)
4664 			return (0);
4665 
4666                 *data_buff++ = temp_sel_val;
4667                 *data_buff++ = read_value;
4668 
4669                 select_value_1 += muxEntry->select_value_stride;
4670                 select_value_2 += muxEntry->select_value_stride;
4671         }
4672 
4673         return (loop_cnt * (4 * sizeof(uint32_t)));
4674 }
4675 
4676 /*
4677  * Handling Queue State Reads.
4678  */
4679 
4680 static uint32_t
4681 ql_rdqueue(qla_host_t *ha,
4682 	ql_minidump_entry_queue_t *queueEntry,
4683 	uint32_t *data_buff)
4684 {
4685 	int ret;
4686 	int loop_cnt, k;
4687 	uint32_t read_value;
4688 	uint32_t read_addr, read_stride, select_addr;
4689 	uint32_t queue_id, read_cnt;
4690 
4691 	read_cnt = queueEntry->read_addr_cnt;
4692 	read_stride = queueEntry->read_addr_stride;
4693 	select_addr = queueEntry->select_addr;
4694 
4695 	for (loop_cnt = 0, queue_id = 0; loop_cnt < queueEntry->op_count;
4696 		loop_cnt++) {
4697 
4698 		ret = ql_rdwr_indreg32(ha, select_addr, &queue_id, 0);
4699 		if (ret)
4700 			return (0);
4701 
4702 		read_addr = queueEntry->read_addr;
4703 
4704 		for (k = 0; k < read_cnt; k++) {
4705 
4706 			ret = ql_rdwr_indreg32(ha, read_addr, &read_value, 1);
4707 			if (ret)
4708 				return (0);
4709 
4710 			*data_buff++ = read_value;
4711 			read_addr += read_stride;
4712 		}
4713 
4714 		queue_id += queueEntry->queue_id_stride;
4715 	}
4716 
4717 	return (loop_cnt * (read_cnt * sizeof(uint32_t)));
4718 }
4719 
4720 /*
4721  * Handling control entries.
4722  */
4723 
4724 static uint32_t
4725 ql_cntrl(qla_host_t *ha,
4726 	ql_minidump_template_hdr_t *template_hdr,
4727 	ql_minidump_entry_cntrl_t *crbEntry)
4728 {
4729 	int ret;
4730 	int count;
4731 	uint32_t opcode, read_value, addr, entry_addr;
4732 	long timeout;
4733 
4734 	entry_addr = crbEntry->addr;
4735 
4736 	for (count = 0; count < crbEntry->op_count; count++) {
4737 		opcode = crbEntry->opcode;
4738 
4739 		if (opcode & QL_DBG_OPCODE_WR) {
4740 
4741                 	ret = ql_rdwr_indreg32(ha, entry_addr,
4742 					&crbEntry->value_1, 0);
4743 			if (ret)
4744 				return (0);
4745 
4746 			opcode &= ~QL_DBG_OPCODE_WR;
4747 		}
4748 
4749 		if (opcode & QL_DBG_OPCODE_RW) {
4750 
4751                 	ret = ql_rdwr_indreg32(ha, entry_addr, &read_value, 1);
4752 			if (ret)
4753 				return (0);
4754 
4755                 	ret = ql_rdwr_indreg32(ha, entry_addr, &read_value, 0);
4756 			if (ret)
4757 				return (0);
4758 
4759 			opcode &= ~QL_DBG_OPCODE_RW;
4760 		}
4761 
4762 		if (opcode & QL_DBG_OPCODE_AND) {
4763 
4764                 	ret = ql_rdwr_indreg32(ha, entry_addr, &read_value, 1);
4765 			if (ret)
4766 				return (0);
4767 
4768 			read_value &= crbEntry->value_2;
4769 			opcode &= ~QL_DBG_OPCODE_AND;
4770 
4771 			if (opcode & QL_DBG_OPCODE_OR) {
4772 				read_value |= crbEntry->value_3;
4773 				opcode &= ~QL_DBG_OPCODE_OR;
4774 			}
4775 
4776                 	ret = ql_rdwr_indreg32(ha, entry_addr, &read_value, 0);
4777 			if (ret)
4778 				return (0);
4779 		}
4780 
4781 		if (opcode & QL_DBG_OPCODE_OR) {
4782 
4783                 	ret = ql_rdwr_indreg32(ha, entry_addr, &read_value, 1);
4784 			if (ret)
4785 				return (0);
4786 
4787 			read_value |= crbEntry->value_3;
4788 
4789                 	ret = ql_rdwr_indreg32(ha, entry_addr, &read_value, 0);
4790 			if (ret)
4791 				return (0);
4792 
4793 			opcode &= ~QL_DBG_OPCODE_OR;
4794 		}
4795 
4796 		if (opcode & QL_DBG_OPCODE_POLL) {
4797 
4798 			opcode &= ~QL_DBG_OPCODE_POLL;
4799 			timeout = crbEntry->poll_timeout;
4800 			addr = entry_addr;
4801 
4802                 	ret = ql_rdwr_indreg32(ha, addr, &read_value, 1);
4803 			if (ret)
4804 				return (0);
4805 
4806 			while ((read_value & crbEntry->value_2)
4807 				!= crbEntry->value_1) {
4808 
4809 				if (timeout) {
4810 					qla_mdelay(__func__, 1);
4811 					timeout--;
4812 				} else
4813 					break;
4814 
4815                 		ret = ql_rdwr_indreg32(ha, addr,
4816 						&read_value, 1);
4817 				if (ret)
4818 					return (0);
4819 			}
4820 
4821 			if (!timeout) {
4822 				/*
4823 				 * Report timeout error.
4824 				 * core dump capture failed
4825 				 * Skip remaining entries.
4826 				 * Write buffer out to file
4827 				 * Use driver specific fields in template header
4828 				 * to report this error.
4829 				 */
4830 				return (-1);
4831 			}
4832 		}
4833 
4834 		if (opcode & QL_DBG_OPCODE_RDSTATE) {
4835 			/*
4836 			 * decide which address to use.
4837 			 */
4838 			if (crbEntry->state_index_a) {
4839 				addr = template_hdr->saved_state_array[
4840 						crbEntry-> state_index_a];
4841 			} else {
4842 				addr = entry_addr;
4843 			}
4844 
4845                 	ret = ql_rdwr_indreg32(ha, addr, &read_value, 1);
4846 			if (ret)
4847 				return (0);
4848 
4849 			template_hdr->saved_state_array[crbEntry->state_index_v]
4850 					= read_value;
4851 			opcode &= ~QL_DBG_OPCODE_RDSTATE;
4852 		}
4853 
4854 		if (opcode & QL_DBG_OPCODE_WRSTATE) {
4855 			/*
4856 			 * decide which value to use.
4857 			 */
4858 			if (crbEntry->state_index_v) {
4859 				read_value = template_hdr->saved_state_array[
4860 						crbEntry->state_index_v];
4861 			} else {
4862 				read_value = crbEntry->value_1;
4863 			}
4864 			/*
4865 			 * decide which address to use.
4866 			 */
4867 			if (crbEntry->state_index_a) {
4868 				addr = template_hdr->saved_state_array[
4869 						crbEntry-> state_index_a];
4870 			} else {
4871 				addr = entry_addr;
4872 			}
4873 
4874                 	ret = ql_rdwr_indreg32(ha, addr, &read_value, 0);
4875 			if (ret)
4876 				return (0);
4877 
4878 			opcode &= ~QL_DBG_OPCODE_WRSTATE;
4879 		}
4880 
4881 		if (opcode & QL_DBG_OPCODE_MDSTATE) {
4882 			/*  Read value from saved state using index */
4883 			read_value = template_hdr->saved_state_array[
4884 						crbEntry->state_index_v];
4885 
4886 			read_value <<= crbEntry->shl; /*Shift left operation */
4887 			read_value >>= crbEntry->shr; /*Shift right operation */
4888 
4889 			if (crbEntry->value_2) {
4890 				/* check if AND mask is provided */
4891 				read_value &= crbEntry->value_2;
4892 			}
4893 
4894 			read_value |= crbEntry->value_3; /* OR operation */
4895 			read_value += crbEntry->value_1; /* increment op */
4896 
4897 			/* Write value back to state area. */
4898 
4899 			template_hdr->saved_state_array[crbEntry->state_index_v]
4900 					= read_value;
4901 			opcode &= ~QL_DBG_OPCODE_MDSTATE;
4902 		}
4903 
4904 		entry_addr += crbEntry->addr_stride;
4905 	}
4906 
4907 	return (0);
4908 }
4909 
4910 /*
4911  * Handling rd poll entry.
4912  */
4913 
4914 static uint32_t
4915 ql_pollrd(qla_host_t *ha, ql_minidump_entry_pollrd_t *entry,
4916 	uint32_t *data_buff)
4917 {
4918         int ret;
4919         int loop_cnt;
4920         uint32_t op_count, select_addr, select_value_stride, select_value;
4921         uint32_t read_addr, poll, mask, data_size, data;
4922         uint32_t wait_count = 0;
4923 
4924         select_addr            = entry->select_addr;
4925         read_addr              = entry->read_addr;
4926         select_value           = entry->select_value;
4927         select_value_stride    = entry->select_value_stride;
4928         op_count               = entry->op_count;
4929         poll                   = entry->poll;
4930         mask                   = entry->mask;
4931         data_size              = entry->data_size;
4932 
4933         for (loop_cnt = 0; loop_cnt < op_count; loop_cnt++) {
4934 
4935                 ret = ql_rdwr_indreg32(ha, select_addr, &select_value, 0);
4936 		if (ret)
4937 			return (0);
4938 
4939                 wait_count = 0;
4940 
4941                 while (wait_count < poll) {
4942 
4943                         uint32_t temp;
4944 
4945 			ret = ql_rdwr_indreg32(ha, select_addr, &temp, 1);
4946 			if (ret)
4947 				return (0);
4948 
4949                         if ( (temp & mask) != 0 ) {
4950                                 break;
4951                         }
4952                         wait_count++;
4953                 }
4954 
4955                 if (wait_count == poll) {
4956                         device_printf(ha->pci_dev,
4957 				"%s: Error in processing entry\n", __func__);
4958                         device_printf(ha->pci_dev,
4959 				"%s: wait_count <0x%x> poll <0x%x>\n",
4960 				__func__, wait_count, poll);
4961                         return 0;
4962                 }
4963 
4964 		ret = ql_rdwr_indreg32(ha, read_addr, &data, 1);
4965 		if (ret)
4966 			return (0);
4967 
4968                 *data_buff++ = select_value;
4969                 *data_buff++ = data;
4970                 select_value = select_value + select_value_stride;
4971         }
4972 
4973         /*
4974          * for testing purpose we return amount of data written
4975          */
4976         return (loop_cnt * (2 * sizeof(uint32_t)));
4977 }
4978 
4979 
4980 /*
4981  * Handling rd modify write poll entry.
4982  */
4983 
4984 static uint32_t
4985 ql_pollrd_modify_write(qla_host_t *ha,
4986 	ql_minidump_entry_rd_modify_wr_with_poll_t *entry,
4987 	uint32_t *data_buff)
4988 {
4989 	int ret;
4990         uint32_t addr_1, addr_2, value_1, value_2, data;
4991         uint32_t poll, mask, data_size, modify_mask;
4992         uint32_t wait_count = 0;
4993 
4994         addr_1		= entry->addr_1;
4995         addr_2		= entry->addr_2;
4996         value_1		= entry->value_1;
4997         value_2		= entry->value_2;
4998 
4999         poll		= entry->poll;
5000         mask		= entry->mask;
5001         modify_mask	= entry->modify_mask;
5002         data_size	= entry->data_size;
5003 
5004 
5005 	ret = ql_rdwr_indreg32(ha, addr_1, &value_1, 0);
5006 	if (ret)
5007 		return (0);
5008 
5009         wait_count = 0;
5010         while (wait_count < poll) {
5011 
5012 		uint32_t temp;
5013 
5014 		ret = ql_rdwr_indreg32(ha, addr_1, &temp, 1);
5015 		if (ret)
5016 			return (0);
5017 
5018                 if ( (temp & mask) != 0 ) {
5019                         break;
5020                 }
5021                 wait_count++;
5022         }
5023 
5024         if (wait_count == poll) {
5025                 device_printf(ha->pci_dev, "%s Error in processing entry\n",
5026 			__func__);
5027         } else {
5028 
5029 		ret = ql_rdwr_indreg32(ha, addr_2, &data, 1);
5030 		if (ret)
5031 			return (0);
5032 
5033                 data = (data & modify_mask);
5034 
5035 		ret = ql_rdwr_indreg32(ha, addr_2, &data, 0);
5036 		if (ret)
5037 			return (0);
5038 
5039 		ret = ql_rdwr_indreg32(ha, addr_1, &value_2, 0);
5040 		if (ret)
5041 			return (0);
5042 
5043                 /* Poll again */
5044                 wait_count = 0;
5045                 while (wait_count < poll) {
5046 
5047                         uint32_t temp;
5048 
5049 			ret = ql_rdwr_indreg32(ha, addr_1, &temp, 1);
5050 			if (ret)
5051 				return (0);
5052 
5053                         if ( (temp & mask) != 0 ) {
5054                                 break;
5055                         }
5056                         wait_count++;
5057                 }
5058                 *data_buff++ = addr_2;
5059                 *data_buff++ = data;
5060         }
5061 
5062         /*
5063          * for testing purpose we return amount of data written
5064          */
5065         return (2 * sizeof(uint32_t));
5066 }
5067 
5068 
5069