1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #include <npi_fflp.h>
27 #include <nxge_common.h>
28 
29 /* macros to compute calss configuration register offset */
30 
31 #define	  GET_TCAM_CLASS_OFFSET(cls) \
32 	(FFLP_TCAM_CLS_BASE_OFFSET + (cls - 2) * 8)
33 #define	  GET_TCAM_KEY_OFFSET(cls) \
34 	(FFLP_TCAM_KEY_BASE_OFFSET + (cls - 4) * 8)
35 #define	  GET_FLOW_KEY_OFFSET(cls) \
36 	(FFLP_FLOW_KEY_BASE_OFFSET + (cls - 4) * 8)
37 
38 #define	  HASHTBL_PART_REG_STEP 8192
39 #define	  HASHTBL_PART_REG_VIR_OFFSET 0x2100
40 #define	  HASHTBL_PART_REG_VIR_STEP 0x4000
41 #define	  GET_HASHTBL_PART_OFFSET_NVIR(partid, reg)	\
42 	((partid  * HASHTBL_PART_REG_STEP) + reg)
43 
44 #define	  GET_HASHTBL_PART_OFFSET(handle, partid, reg)	\
45 	    (handle.is_vraddr ?					\
46 	    (((partid & 0x1) * HASHTBL_PART_REG_VIR_STEP) +	\
47 	    (reg & 0x8) + (HASHTBL_PART_REG_VIR_OFFSET)) :	\
48 	    (partid * HASHTBL_PART_REG_STEP) + reg)
49 
50 #define	 FFLP_PART_OFFSET(partid, reg) ((partid  * 8) + reg)
51 #define	 FFLP_VLAN_OFFSET(vid, reg) ((vid  * 8) + reg)
52 
53 #define	 TCAM_COMPLETION_TRY_COUNT 10
54 #define	 BIT_ENABLE	0x1
55 #define	 BIT_DISABLE	0x0
56 
57 #define	 FCRAM_PARTITION_VALID(partid) \
58 	((partid < NXGE_MAX_RDC_GRPS))
59 #define	FFLP_VLAN_VALID(vid) \
60 	((vid > 0) && (vid < NXGE_MAX_VLANS))
61 #define	FFLP_PORT_VALID(port) \
62 	((port < MAX_PORTS_PER_NXGE))
63 #define	FFLP_RDC_TABLE_VALID(table) \
64 	((table < NXGE_MAX_RDC_GRPS))
65 #define	TCAM_L3_USR_CLASS_VALID(class) \
66 	((class >= TCAM_CLASS_IP_USER_4) && (class <= TCAM_CLASS_IP_USER_7))
67 #define	TCAM_L2_USR_CLASS_VALID(class) \
68 	((class == TCAM_CLASS_ETYPE_1) || (class == TCAM_CLASS_ETYPE_2))
69 #define	TCAM_L3_CLASS_VALID(class) \
70 	((class >= TCAM_CLASS_IP_USER_4) && (class <= TCAM_CLASS_SCTP_IPV6))
71 #define	TCAM_L3_CLASS_VALID_RFNL(class) \
72 	((TCAM_L3_CLASS_VALID(class)) || class == TCAM_CLASS_IPV6_FRAG)
73 #define	TCAM_CLASS_VALID(class) \
74 	((class >= TCAM_CLASS_ETYPE_1) && (class <= TCAM_CLASS_RARP))
75 
76 
77 uint64_t fflp_fzc_offset[] = {
78 	FFLP_ENET_VLAN_TBL_REG, FFLP_L2_CLS_ENET1_REG, FFLP_L2_CLS_ENET2_REG,
79 	FFLP_TCAM_KEY_IP_USR4_REG, FFLP_TCAM_KEY_IP_USR5_REG,
80 	FFLP_TCAM_KEY_IP_USR6_REG, FFLP_TCAM_KEY_IP_USR7_REG,
81 	FFLP_TCAM_KEY_IP4_TCP_REG, FFLP_TCAM_KEY_IP4_UDP_REG,
82 	FFLP_TCAM_KEY_IP4_AH_ESP_REG, FFLP_TCAM_KEY_IP4_SCTP_REG,
83 	FFLP_TCAM_KEY_IP6_TCP_REG, FFLP_TCAM_KEY_IP6_UDP_REG,
84 	FFLP_TCAM_KEY_IP6_AH_ESP_REG, FFLP_TCAM_KEY_IP6_SCTP_REG,
85 	FFLP_TCAM_KEY_0_REG, FFLP_TCAM_KEY_1_REG, FFLP_TCAM_KEY_2_REG,
86 	FFLP_TCAM_KEY_3_REG, FFLP_TCAM_MASK_0_REG, FFLP_TCAM_MASK_1_REG,
87 	FFLP_TCAM_MASK_2_REG, FFLP_TCAM_MASK_3_REG, FFLP_TCAM_CTL_REG,
88 	FFLP_VLAN_PAR_ERR_REG, FFLP_TCAM_ERR_REG, HASH_LKUP_ERR_LOG1_REG,
89 	HASH_LKUP_ERR_LOG2_REG, FFLP_FCRAM_ERR_TST0_REG,
90 	FFLP_FCRAM_ERR_TST1_REG, FFLP_FCRAM_ERR_TST2_REG, FFLP_ERR_MSK_REG,
91 	FFLP_CFG_1_REG, FFLP_DBG_TRAIN_VCT_REG, FFLP_TCP_CFLAG_MSK_REG,
92 	FFLP_FCRAM_REF_TMR_REG,  FFLP_FLOW_KEY_IP_USR4_REG,
93 	FFLP_FLOW_KEY_IP_USR5_REG, FFLP_FLOW_KEY_IP_USR6_REG,
94 	FFLP_FLOW_KEY_IP_USR7_REG, FFLP_FLOW_KEY_IP4_TCP_REG,
95 	FFLP_FLOW_KEY_IP4_UDP_REG, FFLP_FLOW_KEY_IP4_AH_ESP_REG,
96 	FFLP_FLOW_KEY_IP4_SCTP_REG, FFLP_FLOW_KEY_IP6_TCP_REG,
97 	FFLP_FLOW_KEY_IP6_UDP_REG, FFLP_FLOW_KEY_IP6_AH_ESP_REG,
98 	FFLP_FLOW_KEY_IP6_SCTP_REG, FFLP_H1POLY_REG, FFLP_H2POLY_REG,
99 	FFLP_FLW_PRT_SEL_REG
100 };
101 
102 const char *fflp_fzc_name[] = {
103 	"FFLP_ENET_VLAN_TBL_REG", "FFLP_L2_CLS_ENET1_REG",
104 	"FFLP_L2_CLS_ENET2_REG", "FFLP_TCAM_KEY_IP_USR4_REG",
105 	"FFLP_TCAM_KEY_IP_USR5_REG", "FFLP_TCAM_KEY_IP_USR6_REG",
106 	"FFLP_TCAM_KEY_IP_USR7_REG", "FFLP_TCAM_KEY_IP4_TCP_REG",
107 	"FFLP_TCAM_KEY_IP4_UDP_REG", "FFLP_TCAM_KEY_IP4_AH_ESP_REG",
108 	"FFLP_TCAM_KEY_IP4_SCTP_REG", "FFLP_TCAM_KEY_IP6_TCP_REG",
109 	"FFLP_TCAM_KEY_IP6_UDP_REG", "FFLP_TCAM_KEY_IP6_AH_ESP_REG",
110 	"FFLP_TCAM_KEY_IP6_SCTP_REG", "FFLP_TCAM_KEY_0_REG",
111 	"FFLP_TCAM_KEY_1_REG", "FFLP_TCAM_KEY_2_REG", "FFLP_TCAM_KEY_3_REG",
112 	"FFLP_TCAM_MASK_0_REG", "FFLP_TCAM_MASK_1_REG", "FFLP_TCAM_MASK_2_REG",
113 	"FFLP_TCAM_MASK_3_REG", "FFLP_TCAM_CTL_REG", "FFLP_VLAN_PAR_ERR_REG",
114 	"FFLP_TCAM_ERR_REG", "HASH_LKUP_ERR_LOG1_REG",
115 	"HASH_LKUP_ERR_LOG2_REG", "FFLP_FCRAM_ERR_TST0_REG",
116 	"FFLP_FCRAM_ERR_TST1_REG", "FFLP_FCRAM_ERR_TST2_REG",
117 	"FFLP_ERR_MSK_REG", "FFLP_CFG_1_REG", "FFLP_DBG_TRAIN_VCT_REG",
118 	"FFLP_TCP_CFLAG_MSK_REG", "FFLP_FCRAM_REF_TMR_REG",
119 	"FFLP_FLOW_KEY_IP_USR4_REG", "FFLP_FLOW_KEY_IP_USR5_REG",
120 	"FFLP_FLOW_KEY_IP_USR6_REG", "FFLP_FLOW_KEY_IP_USR7_REG",
121 	"FFLP_FLOW_KEY_IP4_TCP_REG", "FFLP_FLOW_KEY_IP4_UDP_REG",
122 	"FFLP_FLOW_KEY_IP4_AH_ESP_REG", "FFLP_FLOW_KEY_IP4_SCTP_REG",
123 	"FFLP_FLOW_KEY_IP6_TCP_REG", "FFLP_FLOW_KEY_IP6_UDP_REG",
124 	"FFLP_FLOW_KEY_IP6_AH_ESP_REG",
125 	"FFLP_FLOW_KEY_IP6_SCTP_REG", "FFLP_H1POLY_REG", "FFLP_H2POLY_REG",
126 	"FFLP_FLW_PRT_SEL_REG"
127 };
128 
129 uint64_t fflp_reg_offset[] = {
130 	FFLP_HASH_TBL_ADDR_REG, FFLP_HASH_TBL_DATA_REG,
131 	FFLP_HASH_TBL_DATA_LOG_REG
132 };
133 
134 const char *fflp_reg_name[] = {
135 	"FFLP_HASH_TBL_ADDR_REG", "FFLP_HASH_TBL_DATA_REG",
136 	"FFLP_HASH_TBL_DATA_LOG_REG"
137 };
138 
139 
140 
141 
142 npi_status_t
143 npi_fflp_dump_regs(npi_handle_t handle)
144 {
145 
146 	uint64_t value;
147 	int num_regs, i;
148 
149 	num_regs = sizeof (fflp_fzc_offset) / sizeof (uint64_t);
150 	NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
151 	    "\nFFLP_FZC Register Dump \n"));
152 	for (i = 0; i < num_regs; i++) {
153 		REG_PIO_READ64(handle, fflp_fzc_offset[i], &value);
154 		NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
155 		    " %8llx %s\t %8llx \n",
156 		    fflp_fzc_offset[i], fflp_fzc_name[i], value));
157 
158 	}
159 
160 	NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
161 	    "\nFFLP Register Dump\n"));
162 	num_regs = sizeof (fflp_reg_offset) / sizeof (uint64_t);
163 
164 	for (i = 0; i < num_regs; i++) {
165 		REG_PIO_READ64(handle, fflp_reg_offset[i], &value);
166 		NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
167 		    " %8llx %s\t %8llx \n",
168 		    fflp_reg_offset[i], fflp_reg_name[i], value));
169 
170 	}
171 
172 	NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
173 	    "\n FFLP Register Dump done\n"));
174 
175 	return (NPI_SUCCESS);
176 }
177 
178 void
179 npi_fflp_vlan_tbl_dump(npi_handle_t handle)
180 {
181 	uint64_t offset;
182 	vlan_id_t vlan_id;
183 	uint64_t value;
184 	vlan_id_t start = 0, stop = NXGE_MAX_VLANS;
185 
186 	NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
187 	    "\nVlan Table Dump \n"));
188 
189 	NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
190 	    "VID\t Offset\t Value\n"));
191 
192 	for (vlan_id = start; vlan_id < stop; vlan_id++) {
193 		offset = FFLP_VLAN_OFFSET(vlan_id, FFLP_ENET_VLAN_TBL_REG);
194 		REG_PIO_READ64(handle, offset, &value);
195 		NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
196 		    "%x\t %llx\t %llx\n", vlan_id, offset, value));
197 	}
198 
199 }
200 
201 static uint64_t
202 npi_fflp_tcam_check_completion(npi_handle_t handle, tcam_op_t op_type);
203 
204 /*
205  * npi_fflp_tcam_check_completion()
206  * Returns TCAM completion status.
207  *
208  * Input:
209  *           op_type :        Read, Write, Compare
210  *           handle  :        OS specific handle
211  *
212  * Output:
213  *        For Read and write operations:
214  *        0   Successful
215  *        -1  Fail/timeout
216  *
217  *       For Compare operations (debug only )
218  *        TCAM_REG_CTL read value    on success
219  *                     value contains match location
220  *        NPI_TCAM_COMP_NO_MATCH          no match
221  *
222  */
223 static uint64_t
224 npi_fflp_tcam_check_completion(npi_handle_t handle, tcam_op_t op_type)
225 {
226 
227 	uint32_t try_counter, tcam_delay = 10;
228 	tcam_ctl_t tctl;
229 
230 	try_counter = TCAM_COMPLETION_TRY_COUNT;
231 
232 	switch (op_type) {
233 	case TCAM_RWC_STAT:
234 
235 		READ_TCAM_REG_CTL(handle, &tctl.value);
236 		while ((try_counter) &&
237 		    (tctl.bits.ldw.stat != TCAM_CTL_RWC_RWC_STAT)) {
238 			try_counter--;
239 			NXGE_DELAY(tcam_delay);
240 			READ_TCAM_REG_CTL(handle, &tctl.value);
241 		}
242 
243 		if (!try_counter) {
244 			NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
245 			    " TCAM RWC_STAT operation"
246 			    " failed to complete \n"));
247 			return (NPI_FFLP_TCAM_HW_ERROR);
248 		}
249 
250 		tctl.value = 0;
251 		break;
252 
253 	case TCAM_RWC_MATCH:
254 		READ_TCAM_REG_CTL(handle, &tctl.value);
255 
256 		while ((try_counter) &&
257 		    (tctl.bits.ldw.match != TCAM_CTL_RWC_RWC_MATCH)) {
258 			try_counter--;
259 			NXGE_DELAY(tcam_delay);
260 			READ_TCAM_REG_CTL(handle, &tctl.value);
261 		}
262 
263 		if (!try_counter) {
264 			NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
265 			    " TCAM Match operation"
266 			    "failed to find match \n"));
267 			tctl.value = NPI_TCAM_COMP_NO_MATCH;
268 		}
269 
270 
271 		break;
272 
273 	default:
274 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
275 		" Invalid TCAM completion Request \n"));
276 		return (NPI_FFLP_ERROR |
277 		    NPI_TCAM_ERROR | OPCODE_INVALID);
278 	}
279 
280 	return (tctl.value);
281 }
282 
283 /*
284  * npi_fflp_tcam_entry_invalidate()
285  *
286  * invalidates entry at tcam location
287  *
288  * Input
289  * handle  :        OS specific handle
290  * location	:	TCAM location
291  *
292  * Return
293  *   NPI_SUCCESS
294  *   NPI_FFLP_TCAM_HW_ERROR
295  *
296  */
297 npi_status_t
298 npi_fflp_tcam_entry_invalidate(npi_handle_t handle, tcam_location_t location)
299 {
300 
301 	tcam_ctl_t tctl, tctl_stat;
302 
303 /*
304  * Need to write zero to class field.
305  * Class field is bits [195:191].
306  * This corresponds to TCAM key 0 register
307  *
308  */
309 
310 
311 	WRITE_TCAM_REG_MASK0(handle, 0xffULL);
312 	WRITE_TCAM_REG_KEY0(handle, 0x0ULL);
313 	tctl.value = 0;
314 	tctl.bits.ldw.location = location;
315 	tctl.bits.ldw.rwc = TCAM_CTL_RWC_TCAM_WR;
316 
317 	WRITE_TCAM_REG_CTL(handle, tctl.value);
318 
319 	tctl_stat.value = npi_fflp_tcam_check_completion(handle, TCAM_RWC_STAT);
320 
321 	if (tctl_stat.value & NPI_FAILURE)
322 		return (NPI_FFLP_TCAM_HW_ERROR);
323 
324 	return (NPI_SUCCESS);
325 
326 }
327 
328 /*
329  * npi_fflp_tcam_entry_match()
330  *
331  * lookup a tcam entry in the TCAM
332  *
333  * Input
334  * handle  :        OS specific handle
335  * tcam_ptr   :     TCAM entry ptr
336  *
337  * Return
338  *
339  *	 NPI_FAILURE | NPI_XX_ERROR:	     Operational Error (HW etc ...)
340  *	 NPI_TCAM_NO_MATCH:		     no match
341  *	 0 - TCAM_SIZE:			     matching entry location (if match)
342  */
343 int
344 npi_fflp_tcam_entry_match(npi_handle_t handle,  tcam_entry_t *tcam_ptr)
345 {
346 
347 	uint64_t tcam_stat = 0;
348 	tcam_ctl_t tctl, tctl_stat;
349 
350 	WRITE_TCAM_REG_MASK0(handle, tcam_ptr->mask0);
351 	WRITE_TCAM_REG_MASK1(handle, tcam_ptr->mask1);
352 	WRITE_TCAM_REG_MASK2(handle, tcam_ptr->mask2);
353 	WRITE_TCAM_REG_MASK3(handle, tcam_ptr->mask3);
354 
355 	WRITE_TCAM_REG_KEY0(handle, tcam_ptr->key0);
356 	WRITE_TCAM_REG_KEY1(handle, tcam_ptr->key1);
357 	WRITE_TCAM_REG_KEY2(handle, tcam_ptr->key2);
358 	WRITE_TCAM_REG_KEY3(handle, tcam_ptr->key3);
359 
360 	tctl.value = 0;
361 	tctl.bits.ldw.rwc = TCAM_CTL_RWC_TCAM_CMP;
362 
363 	WRITE_TCAM_REG_CTL(handle, tctl.value);
364 
365 	tcam_stat = npi_fflp_tcam_check_completion(handle, TCAM_RWC_STAT);
366 	if (tcam_stat & NPI_FAILURE) {
367 		return ((uint32_t)tcam_stat);
368 	}
369 
370 	tctl_stat.value = npi_fflp_tcam_check_completion(handle,
371 	    TCAM_RWC_MATCH);
372 
373 	if (tctl_stat.bits.ldw.match == TCAM_CTL_RWC_RWC_MATCH) {
374 		return (uint32_t)(tctl_stat.bits.ldw.location);
375 	}
376 
377 	return ((uint32_t)tctl_stat.value);
378 
379 }
380 
381 /*
382  * npi_fflp_tcam_entry_read ()
383  *
384  * Reads a tcam entry from the TCAM location, location
385  *
386  * Input:
387  * handle  :        OS specific handle
388  * location  :		TCAM location
389  * tcam_ptr  :		TCAM entry pointer
390  *
391  * Return:
392  * NPI_SUCCESS
393  * NPI_FFLP_TCAM_RD_ERROR
394  *
395  */
396 npi_status_t
397 npi_fflp_tcam_entry_read(npi_handle_t handle,
398 						    tcam_location_t location,
399 						    struct tcam_entry *tcam_ptr)
400 {
401 
402 	uint64_t tcam_stat;
403 	tcam_ctl_t tctl;
404 
405 	tctl.value = 0;
406 	tctl.bits.ldw.location = location;
407 	tctl.bits.ldw.rwc = TCAM_CTL_RWC_TCAM_RD;
408 
409 	WRITE_TCAM_REG_CTL(handle, tctl.value);
410 
411 	tcam_stat = npi_fflp_tcam_check_completion(handle, TCAM_RWC_STAT);
412 
413 	if (tcam_stat & NPI_FAILURE) {
414 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
415 		    "TCAM read failed loc %d \n", location));
416 		return (NPI_FFLP_TCAM_RD_ERROR);
417 	}
418 
419 	READ_TCAM_REG_MASK0(handle, &tcam_ptr->mask0);
420 	READ_TCAM_REG_MASK1(handle, &tcam_ptr->mask1);
421 	READ_TCAM_REG_MASK2(handle, &tcam_ptr->mask2);
422 	READ_TCAM_REG_MASK3(handle, &tcam_ptr->mask3);
423 
424 	READ_TCAM_REG_KEY0(handle, &tcam_ptr->key0);
425 	READ_TCAM_REG_KEY1(handle, &tcam_ptr->key1);
426 	READ_TCAM_REG_KEY2(handle, &tcam_ptr->key2);
427 	READ_TCAM_REG_KEY3(handle, &tcam_ptr->key3);
428 
429 	return (NPI_SUCCESS);
430 }
431 
432 /*
433  * npi_fflp_tcam_entry_write()
434  *
435  * writes a tcam entry to the TCAM location, location
436  *
437  * Input:
438  * handle  :        OS specific handle
439  * location :	TCAM location
440  * tcam_ptr :	TCAM entry pointer
441  *
442  * Return:
443  * NPI_SUCCESS
444  * NPI_FFLP_TCAM_WR_ERROR
445  *
446  */
447 npi_status_t
448 npi_fflp_tcam_entry_write(npi_handle_t handle,
449 			    tcam_location_t location,
450 			    tcam_entry_t *tcam_ptr)
451 {
452 
453 	uint64_t tcam_stat;
454 
455 	tcam_ctl_t tctl;
456 
457 	WRITE_TCAM_REG_MASK0(handle, tcam_ptr->mask0);
458 	WRITE_TCAM_REG_MASK1(handle, tcam_ptr->mask1);
459 	WRITE_TCAM_REG_MASK2(handle, tcam_ptr->mask2);
460 	WRITE_TCAM_REG_MASK3(handle, tcam_ptr->mask3);
461 
462 	WRITE_TCAM_REG_KEY0(handle, tcam_ptr->key0);
463 	WRITE_TCAM_REG_KEY1(handle, tcam_ptr->key1);
464 	WRITE_TCAM_REG_KEY2(handle, tcam_ptr->key2);
465 	WRITE_TCAM_REG_KEY3(handle, tcam_ptr->key3);
466 
467 	NPI_DEBUG_MSG((handle.function, NPI_FFLP_CTL,
468 	    " tcam write: location %x\n"
469 	    " key:  %llx %llx %llx %llx \n"
470 	    " mask: %llx %llx %llx %llx \n",
471 	    location, tcam_ptr->key0, tcam_ptr->key1,
472 	    tcam_ptr->key2, tcam_ptr->key3,
473 	    tcam_ptr->mask0, tcam_ptr->mask1,
474 	    tcam_ptr->mask2, tcam_ptr->mask3));
475 	tctl.value = 0;
476 	tctl.bits.ldw.location = location;
477 	tctl.bits.ldw.rwc = TCAM_CTL_RWC_TCAM_WR;
478 	NPI_DEBUG_MSG((handle.function, NPI_FFLP_CTL,
479 	    " tcam write: ctl value %llx \n", tctl.value));
480 	WRITE_TCAM_REG_CTL(handle, tctl.value);
481 
482 	tcam_stat = npi_fflp_tcam_check_completion(handle, TCAM_RWC_STAT);
483 
484 	if (tcam_stat & NPI_FAILURE) {
485 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
486 		    "TCAM Write failed loc %d \n", location));
487 		return (NPI_FFLP_TCAM_WR_ERROR);
488 	}
489 
490 	return (NPI_SUCCESS);
491 }
492 
493 /*
494  * npi_fflp_tcam_asc_ram_entry_write()
495  *
496  * writes a tcam associatedRAM at the TCAM location, location
497  *
498  * Input:
499  * handle  :        OS specific handle
500  * location :	tcam associatedRAM location
501  * ram_data :	Value to write
502  *
503  * Return:
504  * NPI_SUCCESS
505  * NPI_FFLP_ASC_RAM_WR_ERROR
506  *
507  */
508 npi_status_t
509 npi_fflp_tcam_asc_ram_entry_write(npi_handle_t handle,
510 				    tcam_location_t location,
511 				    uint64_t ram_data)
512 {
513 
514 	uint64_t tcam_stat = 0;
515 	tcam_ctl_t tctl;
516 
517 
518 	WRITE_TCAM_REG_KEY1(handle, ram_data);
519 
520 	tctl.value = 0;
521 	tctl.bits.ldw.location = location;
522 	tctl.bits.ldw.rwc = TCAM_CTL_RWC_RAM_WR;
523 
524 	NPI_DEBUG_MSG((handle.function, NPI_FFLP_CTL,
525 	    " tcam ascr write: location %x data %llx ctl value %llx \n",
526 	    location, ram_data, tctl.value));
527 	WRITE_TCAM_REG_CTL(handle, tctl.value);
528 	tcam_stat = npi_fflp_tcam_check_completion(handle, TCAM_RWC_STAT);
529 
530 	if (tcam_stat & NPI_FAILURE) {
531 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
532 		    "TCAM RAM write failed loc %d \n", location));
533 		return (NPI_FFLP_ASC_RAM_WR_ERROR);
534 	}
535 
536 	return (NPI_SUCCESS);
537 }
538 
539 /*
540  * npi_fflp_tcam_asc_ram_entry_read()
541  *
542  * reads a tcam associatedRAM content at the TCAM location, location
543  *
544  * Input:
545  * handle  :        OS specific handle
546  * location :	tcam associatedRAM location
547  * ram_data :	ptr to return contents
548  *
549  * Return:
550  * NPI_SUCCESS
551  * NPI_FFLP_ASC_RAM_RD_ERROR
552  *
553  */
554 npi_status_t
555 npi_fflp_tcam_asc_ram_entry_read(npi_handle_t handle,
556 				    tcam_location_t location,
557 				    uint64_t *ram_data)
558 {
559 
560 	uint64_t tcam_stat;
561 	tcam_ctl_t tctl;
562 
563 
564 	tctl.value = 0;
565 	tctl.bits.ldw.location = location;
566 	tctl.bits.ldw.rwc = TCAM_CTL_RWC_RAM_RD;
567 
568 	WRITE_TCAM_REG_CTL(handle, tctl.value);
569 
570 	tcam_stat = npi_fflp_tcam_check_completion(handle, TCAM_RWC_STAT);
571 
572 	if (tcam_stat & NPI_FAILURE) {
573 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
574 		    "TCAM RAM read failed loc %d \n", location));
575 		return (NPI_FFLP_ASC_RAM_RD_ERROR);
576 	}
577 
578 	READ_TCAM_REG_KEY1(handle, ram_data);
579 
580 	return (NPI_SUCCESS);
581 }
582 
583 /* FFLP FCRAM Related functions */
584 /* The following are FCRAM datapath functions */
585 
586 /*
587  * npi_fflp_fcram_entry_write ()
588  * Populates an FCRAM entry
589  * Inputs:
590  *         handle:	opaque handle interpreted by the underlying OS
591  *	   partid:	Partition ID
592  *	   location:	Index to the FCRAM.
593  *			 Corresponds to last 20 bits of H1 value
594  *	   fcram_ptr:	Pointer to the FCRAM contents to be used for writing
595  *	   format:	Entry Format. Determines the size of the write.
596  *			      FCRAM_ENTRY_OPTIM:   8 bytes (a 64 bit write)
597  *			      FCRAM_ENTRY_EX_IP4:  32 bytes (4 X 64 bit write)
598  *			      FCRAM_ENTRY_EX_IP6:  56 bytes (7 X 64 bit write)
599  *
600  * Outputs:
601  *         NPI success/failure status code
602  */
603 npi_status_t
604 npi_fflp_fcram_entry_write(npi_handle_t handle, part_id_t partid,
605 			    uint32_t location, fcram_entry_t *fcram_ptr,
606 			    fcram_entry_format_t format)
607 
608 {
609 
610 	int num_subareas = 0;
611 	uint64_t addr_reg, data_reg;
612 	int subarea;
613 	int autoinc;
614 	hash_tbl_addr_t addr;
615 	switch (format) {
616 	case FCRAM_ENTRY_OPTIM:
617 		if (location % 8) {
618 		/* need to be 8 byte alligned */
619 
620 			NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
621 				    " FCRAM_ENTRY_OOPTIM Write:"
622 				    " unaligned location %llx \n",
623 				    location));
624 
625 			return (NPI_FFLP_FCRAM_LOC_INVALID);
626 	}
627 
628 	num_subareas = 1;
629 	autoinc = 0;
630 	break;
631 
632 	case FCRAM_ENTRY_EX_IP4:
633 		if (location % 32) {
634 /* need to be 32 byte alligned */
635 			NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
636 			    " FCRAM_ENTRY_EX_IP4 Write:"
637 			    " unaligned location %llx \n",
638 			    location));
639 			return (NPI_FFLP_FCRAM_LOC_INVALID);
640 	}
641 
642 	num_subareas = 4;
643 	autoinc = 1;
644 
645 	break;
646 	case FCRAM_ENTRY_EX_IP6:
647 		if (location % 64) {
648 				/* need to be 64 byte alligned */
649 			NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
650 				    " FCRAM_ENTRY_EX_IP6 Write:"
651 				    " unaligned location %llx \n",
652 				    location));
653 				return (NPI_FFLP_FCRAM_LOC_INVALID);
654 
655 		}
656 		num_subareas = 7;
657 		autoinc = 1;
658 			break;
659 	default:
660 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
661 			    " fcram_entry_write:"
662 			    " unknown format param location %llx\n",
663 			    location));
664 		return (NPI_FFLP_ERROR | NPI_FCRAM_ERROR | OPCODE_INVALID);
665 	}
666 
667 	addr.value = 0;
668 	addr.bits.ldw.autoinc = autoinc;
669 	addr.bits.ldw.addr = location;
670 	addr_reg = GET_HASHTBL_PART_OFFSET(handle, partid,
671 					    FFLP_HASH_TBL_ADDR_REG);
672 	data_reg = GET_HASHTBL_PART_OFFSET(handle, partid,
673 					    FFLP_HASH_TBL_DATA_REG);
674 /* write to addr reg */
675 	REG_PIO_WRITE64(handle, addr_reg, addr.value);
676 /* write data to the data register */
677 
678 	for (subarea = 0; subarea < num_subareas; subarea++) {
679 		REG_PIO_WRITE64(handle, data_reg, fcram_ptr->value[subarea]);
680 	}
681 
682 	return (NPI_SUCCESS);
683 }
684 
685 /*
686  * npi_fflp_fcram_read_read ()
687  * Reads an FCRAM entry
688  * Inputs:
689  *         handle:	opaque handle interpreted by the underlying OS
690  *	   partid:	Partition ID
691  *	   location:	Index to the FCRAM.
692  *                  Corresponds to last 20 bits of H1 value
693  *
694  *	   fcram_ptr:	Pointer to the FCRAM contents to be updated
695  *	   format:	Entry Format. Determines the size of the read.
696  *			      FCRAM_ENTRY_OPTIM:   8 bytes (a 64 bit read)
697  *			      FCRAM_ENTRY_EX_IP4:  32 bytes (4 X 64 bit read )
698  *			      FCRAM_ENTRY_EX_IP6:  56 bytes (7 X 64 bit read )
699  * Return:
700  * NPI Success/Failure status code
701  *
702  */
703 npi_status_t
704 npi_fflp_fcram_entry_read(npi_handle_t handle,  part_id_t partid,
705 			    uint32_t location, fcram_entry_t *fcram_ptr,
706 			    fcram_entry_format_t format)
707 {
708 
709 	int num_subareas = 0;
710 	uint64_t addr_reg, data_reg;
711 	int subarea, autoinc;
712 	hash_tbl_addr_t addr;
713 	switch (format) {
714 		case FCRAM_ENTRY_OPTIM:
715 			if (location % 8) {
716 			NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
717 			    " FCRAM_ENTRY_OOPTIM Read:"
718 			    " unaligned location %llx \n",
719 			    location));
720 			/* need to be 8 byte alligned */
721 				return (NPI_FFLP_FCRAM_LOC_INVALID);
722 			}
723 			num_subareas = 1;
724 			autoinc = 0;
725 			break;
726 		case FCRAM_ENTRY_EX_IP4:
727 			if (location % 32) {
728 					/* need to be 32 byte alligned */
729 			NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
730 			    " FCRAM_ENTRY_EX_IP4 READ:"
731 			    " unaligned location %llx \n",
732 			    location));
733 				return (NPI_FFLP_FCRAM_LOC_INVALID);
734 			}
735 			num_subareas = 4;
736 			autoinc = 1;
737 
738 			break;
739 		case FCRAM_ENTRY_EX_IP6:
740 			if (location % 64) {
741 					/* need to be 64 byte alligned */
742 			NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
743 			    " FCRAM_ENTRY_EX_IP6 READ:"
744 			    " unaligned location %llx \n",
745 			    location));
746 
747 				return (NPI_FFLP_FCRAM_LOC_INVALID);
748 	}
749 			num_subareas = 7;
750 			autoinc = 1;
751 
752 			break;
753 		default:
754 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
755 		    " fcram_entry_read:"
756 		    " unknown format param location %llx\n",
757 		    location));
758 		return (NPI_FFLP_SW_PARAM_ERROR);
759 	}
760 
761 	addr.value = 0;
762 	addr.bits.ldw.autoinc = autoinc;
763 	addr.bits.ldw.addr = location;
764 	addr_reg = GET_HASHTBL_PART_OFFSET(handle, partid,
765 	    FFLP_HASH_TBL_ADDR_REG);
766 	data_reg = GET_HASHTBL_PART_OFFSET(handle, partid,
767 	    FFLP_HASH_TBL_DATA_REG);
768 /* write to addr reg */
769 	REG_PIO_WRITE64(handle, addr_reg, addr.value);
770 /* read data from the data register */
771 	for (subarea = 0; subarea < num_subareas; subarea++) {
772 		REG_PIO_READ64(handle, data_reg, &fcram_ptr->value[subarea]);
773 	}
774 
775 
776 	return (NPI_SUCCESS);
777 
778 }
779 
780 /*
781  * npi_fflp_fcram_entry_invalidate ()
782  * Invalidate FCRAM entry at the given location
783  * Inputs:
784  *	handle:		opaque handle interpreted by the underlying OS
785  *	partid:		Partition ID
786  *	location:	location of the FCRAM/hash entry.
787  *
788  * Return:
789  * NPI Success/Failure status code
790  */
791 npi_status_t
792 npi_fflp_fcram_entry_invalidate(npi_handle_t handle, part_id_t partid,
793 				    uint32_t location)
794 {
795 
796 	hash_tbl_addr_t addr;
797 	uint64_t addr_reg, data_reg;
798 	hash_hdr_t	   hdr;
799 
800 
801 	if (location % 8) {
802 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
803 		    " FCRAM_ENTRY_Invalidate:"
804 		    " unaligned location %llx \n",
805 		    location));
806 			/* need to be 8 byte aligned */
807 		return (NPI_FFLP_FCRAM_LOC_INVALID);
808 	}
809 
810 	addr.value = 0;
811 	addr.bits.ldw.addr = location;
812 	addr_reg = GET_HASHTBL_PART_OFFSET(handle, partid,
813 	    FFLP_HASH_TBL_ADDR_REG);
814 	data_reg = GET_HASHTBL_PART_OFFSET(handle, partid,
815 	    FFLP_HASH_TBL_DATA_REG);
816 
817 /* write to addr reg */
818 	REG_PIO_WRITE64(handle, addr_reg, addr.value);
819 
820 	REG_PIO_READ64(handle, data_reg, &hdr.value);
821 	hdr.exact_hdr.valid = 0;
822 	REG_PIO_WRITE64(handle, data_reg, hdr.value);
823 
824 	return (NPI_SUCCESS);
825 
826 }
827 
828 /*
829  * npi_fflp_fcram_write_subarea ()
830  * Writes to FCRAM entry subarea i.e the 8 bytes within the 64 bytes
831  * pointed by the  last 20 bits of  H1. Effectively, this accesses
832  * specific 8 bytes within the hash table bucket.
833  *
834  *  H1-->  |-----------------|
835  *	   |	subarea 0    |
836  *	   |_________________|
837  *	   | Subarea 1	     |
838  *	   |_________________|
839  *	   | .......	     |
840  *	   |_________________|
841  *	   | Subarea 7       |
842  *	   |_________________|
843  *
844  * Inputs:
845  *         handle:	opaque handle interpreted by the underlying OS
846  *	   partid:	Partition ID
847  *	   location:	location of the subarea. It is derived from:
848  *			Bucket = [19:15][14:0]       (20 bits of H1)
849  *			location = (Bucket << 3 ) + subarea * 8
850  *				 = [22:18][17:3] || subarea * 8
851  *	   data:	Data
852  *
853  * Return:
854  * NPI Success/Failure status code
855  */
856 npi_status_t
857 npi_fflp_fcram_subarea_write(npi_handle_t handle, part_id_t partid,
858 			    uint32_t location, uint64_t data)
859 {
860 
861 	hash_tbl_addr_t addr;
862 	uint64_t addr_reg, data_reg;
863 
864 
865 	if (location % 8) {
866 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
867 		    " fcram_subarea_write:"
868 		    " unaligned location %llx \n",
869 		    location));
870 			/* need to be 8 byte alligned */
871 		return (NPI_FFLP_FCRAM_LOC_INVALID);
872 	}
873 
874 	addr.value = 0;
875 	addr.bits.ldw.addr = location;
876 	addr_reg = GET_HASHTBL_PART_OFFSET(handle, partid,
877 	    FFLP_HASH_TBL_ADDR_REG);
878 	data_reg = GET_HASHTBL_PART_OFFSET(handle, partid,
879 	    FFLP_HASH_TBL_DATA_REG);
880 
881 /* write to addr reg */
882 	REG_PIO_WRITE64(handle, addr_reg, addr.value);
883 	REG_PIO_WRITE64(handle, data_reg, data);
884 
885 	return (NPI_SUCCESS);
886 
887 }
888 
889 /*
890  * npi_fflp_fcram_subarea_read ()
891  * Reads an FCRAM entry subarea i.e the 8 bytes within the 64 bytes
892  * pointed by  the last 20 bits of  H1. Effectively, this accesses
893  * specific 8 bytes within the hash table bucket.
894  *
895  *  H1-->  |-----------------|
896  *	   |	subarea 0    |
897  *	   |_________________|
898  *	   | Subarea 1	     |
899  *	   |_________________|
900  *	   | .......	     |
901  *	   |_________________|
902  *	   | Subarea 7       |
903  *	   |_________________|
904  *
905  * Inputs:
906  *         handle:	opaque handle interpreted by the underlying OS
907  *	   partid:	Partition ID
908  *	   location:	location of the subarea. It is derived from:
909  *			Bucket = [19:15][14:0]       (20 bits of H1)
910  *			location = (Bucket << 3 ) + subarea * 8
911  *				 = [22:18][17:3] || subarea * 8
912  *	   data:	ptr do write subarea contents to.
913  *
914  * Return:
915  * NPI Success/Failure status code
916  */
917 npi_status_t
918 npi_fflp_fcram_subarea_read(npi_handle_t handle, part_id_t partid,
919 			    uint32_t location, uint64_t *data)
920 
921 {
922 
923 	hash_tbl_addr_t addr;
924 	uint64_t addr_reg, data_reg;
925 
926 	if (location % 8) {
927 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
928 				    " fcram_subarea_read:"
929 				    " unaligned location %llx \n",
930 				    location));
931 			/* need to be 8 byte alligned */
932 		return (NPI_FFLP_FCRAM_LOC_INVALID);
933 	}
934 
935 	addr.value = 0;
936 	addr.bits.ldw.addr = location;
937 	addr_reg = GET_HASHTBL_PART_OFFSET(handle, partid,
938 						    FFLP_HASH_TBL_ADDR_REG);
939 	data_reg = GET_HASHTBL_PART_OFFSET(handle, partid,
940 						    FFLP_HASH_TBL_DATA_REG);
941 
942 /* write to addr reg */
943 	REG_PIO_WRITE64(handle, addr_reg, addr.value);
944 	REG_PIO_READ64(handle, data_reg, data);
945 
946 	return (NPI_SUCCESS);
947 
948 }
949 
950 /*
951  * The following are zero function fflp configuration functions.
952  */
953 
954 /*
955  * npi_fflp_fcram_config_partition()
956  * Partitions and configures the FCRAM
957  */
958 npi_status_t
959 npi_fflp_cfg_fcram_partition(npi_handle_t handle, part_id_t partid,
960 				    uint8_t base_mask, uint8_t base_reloc)
961 
962 {
963 /*
964  * assumes that the base mask and relocation are computed somewhere
965  * and kept in the state data structure. Alternativiely, one can pass
966  * a partition size and a starting address and this routine can compute
967  * the mask and reloc vlaues.
968  */
969 
970     flow_prt_sel_t sel;
971     uint64_t offset;
972 
973     ASSERT(FCRAM_PARTITION_VALID(partid));
974 	if (!FCRAM_PARTITION_VALID(partid)) {
975 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
976 				    " npi_fflp_cfg_fcram_partition:"
977 				    " Invalid Partition %d \n",
978 				    partid));
979 		return (NPI_FFLP_FCRAM_PART_INVALID);
980 	}
981 
982     offset = FFLP_PART_OFFSET(partid, FFLP_FLW_PRT_SEL_REG);
983     sel.value = 0;
984     sel.bits.ldw.mask = base_mask;
985     sel.bits.ldw.base = base_reloc;
986     sel.bits.ldw.ext = BIT_DISABLE; /* disable */
987     REG_PIO_WRITE64(handle, offset, sel.value);
988     return (NPI_SUCCESS);
989 
990 }
991 
992 /*
993  * npi_fflp_fcram_partition_enable
994  * Enable previously configured FCRAM partition
995  *
996  * Input
997  *         handle:	opaque handle interpreted by the underlying OS
998  *         partid:	 partition ID, Corresponds to the RDC table
999  *
1000  * Return
1001  *      0			Successful
1002  *      Non zero  error code    Enable failed, and reason.
1003  *
1004  */
1005 npi_status_t
1006 npi_fflp_cfg_fcram_partition_enable  (npi_handle_t handle, part_id_t partid)
1007 
1008 {
1009 
1010     flow_prt_sel_t sel;
1011     uint64_t offset;
1012 
1013     ASSERT(FCRAM_PARTITION_VALID(partid));
1014     if (!FCRAM_PARTITION_VALID(partid)) {
1015 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
1016 				    " fcram_partition enable:"
1017 				    " Invalid Partition %d \n",
1018 				    partid));
1019 		return (NPI_FFLP_FCRAM_PART_INVALID);
1020 	}
1021 
1022     offset = FFLP_PART_OFFSET(partid, FFLP_FLW_PRT_SEL_REG);
1023 
1024     REG_PIO_READ64(handle, offset, &sel.value);
1025     sel.bits.ldw.ext = BIT_ENABLE; /* enable */
1026     REG_PIO_WRITE64(handle, offset, sel.value);
1027 
1028     return (NPI_SUCCESS);
1029 
1030 }
1031 
1032 /*
1033  * npi_fflp_fcram_partition_disable
1034  * Disable previously configured FCRAM partition
1035  *
1036  * Input
1037  *         handle:	opaque handle interpreted by the underlying OS
1038  *         partid:	partition ID, Corresponds to the RDC table
1039  *
1040  * Return:
1041  * NPI Success/Failure status code
1042  */
1043 npi_status_t
1044 npi_fflp_cfg_fcram_partition_disable(npi_handle_t handle, part_id_t partid)
1045 
1046 {
1047 
1048 	flow_prt_sel_t sel;
1049 	uint64_t offset;
1050 
1051 	ASSERT(FCRAM_PARTITION_VALID(partid));
1052 	if (!FCRAM_PARTITION_VALID(partid)) {
1053 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
1054 				    " fcram_partition disable:"
1055 				    " Invalid Partition %d \n",
1056 				    partid));
1057 		return (NPI_FFLP_FCRAM_PART_INVALID);
1058 	}
1059 	offset = FFLP_PART_OFFSET(partid, FFLP_FLW_PRT_SEL_REG);
1060 	REG_PIO_READ64(handle, offset, &sel.value);
1061 	sel.bits.ldw.ext = BIT_DISABLE; /* disable */
1062 	REG_PIO_WRITE64(handle, offset, sel.value);
1063 	return (NPI_SUCCESS);
1064 }
1065 
1066 /*
1067  *  npi_fflp_cam_errorcheck_disable
1068  *  Disables FCRAM and TCAM error checking
1069  */
1070 npi_status_t
1071 npi_fflp_cfg_cam_errorcheck_disable(npi_handle_t handle)
1072 
1073 {
1074 
1075 	fflp_cfg_1_t fflp_cfg;
1076 	uint64_t offset;
1077 	offset = FFLP_CFG_1_REG;
1078 
1079 	REG_PIO_READ64(handle, offset, &fflp_cfg.value);
1080 
1081 	fflp_cfg.bits.ldw.errordis = BIT_ENABLE;
1082 	REG_PIO_WRITE64(handle, offset, fflp_cfg.value);
1083 
1084 	return (NPI_SUCCESS);
1085 
1086 }
1087 
1088 /*
1089  *  npi_fflp_cam_errorcheck_enable
1090  *  Enables FCRAM and TCAM error checking
1091  */
1092 npi_status_t
1093 npi_fflp_cfg_cam_errorcheck_enable(npi_handle_t handle)
1094 
1095 {
1096 	fflp_cfg_1_t fflp_cfg;
1097 	uint64_t offset;
1098 	offset = FFLP_CFG_1_REG;
1099 
1100 	REG_PIO_READ64(handle, offset, &fflp_cfg.value);
1101 
1102 	fflp_cfg.bits.ldw.errordis = BIT_DISABLE;
1103 	REG_PIO_WRITE64(handle, offset, fflp_cfg.value);
1104 
1105 	return (NPI_SUCCESS);
1106 
1107 }
1108 
1109 /*
1110  *  npi_fflp_cam_llcsnap_enable
1111  *  Enables input parser llcsnap recognition
1112  */
1113 npi_status_t
1114 npi_fflp_cfg_llcsnap_enable(npi_handle_t handle)
1115 
1116 {
1117 
1118 	fflp_cfg_1_t fflp_cfg;
1119 	uint64_t offset;
1120 	offset = FFLP_CFG_1_REG;
1121 
1122 	REG_PIO_READ64(handle, offset, &fflp_cfg.value);
1123 
1124 	fflp_cfg.bits.ldw.llcsnap = BIT_ENABLE;
1125 	REG_PIO_WRITE64(handle, offset, fflp_cfg.value);
1126 
1127 	return (NPI_SUCCESS);
1128 
1129 }
1130 
1131 /*
1132  *  npi_fflp_cam_llcsnap_disable
1133  *  Disables input parser llcsnap recognition
1134  */
1135 npi_status_t
1136 npi_fflp_cfg_llcsnap_disable(npi_handle_t handle)
1137 
1138 {
1139 
1140 
1141 	fflp_cfg_1_t fflp_cfg;
1142 	uint64_t offset;
1143 	offset = FFLP_CFG_1_REG;
1144 
1145 	REG_PIO_READ64(handle, offset, &fflp_cfg.value);
1146 
1147 	fflp_cfg.bits.ldw.llcsnap = BIT_DISABLE;
1148 	REG_PIO_WRITE64(handle, offset, fflp_cfg.value);
1149 
1150 	return (NPI_SUCCESS);
1151 
1152 }
1153 
1154 /*
1155  * npi_fflp_config_fcram_refresh
1156  * Set FCRAM min and max refresh time.
1157  *
1158  * Input
1159  *      handle			opaque handle interpreted by the underlying OS
1160  *	min_time		Minimum Refresh time count
1161  *	max_time		maximum Refresh Time count
1162  *	sys_time		System Clock rate
1163  *
1164  *	The counters are 16 bit counters. The maximum refresh time is
1165  *      3.9us/clock cycle. The minimum is 400ns/clock cycle.
1166  *	Clock cycle is the FCRAM clock cycle?????
1167  *	If the cycle is FCRAM clock cycle, then sys_time parameter
1168  *      is not needed as there wont be configuration variation due to
1169  *      system clock cycle.
1170  *
1171  * Return:
1172  * NPI Success/Failure status code
1173  */
1174 npi_status_t
1175 npi_fflp_cfg_fcram_refresh_time(npi_handle_t handle, uint32_t min_time,
1176 				    uint32_t max_time, uint32_t sys_time)
1177 
1178 {
1179 
1180 	uint64_t offset;
1181 	fcram_ref_tmr_t refresh_timer_reg;
1182 	uint16_t max, min;
1183 
1184 	offset = FFLP_FCRAM_REF_TMR_REG;
1185 /* need to figure out how to dervive the numbers */
1186 	max = max_time * sys_time;
1187 	min = min_time * sys_time;
1188 /* for now, just set with #def values */
1189 
1190 	max = FCRAM_REFRESH_DEFAULT_MAX_TIME;
1191 	min = FCRAM_REFRESH_DEFAULT_MIN_TIME;
1192 	REG_PIO_READ64(handle, offset, &refresh_timer_reg.value);
1193 	refresh_timer_reg.bits.ldw.min = min;
1194 	refresh_timer_reg.bits.ldw.max = max;
1195 	REG_PIO_WRITE64(handle, offset, refresh_timer_reg.value);
1196 	return (NPI_SUCCESS);
1197 }
1198 
1199 /*
1200  *  npi_fflp_hash_lookup_err_report
1201  *  Reports hash table (fcram) lookup errors
1202  *
1203  *  Input
1204  *      handle			opaque handle interpreted by the underlying OS
1205  *      err_stat		Pointer to return Error bits
1206  *
1207  *
1208  * Return:
1209  * NPI success/failure status code
1210  */
1211 npi_status_t
1212 npi_fflp_fcram_get_lookup_err_log(npi_handle_t handle,
1213 				    hash_lookup_err_log_t *err_stat)
1214 
1215 {
1216 
1217 	hash_lookup_err_log1_t err_log1;
1218 	hash_lookup_err_log2_t err_log2;
1219 	uint64_t  err_log1_offset, err_log2_offset;
1220 	err_log1.value = 0;
1221 	err_log2.value = 0;
1222 
1223 	err_log1_offset = HASH_LKUP_ERR_LOG1_REG;
1224 	err_log2_offset = HASH_LKUP_ERR_LOG2_REG;
1225 
1226 	REG_PIO_READ64(handle, err_log1_offset, &err_log1.value);
1227 	REG_PIO_READ64(handle, err_log2_offset, &err_log2.value);
1228 
1229 	if (err_log1.value) {
1230 /* nonzero means there are some errors */
1231 		err_stat->lookup_err = BIT_ENABLE;
1232 		err_stat->syndrome = err_log2.bits.ldw.syndrome;
1233 		err_stat->subarea = err_log2.bits.ldw.subarea;
1234 		err_stat->h1 = err_log2.bits.ldw.h1;
1235 		err_stat->multi_bit = err_log1.bits.ldw.mult_bit;
1236 		err_stat->multi_lkup = err_log1.bits.ldw.mult_lk;
1237 		err_stat->ecc_err = err_log1.bits.ldw.ecc_err;
1238 		err_stat->uncor_err = err_log1.bits.ldw.cu;
1239 	} else {
1240 		err_stat->lookup_err = BIT_DISABLE;
1241 	}
1242 
1243 	return (NPI_SUCCESS);
1244 
1245 }
1246 
1247 /*
1248  * npi_fflp_fcram_get_pio_err_log
1249  * Reports hash table PIO read errors for the given partition.
1250  * by default, it clears the error bit which was set by the HW.
1251  *
1252  * Input
1253  *      handle:		opaque handle interpreted by the underlying OS
1254  *	partid:		partition ID
1255  *      err_stat	Pointer to return Error bits
1256  *
1257  * Return
1258  *	NPI success/failure status code
1259  */
1260 npi_status_t
1261 npi_fflp_fcram_get_pio_err_log(npi_handle_t handle, part_id_t partid,
1262 				    hash_pio_err_log_t *err_stat)
1263 {
1264 
1265 	hash_tbl_data_log_t err_log;
1266 	uint64_t offset;
1267 
1268 	ASSERT(FCRAM_PARTITION_VALID(partid));
1269 	if (!FCRAM_PARTITION_VALID(partid)) {
1270 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
1271 		    " fcram_get_pio_err_log:"
1272 		    " Invalid Partition %d \n",
1273 		    partid));
1274 		return (NPI_FFLP_FCRAM_PART_INVALID);
1275 	}
1276 
1277 	offset = GET_HASHTBL_PART_OFFSET_NVIR(partid,
1278 	    FFLP_HASH_TBL_DATA_LOG_REG);
1279 
1280 	REG_PIO_READ64(handle, offset, &err_log.value);
1281 
1282 	if (err_log.bits.ldw.pio_err == BIT_ENABLE) {
1283 /* nonzero means there are some errors */
1284 		err_stat->pio_err = BIT_ENABLE;
1285 		err_stat->syndrome = err_log.bits.ldw.syndrome;
1286 		err_stat->addr = err_log.bits.ldw.fcram_addr;
1287 		err_log.value = 0;
1288 		REG_PIO_WRITE64(handle, offset, err_log.value);
1289 	} else {
1290 		err_stat->pio_err = BIT_DISABLE;
1291 	}
1292 
1293 	return (NPI_SUCCESS);
1294 
1295 }
1296 
1297 /*
1298  * npi_fflp_fcram_clr_pio_err_log
1299  * Clears FCRAM PIO  error status for the partition.
1300  * If there are TCAM errors as indicated by err bit set by HW,
1301  *  then the SW will clear it by clearing the bit.
1302  *
1303  * Input
1304  *      handle:		opaque handle interpreted by the underlying OS
1305  *	partid:		partition ID
1306  *
1307  *
1308  * Return
1309  *	NPI success/failure status code
1310  */
1311 npi_status_t
1312 npi_fflp_fcram_clr_pio_err_log(npi_handle_t handle, part_id_t partid)
1313 {
1314 	uint64_t offset;
1315 
1316 	hash_tbl_data_log_t err_log;
1317 
1318 	ASSERT(FCRAM_PARTITION_VALID(partid));
1319 	if (!FCRAM_PARTITION_VALID(partid)) {
1320 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
1321 		    " fcram_clr_pio_err_log:"
1322 		    " Invalid Partition %d \n",
1323 		    partid));
1324 
1325 		return (NPI_FFLP_FCRAM_PART_INVALID);
1326 	}
1327 
1328 	offset = GET_HASHTBL_PART_OFFSET_NVIR(partid,
1329 	    FFLP_HASH_TBL_DATA_LOG_REG);
1330 
1331 	err_log.value = 0;
1332 	REG_PIO_WRITE64(handle, offset, err_log.value);
1333 
1334 
1335 	return (NPI_SUCCESS);
1336 
1337 }
1338 
1339 /*
1340  * npi_fflp_tcam_get_err_log
1341  * Reports TCAM PIO read and lookup errors.
1342  * If there are TCAM errors as indicated by err bit set by HW,
1343  *  then the SW will clear it by clearing the bit.
1344  *
1345  * Input
1346  *      handle:		opaque handle interpreted by the underlying OS
1347  *	err_stat:	 structure to report various TCAM errors.
1348  *                       will be updated if there are TCAM errors.
1349  *
1350  *
1351  * Return
1352  *	NPI_SUCCESS	Success
1353  *
1354  *
1355  */
1356 npi_status_t
1357 npi_fflp_tcam_get_err_log(npi_handle_t handle, tcam_err_log_t *err_stat)
1358 {
1359 	tcam_err_t err_log;
1360 	uint64_t offset;
1361 
1362 	offset = FFLP_TCAM_ERR_REG;
1363 	err_log.value = 0;
1364 
1365 	REG_PIO_READ64(handle, offset, &err_log.value);
1366 
1367 	if (err_log.bits.ldw.err == BIT_ENABLE) {
1368 /* non-zero means err */
1369 		err_stat->tcam_err = BIT_ENABLE;
1370 		if (err_log.bits.ldw.p_ecc) {
1371 			err_stat->parity_err = 0;
1372 			err_stat->ecc_err = 1;
1373 		} else {
1374 			err_stat->parity_err = 1;
1375 			err_stat->ecc_err = 0;
1376 
1377 		}
1378 		err_stat->syndrome = err_log.bits.ldw.syndrome;
1379 		err_stat->location = err_log.bits.ldw.addr;
1380 
1381 
1382 		err_stat->multi_lkup = err_log.bits.ldw.mult;
1383 			/* now clear the error */
1384 		err_log.value = 0;
1385 		REG_PIO_WRITE64(handle, offset, err_log.value);
1386 
1387 	} else {
1388 		err_stat->tcam_err = 0;
1389 	}
1390 	return (NPI_SUCCESS);
1391 
1392 }
1393 
1394 /*
1395  * npi_fflp_tcam_clr_err_log
1396  * Clears TCAM PIO read and lookup error status.
1397  * If there are TCAM errors as indicated by err bit set by HW,
1398  *  then the SW will clear it by clearing the bit.
1399  *
1400  * Input
1401  *         handle:	opaque handle interpreted by the underlying OS
1402  *
1403  *
1404  * Return
1405  *	NPI_SUCCESS	Success
1406  *
1407  *
1408  */
1409 npi_status_t
1410 npi_fflp_tcam_clr_err_log(npi_handle_t handle)
1411 {
1412 	tcam_err_t err_log;
1413 	uint64_t offset;
1414 
1415 	offset = FFLP_TCAM_ERR_REG;
1416 	err_log.value = 0;
1417 	REG_PIO_WRITE64(handle, offset, err_log.value);
1418 
1419 	return (NPI_SUCCESS);
1420 
1421 }
1422 
1423 /*
1424  * npi_fflp_fcram_err_synd_test
1425  * Tests the FCRAM error detection logic.
1426  * The error detection logic for the syndrome is tested.
1427  * tst0->synd (8bits) are set to select the syndrome bits
1428  * to be XOR'ed
1429  *
1430  * Input
1431  *      handle:	opaque handle interpreted by the underlying OS
1432  *	syndrome_bits:	 Syndrome bits to select bits to be xor'ed
1433  *
1434  *
1435  * Return
1436  *	NPI_SUCCESS	Success
1437  *
1438  *
1439  */
1440 npi_status_t
1441 npi_fflp_fcram_err_synd_test(npi_handle_t handle, uint8_t syndrome_bits)
1442 {
1443 
1444 	uint64_t t0_offset;
1445 	fcram_err_tst0_t tst0;
1446 	t0_offset = FFLP_FCRAM_ERR_TST0_REG;
1447 
1448 	tst0.value = 0;
1449 	tst0.bits.ldw.syndrome_mask = syndrome_bits;
1450 
1451 	REG_PIO_WRITE64(handle, t0_offset, tst0.value);
1452 
1453 	return (NPI_SUCCESS);
1454 
1455 }
1456 
1457 /*
1458  * npi_fflp_fcram_err_data_test
1459  * Tests the FCRAM error detection logic.
1460  * The error detection logic for the datapath is tested.
1461  * bits [63:0] are set to select the data bits to be xor'ed
1462  *
1463  * Input
1464  *      handle:	opaque handle interpreted by the underlying OS
1465  *	data:	 data bits to select bits to be xor'ed
1466  *
1467  *
1468  * Return
1469  *	NPI_SUCCESS	Success
1470  *
1471  *
1472  */
1473 npi_status_t
1474 npi_fflp_fcram_err_data_test(npi_handle_t handle, fcram_err_data_t *data)
1475 {
1476 
1477 	uint64_t t1_offset, t2_offset;
1478 	fcram_err_tst1_t tst1; /* for data bits [31:0] */
1479 	fcram_err_tst2_t tst2; /* for data bits [63:32] */
1480 
1481 	t1_offset = FFLP_FCRAM_ERR_TST1_REG;
1482 	t2_offset = FFLP_FCRAM_ERR_TST2_REG;
1483 	tst1.value = 0;
1484 	tst2.value = 0;
1485 	tst1.bits.ldw.dat = data->bits.ldw.dat;
1486 	tst2.bits.ldw.dat = data->bits.hdw.dat;
1487 
1488 	REG_PIO_WRITE64(handle, t1_offset, tst1.value);
1489 	REG_PIO_WRITE64(handle, t2_offset, tst2.value);
1490 
1491 	return (NPI_SUCCESS);
1492 
1493 }
1494 
1495 /*
1496  * npi_fflp_cfg_enet_vlan_table_assoc
1497  * associates port vlan id to rdc table.
1498  *
1499  * Input
1500  *     handle			opaque handle interpreted by the underlying OS
1501  *     mac_portn		port number
1502  *     vlan_id			VLAN ID
1503  *     rdc_table		RDC Table #
1504  *     priority			priority
1505  *
1506  * Output
1507  *
1508  *	NPI success/failure status code
1509  *
1510  */
1511 npi_status_t
1512 npi_fflp_cfg_enet_vlan_table_assoc(npi_handle_t handle, uint8_t mac_portn,
1513 				    vlan_id_t vlan_id, uint8_t rdc_table,
1514 				    uint8_t priority)
1515 {
1516 
1517 	fflp_enet_vlan_tbl_t cfg;
1518 	uint64_t offset;
1519 	uint8_t vlan_parity[8] = {0, 1, 1, 2, 1, 2, 2, 3};
1520 	uint8_t parity_bit;
1521 
1522 	ASSERT(FFLP_VLAN_VALID(vlan_id));
1523 	if (!FFLP_VLAN_VALID(vlan_id)) {
1524 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
1525 		    " fflp_cfg_enet_vlan_table:"
1526 		    " Invalid vlan ID %d \n",
1527 		    vlan_id));
1528 		return (NPI_FFLP_VLAN_INVALID);
1529 	}
1530 
1531 	ASSERT(FFLP_PORT_VALID(mac_portn));
1532 	if (!FFLP_PORT_VALID(mac_portn)) {
1533 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
1534 		    " fflp_cfg_enet_vlan_table:"
1535 		    " Invalid port num %d \n",
1536 		    mac_portn));
1537 		return (NPI_FFLP_PORT_INVALID);
1538 	}
1539 
1540 	ASSERT(FFLP_RDC_TABLE_VALID(rdc_table));
1541 	if (!FFLP_RDC_TABLE_VALID(rdc_table)) {
1542 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
1543 		    " fflp_cfg_enet_vlan_table:"
1544 		    " Invalid RDC Table %d \n",
1545 		    rdc_table));
1546 		return (NPI_FFLP_RDC_TABLE_INVALID);
1547 	}
1548 
1549 	offset = FFLP_VLAN_OFFSET(vlan_id, FFLP_ENET_VLAN_TBL_REG);
1550 	REG_PIO_READ64(handle, offset, &cfg.value);
1551 
1552 	switch (mac_portn) {
1553 		case 0:
1554 			cfg.bits.ldw.vlanrdctbln0 = rdc_table;
1555 			if (priority)
1556 				cfg.bits.ldw.vpr0 = BIT_ENABLE;
1557 			else
1558 				cfg.bits.ldw.vpr0 = BIT_DISABLE;
1559 				/* set the parity bits */
1560 			parity_bit = vlan_parity[cfg.bits.ldw.vlanrdctbln0] +
1561 			    vlan_parity[cfg.bits.ldw.vlanrdctbln1] +
1562 			    cfg.bits.ldw.vpr0 + cfg.bits.ldw.vpr1;
1563 			cfg.bits.ldw.parity0 = parity_bit & 0x1;
1564 			break;
1565 		case 1:
1566 			cfg.bits.ldw.vlanrdctbln1 = rdc_table;
1567 			if (priority)
1568 				cfg.bits.ldw.vpr1 = BIT_ENABLE;
1569 			else
1570 				cfg.bits.ldw.vpr1 = BIT_DISABLE;
1571 				/* set the parity bits */
1572 			parity_bit = vlan_parity[cfg.bits.ldw.vlanrdctbln0] +
1573 			    vlan_parity[cfg.bits.ldw.vlanrdctbln1] +
1574 			    cfg.bits.ldw.vpr0 + cfg.bits.ldw.vpr1;
1575 				cfg.bits.ldw.parity0 = parity_bit & 0x1;
1576 
1577 			break;
1578 		case 2:
1579 			cfg.bits.ldw.vlanrdctbln2 = rdc_table;
1580 			if (priority)
1581 				cfg.bits.ldw.vpr2 = BIT_ENABLE;
1582 			else
1583 				cfg.bits.ldw.vpr2 = BIT_DISABLE;
1584 				/* set the parity bits */
1585 			parity_bit = vlan_parity[cfg.bits.ldw.vlanrdctbln2] +
1586 			    vlan_parity[cfg.bits.ldw.vlanrdctbln3] +
1587 			    cfg.bits.ldw.vpr2 + cfg.bits.ldw.vpr3;
1588 			cfg.bits.ldw.parity1 = parity_bit & 0x1;
1589 
1590 			break;
1591 		case 3:
1592 			cfg.bits.ldw.vlanrdctbln3 = rdc_table;
1593 			if (priority)
1594 				cfg.bits.ldw.vpr3 = BIT_ENABLE;
1595 			else
1596 				cfg.bits.ldw.vpr3 = BIT_DISABLE;
1597 				/* set the parity bits */
1598 			parity_bit = vlan_parity[cfg.bits.ldw.vlanrdctbln2] +
1599 			    vlan_parity[cfg.bits.ldw.vlanrdctbln3] +
1600 			    cfg.bits.ldw.vpr2 + cfg.bits.ldw.vpr3;
1601 			cfg.bits.ldw.parity1 = parity_bit & 0x1;
1602 			break;
1603 		default:
1604 			return (NPI_FFLP_SW_PARAM_ERROR);
1605 	}
1606 
1607 	REG_PIO_WRITE64(handle, offset, cfg.value);
1608 	return (NPI_SUCCESS);
1609 }
1610 
1611 /*
1612  * npi_fflp_cfg_enet_vlan_table_set_pri
1613  * sets the  vlan based classification priority in respect to L2DA
1614  * classification.
1615  *
1616  * Input
1617  *     handle		opaque handle interpreted by the underlying OS
1618  *     mac_portn	port number
1619  *     vlan_id		VLAN ID
1620  *     priority 	priority
1621  *			1: vlan classification has higher priority
1622  *			0: l2da classification has higher priority
1623  *
1624  * Output
1625  *
1626  *	NPI success/failure status code
1627  */
1628 npi_status_t
1629 npi_fflp_cfg_enet_vlan_table_set_pri(npi_handle_t handle, uint8_t mac_portn,
1630 				    vlan_id_t vlan_id, uint8_t priority)
1631 {
1632 
1633 	fflp_enet_vlan_tbl_t cfg;
1634 	uint64_t offset;
1635 	uint64_t old_value;
1636 
1637 	ASSERT(FFLP_VLAN_VALID(vlan_id));
1638 	if (!FFLP_VLAN_VALID(vlan_id)) {
1639 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
1640 		    " enet_vlan_table set pri:"
1641 		    " Invalid vlan ID %d \n",
1642 		    vlan_id));
1643 		return (NPI_FFLP_VLAN_INVALID);
1644 	}
1645 
1646 	ASSERT(FFLP_PORT_VALID(mac_portn));
1647 	if (!FFLP_PORT_VALID(mac_portn)) {
1648 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
1649 		    " enet_vlan_table set pri:"
1650 		    " Invalid port num %d \n",
1651 		    mac_portn));
1652 		return (NPI_FFLP_PORT_INVALID);
1653 	}
1654 
1655 
1656 	offset = FFLP_ENET_VLAN_TBL_REG + (vlan_id  << 3);
1657 	REG_PIO_READ64(handle, offset, &cfg.value);
1658 	old_value = cfg.value;
1659 	switch (mac_portn) {
1660 		case 0:
1661 			if (priority)
1662 				cfg.bits.ldw.vpr0 = BIT_ENABLE;
1663 			else
1664 				cfg.bits.ldw.vpr0 = BIT_DISABLE;
1665 			break;
1666 		case 1:
1667 			if (priority)
1668 				cfg.bits.ldw.vpr1 = BIT_ENABLE;
1669 			else
1670 				cfg.bits.ldw.vpr1 = BIT_DISABLE;
1671 			break;
1672 		case 2:
1673 			if (priority)
1674 				cfg.bits.ldw.vpr2 = BIT_ENABLE;
1675 			else
1676 				cfg.bits.ldw.vpr2 = BIT_DISABLE;
1677 			break;
1678 		case 3:
1679 			if (priority)
1680 				cfg.bits.ldw.vpr3 = BIT_ENABLE;
1681 			else
1682 				cfg.bits.ldw.vpr3 = BIT_DISABLE;
1683 			break;
1684 		default:
1685 			return (NPI_FFLP_SW_PARAM_ERROR);
1686 	}
1687 	if (old_value != cfg.value) {
1688 		if (mac_portn > 1)
1689 			cfg.bits.ldw.parity1++;
1690 		else
1691 			cfg.bits.ldw.parity0++;
1692 
1693 		REG_PIO_WRITE64(handle, offset, cfg.value);
1694 	}
1695 	return (NPI_SUCCESS);
1696 }
1697 
1698 /*
1699  * npi_fflp_cfg_vlan_table_clear
1700  * Clears the vlan RDC table
1701  *
1702  * Input
1703  *     handle		opaque handle interpreted by the underlying OS
1704  *     vlan_id		VLAN ID
1705  *
1706  * Output
1707  *
1708  *	NPI success/failure status code
1709  *
1710  */
1711 npi_status_t
1712 npi_fflp_cfg_vlan_table_clear(npi_handle_t handle, vlan_id_t vlan_id)
1713 {
1714 
1715 	uint64_t offset;
1716 	uint64_t clear = 0ULL;
1717 	vlan_id_t start_vlan = 0;
1718 
1719 	if ((vlan_id < start_vlan) || (vlan_id >= NXGE_MAX_VLANS)) {
1720 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
1721 		    " enet_vlan_table clear:"
1722 		    " Invalid vlan ID %d \n",
1723 		    vlan_id));
1724 		return (NPI_FFLP_VLAN_INVALID);
1725 	}
1726 
1727 
1728 	offset = FFLP_VLAN_OFFSET(vlan_id, FFLP_ENET_VLAN_TBL_REG);
1729 
1730 	REG_PIO_WRITE64(handle, offset, clear);
1731 	return (NPI_SUCCESS);
1732 }
1733 
1734 /*
1735  * npi_fflp_vlan_tbl_get_err_log
1736  * Reports VLAN Table  errors.
1737  * If there are VLAN Table errors as indicated by err bit set by HW,
1738  *  then the SW will clear it by clearing the bit.
1739  *
1740  * Input
1741  *      handle:		opaque handle interpreted by the underlying OS
1742  *	err_stat:	 structure to report various VLAN table errors.
1743  *                       will be updated if there are errors.
1744  *
1745  *
1746  * Return
1747  *	NPI_SUCCESS	Success
1748  *
1749  *
1750  */
1751 npi_status_t
1752 npi_fflp_vlan_tbl_get_err_log(npi_handle_t handle, vlan_tbl_err_log_t *err_stat)
1753 {
1754 	vlan_par_err_t err_log;
1755 	uint64_t offset;
1756 
1757 
1758 	offset = FFLP_VLAN_PAR_ERR_REG;
1759 	err_log.value = 0;
1760 
1761 	REG_PIO_READ64(handle, offset, &err_log.value);
1762 
1763 	if (err_log.bits.ldw.err == BIT_ENABLE) {
1764 /* non-zero means err */
1765 		err_stat->err = BIT_ENABLE;
1766 		err_stat->multi = err_log.bits.ldw.m_err;
1767 		err_stat->addr = err_log.bits.ldw.addr;
1768 		err_stat->data = err_log.bits.ldw.data;
1769 /* now clear the error */
1770 		err_log.value = 0;
1771 		REG_PIO_WRITE64(handle, offset, err_log.value);
1772 
1773 	} else {
1774 		err_stat->err = 0;
1775 	}
1776 
1777 	return (NPI_SUCCESS);
1778 }
1779 
1780 /*
1781  * npi_fflp_vlan_tbl_clr_err_log
1782  * Clears VLAN Table PIO  error status.
1783  * If there are VLAN Table errors as indicated by err bit set by HW,
1784  *  then the SW will clear it by clearing the bit.
1785  *
1786  * Input
1787  *         handle:	opaque handle interpreted by the underlying OS
1788  *
1789  *
1790  * Return
1791  *	NPI_SUCCESS	Success
1792  *
1793  *
1794  */
1795 npi_status_t
1796 npi_fflp_vlan_tbl_clr_err_log(npi_handle_t handle)
1797 {
1798 	vlan_par_err_t err_log;
1799 	uint64_t offset;
1800 
1801 	offset = FFLP_VLAN_PAR_ERR_REG;
1802 	err_log.value = 0;
1803 
1804 	REG_PIO_WRITE64(handle, offset, err_log.value);
1805 
1806 	return (NPI_SUCCESS);
1807 }
1808 
1809 /*
1810  * npi_fflp_cfg_enet_usr_cls_set()
1811  * Configures a user configurable ethernet class
1812  *
1813  * Input
1814  *      handle:		opaque handle interpreted by the underlying OS
1815  *      class:       Ethernet Class  class
1816  *		     (TCAM_CLASS_ETYPE or  TCAM_CLASS_ETYPE_2)
1817  *      enet_type:   16 bit Ethernet Type value, corresponding ethernet bytes
1818  *                        [13:14] in the frame.
1819  *
1820  *  by default, the class will be disabled until explicitly enabled.
1821  *
1822  * Return
1823  * NPI success/failure status code
1824  */
1825 npi_status_t
1826 npi_fflp_cfg_enet_usr_cls_set(npi_handle_t handle,
1827 			    tcam_class_t class, uint16_t enet_type)
1828 {
1829 	uint64_t offset;
1830 	tcam_class_prg_ether_t cls_cfg;
1831 	cls_cfg.value = 0x0;
1832 
1833 /* check if etype is valid */
1834 	ASSERT(TCAM_L2_USR_CLASS_VALID(class));
1835 	if (!TCAM_L2_USR_CLASS_VALID(class)) {
1836 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
1837 		    " npi_fflp_cfg_enet_usr_cls_set:"
1838 		    " Invalid class %d \n",
1839 		    class));
1840 		return (NPI_FFLP_TCAM_CLASS_INVALID);
1841 	}
1842 	offset = GET_TCAM_CLASS_OFFSET(class);
1843 
1844 /*
1845  * etype check code
1846  *
1847  * if (check_fail)
1848  *  return (NPI_FAILURE | NPI_SW_ERROR);
1849  */
1850 
1851 	cls_cfg.bits.ldw.etype = enet_type;
1852 	cls_cfg.bits.ldw.valid = BIT_DISABLE;
1853 	REG_PIO_WRITE64(handle, offset, cls_cfg.value);
1854 	return (NPI_SUCCESS);
1855 }
1856 
1857 /*
1858  * npi_fflp_cfg_enet_usr_cls_enable()
1859  * Enable previously configured TCAM user configurable Ethernet classes.
1860  *
1861  * Input
1862  *      handle:	opaque handle interpreted by the underlying OS
1863  *      class:       Ethernet Class  class
1864  *		     (TCAM_CLASS_ETYPE or  TCAM_CLASS_ETYPE_2)
1865  *
1866  * Return
1867  * NPI success/failure status code
1868  */
1869 npi_status_t
1870 npi_fflp_cfg_enet_usr_cls_enable(npi_handle_t handle, tcam_class_t class)
1871 {
1872 	uint64_t offset;
1873 	tcam_class_prg_ether_t cls_cfg;
1874 
1875 	ASSERT(TCAM_L2_USR_CLASS_VALID(class));
1876 	if (!TCAM_L2_USR_CLASS_VALID(class)) {
1877 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
1878 		    " npi_fflp_cfg_enet_usr_cls_enable:"
1879 		    " Invalid class %d \n",
1880 		    class));
1881 		return (NPI_FFLP_TCAM_CLASS_INVALID);
1882 	}
1883 
1884 	offset = GET_TCAM_CLASS_OFFSET(class);
1885 
1886 	REG_PIO_READ64(handle, offset, &cls_cfg.value);
1887 	cls_cfg.bits.ldw.valid = BIT_ENABLE;
1888 	REG_PIO_WRITE64(handle, offset, cls_cfg.value);
1889 	return (NPI_SUCCESS);
1890 }
1891 
1892 /*
1893  * npi_fflp_cfg_enet_usr_cls_disable()
1894  * Disables previously configured TCAM user configurable Ethernet classes.
1895  *
1896  * Input
1897  *      handle:	opaque handle interpreted by the underlying OS
1898  *      class:       Ethernet Class  class
1899  *		     (TCAM_CLASS_ETYPE or  TCAM_CLASS_ETYPE_2)
1900  *
1901  * Return
1902  * NPI success/failure status code
1903  */
1904 npi_status_t
1905 npi_fflp_cfg_enet_usr_cls_disable(npi_handle_t handle, tcam_class_t class)
1906 {
1907 	uint64_t offset;
1908 	tcam_class_prg_ether_t cls_cfg;
1909 
1910 	ASSERT(TCAM_L2_USR_CLASS_VALID(class));
1911 	if (!TCAM_L2_USR_CLASS_VALID(class)) {
1912 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
1913 		    " npi_fflp_cfg_enet_usr_cls_disable:"
1914 		    " Invalid class %d \n",
1915 		    class));
1916 		return (NPI_FFLP_TCAM_CLASS_INVALID);
1917 	}
1918 
1919 	offset = GET_TCAM_CLASS_OFFSET(class);
1920 
1921 	REG_PIO_READ64(handle, offset, &cls_cfg.value);
1922 	cls_cfg.bits.ldw.valid = BIT_DISABLE;
1923 
1924 	REG_PIO_WRITE64(handle, offset, cls_cfg.value);
1925 	return (NPI_SUCCESS);
1926 }
1927 
1928 /*
1929  * npi_fflp_cfg_ip_usr_cls_set()
1930  * Configures the TCAM user configurable IP classes.
1931  *
1932  * Input
1933  *      handle:		opaque handle interpreted by the underlying OS
1934  *      class:       IP Class  class
1935  *		     (TCAM_CLASS_IP_USER_4 <= class <= TCAM_CLASS_IP_USER_7)
1936  *      tos:         IP TOS bits
1937  *      tos_mask:    IP TOS bits mask. bits with mask bits set will be used
1938  *      proto:       IP Proto
1939  *      ver:         IP Version
1940  * by default, will the class is disabled until explicitly enabled
1941  *
1942  * Return
1943  * NPI success/failure status code
1944  */
1945 npi_status_t
1946 npi_fflp_cfg_ip_usr_cls_set(npi_handle_t handle, tcam_class_t class,
1947 			    uint8_t tos, uint8_t tos_mask,
1948 			    uint8_t proto, uint8_t ver)
1949 {
1950 	uint64_t offset;
1951 	tcam_class_prg_ip_t ip_cls_cfg;
1952 
1953 	ASSERT(TCAM_L3_USR_CLASS_VALID(class));
1954 	if (!TCAM_L3_USR_CLASS_VALID(class)) {
1955 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
1956 		    " npi_fflp_cfg_ip_usr_cls_set:"
1957 		    " Invalid class %d \n",
1958 		    class));
1959 		return (NPI_FFLP_TCAM_CLASS_INVALID);
1960 	}
1961 
1962 	offset = GET_TCAM_CLASS_OFFSET(class);
1963 
1964 	ip_cls_cfg.bits.ldw.pid = proto;
1965 	ip_cls_cfg.bits.ldw.ipver = ver;
1966 	ip_cls_cfg.bits.ldw.tos = tos;
1967 	ip_cls_cfg.bits.ldw.tosmask = tos_mask;
1968 	ip_cls_cfg.bits.ldw.valid = 0;
1969 	REG_PIO_WRITE64(handle, offset, ip_cls_cfg.value);
1970 	return (NPI_SUCCESS);
1971 
1972 }
1973 
1974 /*
1975  * npi_fflp_cfg_ip_usr_cls_set_iptun()
1976  * Configures the TCAM user configurable IP classes. This function sets the
1977  * new fields that were added for IP tunneling support
1978  *
1979  * Input
1980  *      handle:		opaque handle interpreted by the underlying OS
1981  *      class:       IP Class  class
1982  *		     (TCAM_CLASS_IP_USER_4 <= class <= TCAM_CLASS_IP_USER_7)
1983  *	l4b0_val	value of the first L4 byte to be compared
1984  *	l4b0_msk	mask to apply to compare byte 0 of L4
1985  *	l4b23_val	values of L4 bytes 2 and 3 to compare
1986  *	l4b23_sel	set to 1 to compare L4 bytes 2 and 3.
1987  * by default, the class is disabled until explicitly enabled
1988  *
1989  * Return
1990  * NPI success/failure status code
1991  */
1992 npi_status_t
1993 npi_fflp_cfg_ip_usr_cls_set_iptun(npi_handle_t handle, tcam_class_t class,
1994 			    uint8_t l4b0_val, uint8_t l4b0_msk,
1995 			    uint16_t l4b23_val, uint8_t l4b23_sel)
1996 {
1997 	uint64_t offset, val;
1998 	tcam_class_prg_ip_t ip_cls_cfg;
1999 
2000 	ASSERT(TCAM_L3_USR_CLASS_VALID(class));
2001 	if (!TCAM_L3_USR_CLASS_VALID(class)) {
2002 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
2003 		    " npi_fflp_cfg_ip_usr_cls_set:"
2004 		    " Invalid class %d \n",
2005 		    class));
2006 		return (NPI_FFLP_TCAM_CLASS_INVALID);
2007 	}
2008 
2009 	offset = GET_TCAM_CLASS_OFFSET(class);
2010 	REG_PIO_READ64(handle, offset, &ip_cls_cfg.value);
2011 
2012 	val = 1;
2013 	ip_cls_cfg.value |= (val << L3_UCLS_L4_MODE_SH);
2014 	val = l4b0_val;
2015 	ip_cls_cfg.value |= (val << L3_UCLS_L4B0_VAL_SH);
2016 	val = l4b0_msk;
2017 	ip_cls_cfg.value |= (val << L3_UCLS_L4B0_MASK_SH);
2018 	val = l4b23_sel;
2019 	ip_cls_cfg.value |= (val << L3_UCLS_L4B23_SEL_SH);
2020 	val = l4b23_val;
2021 	ip_cls_cfg.value |= (val << L3_UCLS_L4B23_VAL_SH);
2022 
2023 	ip_cls_cfg.bits.ldw.valid = 0;
2024 	REG_PIO_WRITE64(handle, offset, ip_cls_cfg.value);
2025 	return (NPI_SUCCESS);
2026 }
2027 
2028 /*
2029  * npi_fflp_cfg_ip_usr_cls_get_iptun()
2030  * Retrieves the IP tunneling related settings for the given TCAM user
2031  * configurable IP classe.
2032  *
2033  * Input
2034  *      handle:		opaque handle interpreted by the underlying OS
2035  *      class:       IP Class  class
2036  *		     (TCAM_CLASS_IP_USER_4 <= class <= TCAM_CLASS_IP_USER_7)
2037  *	l4b0_val	value of the first L4 byte to be compared
2038  *	l4b0_msk	mask to apply to compare byte 0 of L4
2039  *	l4b23_val	values of L4 bytes 2 and 3 to compare
2040  *	l4b23_sel	set to 1 to compare L4 bytes 2 and 3.
2041  * by default, the class is disabled until explicitly enabled
2042  *
2043  * Return
2044  * NPI success/failure status code
2045  */
2046 npi_status_t
2047 npi_fflp_cfg_ip_usr_cls_get_iptun(npi_handle_t handle, tcam_class_t class,
2048 			    uint8_t *l4b0_val, uint8_t *l4b0_msk,
2049 			    uint16_t *l4b23_val, uint8_t *l4b23_sel)
2050 {
2051 	uint64_t offset;
2052 	tcam_class_prg_ip_t ip_cls_cfg;
2053 
2054 	ASSERT(TCAM_L3_USR_CLASS_VALID(class));
2055 	if (!TCAM_L3_USR_CLASS_VALID(class)) {
2056 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
2057 		    " npi_fflp_cfg_ip_usr_cls_set:"
2058 		    " Invalid class %d \n",
2059 		    class));
2060 		return (NPI_FFLP_TCAM_CLASS_INVALID);
2061 	}
2062 
2063 	offset = GET_TCAM_CLASS_OFFSET(class);
2064 	REG_PIO_READ64(handle, offset, &ip_cls_cfg.value);
2065 
2066 	*l4b0_val = (ip_cls_cfg.value >> L3_UCLS_L4B0_VAL_SH) &
2067 	    L3_UCLS_L4B0_VAL_MSK;
2068 	*l4b0_msk = (ip_cls_cfg.value >> L3_UCLS_L4B0_MASK_SH) &
2069 	    L3_UCLS_L4B0_MASK_MSK;
2070 	*l4b23_sel = (ip_cls_cfg.value >> L3_UCLS_L4B23_SEL_SH) &
2071 	    L3_UCLS_L4B23_SEL_MSK;
2072 	*l4b23_val = (ip_cls_cfg.value >> L3_UCLS_L4B23_VAL_SH) &
2073 	    L3_UCLS_L4B23_VAL_MSK;
2074 
2075 	return (NPI_SUCCESS);
2076 
2077 }
2078 
2079 /*
2080  * npi_fflp_cfg_ip_usr_cls_enable()
2081  * Enable previously configured TCAM user configurable IP classes.
2082  *
2083  * Input
2084  *      handle:	opaque handle interpreted by the underlying OS
2085  *      class:       IP Class  class
2086  *		     (TCAM_CLASS_IP_USER_4 <= class <= TCAM_CLASS_IP_USER_7)
2087  *
2088  * Return
2089  * NPI success/failure status code
2090  */
2091 npi_status_t
2092 npi_fflp_cfg_ip_usr_cls_enable(npi_handle_t handle, tcam_class_t class)
2093 {
2094 	uint64_t offset;
2095 	tcam_class_prg_ip_t ip_cls_cfg;
2096 
2097 	ASSERT(TCAM_L3_USR_CLASS_VALID(class));
2098 	if (!TCAM_L3_USR_CLASS_VALID(class)) {
2099 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
2100 		    " npi_fflp_cfg_ip_usr_cls_enable:"
2101 		    " Invalid class %d \n",
2102 		    class));
2103 		return (NPI_FFLP_TCAM_CLASS_INVALID);
2104 	}
2105 
2106 	offset = GET_TCAM_CLASS_OFFSET(class);
2107 	REG_PIO_READ64(handle, offset, &ip_cls_cfg.value);
2108 	ip_cls_cfg.bits.ldw.valid = 1;
2109 
2110 	REG_PIO_WRITE64(handle, offset, ip_cls_cfg.value);
2111 	return (NPI_SUCCESS);
2112 
2113 }
2114 
2115 /*
2116  * npi_fflp_cfg_ip_usr_cls_disable()
2117  * Disables previously configured TCAM user configurable IP classes.
2118  *
2119  * Input
2120  *      handle:	opaque handle interpreted by the underlying OS
2121  *      class:       IP Class  class
2122  *		     (TCAM_CLASS_IP_USER_4 <= class <= TCAM_CLASS_IP_USER_7)
2123  *
2124  * Return
2125  * NPI success/failure status code
2126  */
2127 npi_status_t
2128 npi_fflp_cfg_ip_usr_cls_disable(npi_handle_t handle, tcam_class_t class)
2129 {
2130 	uint64_t offset;
2131 	tcam_class_prg_ip_t ip_cls_cfg;
2132 
2133 	ASSERT(TCAM_L3_USR_CLASS_VALID(class));
2134 	if (!TCAM_L3_USR_CLASS_VALID(class)) {
2135 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
2136 		    " npi_fflp_cfg_ip_usr_cls_disable:"
2137 		    " Invalid class %d \n",
2138 		    class));
2139 		return (NPI_FFLP_TCAM_CLASS_INVALID);
2140 	}
2141 
2142 	offset = GET_TCAM_CLASS_OFFSET(class);
2143 
2144 	REG_PIO_READ64(handle, offset, &ip_cls_cfg.value);
2145 	ip_cls_cfg.bits.ldw.valid = 0;
2146 
2147 	REG_PIO_WRITE64(handle, offset, ip_cls_cfg.value);
2148 	return (NPI_SUCCESS);
2149 
2150 }
2151 
2152 /*
2153  * npi_fflp_cfg_ip_cls_tcam_key ()
2154  *
2155  * Configures the TCAM key generation for the IP classes
2156  *
2157  * Input
2158  *      handle:	opaque handle interpreted by the underlying OS
2159  *      l3_class:        IP class to configure key generation
2160  *      cfg:             Configuration bits:
2161  *                   discard:      Discard all frames of this class
2162  *                   use_ip_saddr: use ip src address (for ipv6)
2163  *                   use_ip_daddr: use ip dest address (for ipv6)
2164  *                   lookup_enable: Enable Lookup
2165  *
2166  *
2167  * Return
2168  * NPI success/failure status code
2169  */
2170 npi_status_t
2171 npi_fflp_cfg_ip_cls_tcam_key(npi_handle_t handle,
2172 			    tcam_class_t l3_class, tcam_key_cfg_t *cfg)
2173 {
2174 	uint64_t offset;
2175 	tcam_class_key_ip_t tcam_cls_cfg;
2176 
2177 	ASSERT(TCAM_L3_CLASS_VALID(l3_class));
2178 	if (!(TCAM_L3_CLASS_VALID(l3_class))) {
2179 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
2180 		    " npi_fflp_cfg_ip_cls_tcam_key:"
2181 		    " Invalid class %d \n",
2182 		    l3_class));
2183 		return (NPI_FFLP_TCAM_CLASS_INVALID);
2184 	}
2185 
2186 	if ((cfg->use_ip_daddr) &&
2187 	    (cfg->use_ip_saddr == cfg->use_ip_daddr)) {
2188 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
2189 		    " npi_fflp_cfg_ip_cls_tcam_key:"
2190 		    " Invalid configuration %x for class %d \n",
2191 		    *cfg, l3_class));
2192 		return (NPI_FFLP_SW_PARAM_ERROR);
2193 	}
2194 
2195 
2196 	offset = GET_TCAM_KEY_OFFSET(l3_class);
2197 	tcam_cls_cfg.value = 0;
2198 
2199 	if (cfg->discard) {
2200 		tcam_cls_cfg.bits.ldw.discard = 1;
2201 	}
2202 
2203 	if (cfg->use_ip_saddr) {
2204 		tcam_cls_cfg.bits.ldw.ipaddr = 1;
2205 	}
2206 
2207 	if (cfg->use_ip_daddr) {
2208 		tcam_cls_cfg.bits.ldw.ipaddr = 0;
2209 	}
2210 
2211 	if (cfg->lookup_enable) {
2212 		tcam_cls_cfg.bits.ldw.tsel = 1;
2213 	}
2214 
2215 	REG_PIO_WRITE64(handle, offset, tcam_cls_cfg.value);
2216 	return (NPI_SUCCESS);
2217 }
2218 
2219 /*
2220  * npi_fflp_cfg_ip_cls_flow_key ()
2221  *
2222  * Configures the flow key generation for the IP classes
2223  * Flow key is used to generate the H1 hash function value
2224  * The fields used for the generation are configured using this
2225  * NPI function.
2226  *
2227  * Input
2228  *      handle:	opaque handle interpreted by the underlying OS
2229  *      l3_class:        IP class to configure flow key generation
2230  *      cfg:             Configuration bits:
2231  *                   use_proto:     Use IP proto field
2232  *                   use_dport:     use l4 destination port
2233  *                   use_sport:     use l4 source port
2234  *                   ip_opts_exist: IP Options Present
2235  *                   use_daddr:     use ip dest address
2236  *                   use_saddr:     use ip source address
2237  *                   use_vlan:      use VLAN ID
2238  *                   use_l2da:      use L2 Dest MAC Address
2239  *                   use_portnum:   use L2 virtual port number
2240  *
2241  *
2242  * Return
2243  * NPI success/failure status code
2244  */
2245 npi_status_t
2246 npi_fflp_cfg_ip_cls_flow_key(npi_handle_t handle, tcam_class_t l3_class,
2247 							    flow_key_cfg_t *cfg)
2248 {
2249 	uint64_t offset;
2250 	flow_class_key_ip_t flow_cfg_reg;
2251 
2252 	ASSERT(TCAM_L3_CLASS_VALID(l3_class));
2253 	if (!(TCAM_L3_CLASS_VALID(l3_class))) {
2254 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
2255 		    " npi_fflp_cfg_ip_cls_flow_key:"
2256 		    " Invalid class %d \n",
2257 		    l3_class));
2258 		return (NPI_FFLP_TCAM_CLASS_INVALID);
2259 	}
2260 
2261 
2262 	offset = GET_FLOW_KEY_OFFSET(l3_class);
2263 	flow_cfg_reg.value = 0; /* default */
2264 
2265 	if (cfg->use_proto) {
2266 		flow_cfg_reg.bits.ldw.proto = 1;
2267 	}
2268 
2269 	if (cfg->use_dport) {
2270 		flow_cfg_reg.bits.ldw.l4_1 = 2;
2271 		if (cfg->ip_opts_exist)
2272 			flow_cfg_reg.bits.ldw.l4_1 = 3;
2273 	}
2274 
2275 	if (cfg->use_sport) {
2276 		flow_cfg_reg.bits.ldw.l4_0 = 2;
2277 		if (cfg->ip_opts_exist)
2278 			flow_cfg_reg.bits.ldw.l4_0 = 3;
2279 	}
2280 
2281 	if (cfg->use_daddr) {
2282 		flow_cfg_reg.bits.ldw.ipda = BIT_ENABLE;
2283 	}
2284 
2285 	if (cfg->use_saddr) {
2286 		flow_cfg_reg.bits.ldw.ipsa = BIT_ENABLE;
2287 	}
2288 
2289 	if (cfg->use_vlan) {
2290 		flow_cfg_reg.bits.ldw.vlan = BIT_ENABLE;
2291 	}
2292 
2293 	if (cfg->use_l2da) {
2294 		flow_cfg_reg.bits.ldw.l2da = BIT_ENABLE;
2295 	}
2296 
2297 	if (cfg->use_portnum) {
2298 		flow_cfg_reg.bits.ldw.port = BIT_ENABLE;
2299 	}
2300 
2301 	REG_PIO_WRITE64(handle, offset, flow_cfg_reg.value);
2302 	return (NPI_SUCCESS);
2303 
2304 }
2305 
2306 npi_status_t
2307 npi_fflp_cfg_ip_cls_flow_key_get(npi_handle_t handle,
2308 				    tcam_class_t l3_class,
2309 				    flow_key_cfg_t *cfg)
2310 {
2311 	uint64_t offset;
2312 	flow_class_key_ip_t flow_cfg_reg;
2313 
2314 	ASSERT(TCAM_L3_CLASS_VALID(l3_class));
2315 	if (!(TCAM_L3_CLASS_VALID(l3_class))) {
2316 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
2317 		    " npi_fflp_cfg_ip_cls_flow_key:"
2318 		    " Invalid class %d \n",
2319 		    l3_class));
2320 		return (NPI_FFLP_TCAM_CLASS_INVALID);
2321 	}
2322 
2323 	offset = GET_FLOW_KEY_OFFSET(l3_class);
2324 
2325 	cfg->use_proto = 0;
2326 	cfg->use_dport = 0;
2327 	cfg->use_sport = 0;
2328 	cfg->ip_opts_exist = 0;
2329 	cfg->use_daddr = 0;
2330 	cfg->use_saddr = 0;
2331 	cfg->use_vlan = 0;
2332 	cfg->use_l2da = 0;
2333 	cfg->use_portnum  = 0;
2334 
2335 	REG_PIO_READ64(handle, offset, &flow_cfg_reg.value);
2336 
2337 	if (flow_cfg_reg.bits.ldw.proto) {
2338 		cfg->use_proto = 1;
2339 	}
2340 
2341 	if (flow_cfg_reg.bits.ldw.l4_1 == 2) {
2342 		cfg->use_dport = 1;
2343 	}
2344 
2345 	if (flow_cfg_reg.bits.ldw.l4_1 == 3) {
2346 		cfg->use_dport = 1;
2347 		cfg->ip_opts_exist = 1;
2348 	}
2349 
2350 	if (flow_cfg_reg.bits.ldw.l4_0 == 2) {
2351 		cfg->use_sport = 1;
2352 	}
2353 
2354 	if (flow_cfg_reg.bits.ldw.l4_0 == 3) {
2355 		cfg->use_sport = 1;
2356 		cfg->ip_opts_exist = 1;
2357 	}
2358 
2359 	if (flow_cfg_reg.bits.ldw.ipda) {
2360 		cfg->use_daddr = 1;
2361 	}
2362 
2363 	if (flow_cfg_reg.bits.ldw.ipsa) {
2364 		cfg->use_saddr = 1;
2365 	}
2366 
2367 	if (flow_cfg_reg.bits.ldw.vlan) {
2368 		cfg->use_vlan = 1;
2369 	}
2370 
2371 	if (flow_cfg_reg.bits.ldw.l2da) {
2372 		cfg->use_l2da = 1;
2373 	}
2374 
2375 	if (flow_cfg_reg.bits.ldw.port) {
2376 		cfg->use_portnum = 1;
2377 	}
2378 
2379 	NPI_DEBUG_MSG((handle.function, NPI_FFLP_CTL,
2380 	    " npi_fflp_cfg_ip_cls_flow_get %llx \n",
2381 	    flow_cfg_reg.value));
2382 
2383 	return (NPI_SUCCESS);
2384 
2385 }
2386 
2387 /*
2388  * npi_fflp_cfg_ip_cls_flow_key_rfnl ()
2389  *
2390  * Configures the flow key generation for the IP classes
2391  * Flow key is used to generate the H1 hash function value
2392  * The fields used for the generation are configured using this
2393  * NPI function.
2394  *
2395  * Input
2396  *      handle:	opaque handle interpreted by the underlying OS
2397  *      l3_class:        IP class to configure flow key generation
2398  *      cfg:             Configuration bits:
2399  *		     l4_xor_sel:    bit field to select the L4 payload
2400  *				    bytes for X-OR to get hash key.
2401  *		     use_l4_md:	    Set to 1 for enabling L4-mode.
2402  *		     use_sym:	    Set to 1 to use symmetric mode.
2403  *                   use_proto:     Use IP proto field
2404  *                   use_dport:     use l4 destination port
2405  *                   use_sport:     use l4 source port
2406  *                   ip_opts_exist: IP Options Present
2407  *                   use_daddr:     use ip dest address
2408  *                   use_saddr:     use ip source address
2409  *                   use_vlan:      use VLAN ID
2410  *                   use_l2da:      use L2 Dest MAC Address
2411  *                   use_portnum:   use L2 virtual port number
2412  *
2413  *
2414  * Return
2415  * NPI success/failure status code
2416  */
2417 npi_status_t
2418 npi_fflp_cfg_ip_cls_flow_key_rfnl(npi_handle_t handle, tcam_class_t l3_class,
2419 		flow_key_cfg_t *cfg)
2420 {
2421 	uint64_t offset;
2422 	flow_class_key_ip_t flow_cfg_reg;
2423 
2424 	ASSERT(TCAM_L3_CLASS_VALID_RFNL(l3_class));
2425 	if (!(TCAM_L3_CLASS_VALID_RFNL(l3_class))) {
2426 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
2427 		    " npi_fflp_cfg_ip_cls_flow_key_rfnl:"
2428 		    " Invalid class %d \n",
2429 		    l3_class));
2430 		return (NPI_FFLP_TCAM_CLASS_INVALID);
2431 	}
2432 
2433 	if (l3_class == TCAM_CLASS_IPV6_FRAG) {
2434 		offset = FFLP_FLOW_KEY_IP6_FRAG_REG;
2435 	} else {
2436 		offset = GET_FLOW_KEY_OFFSET(l3_class);
2437 	}
2438 
2439 	flow_cfg_reg.value = 0;
2440 
2441 	flow_cfg_reg.bits.ldw.l4_xor = cfg->l4_xor_sel;
2442 
2443 	if (cfg->use_l4_md)
2444 		flow_cfg_reg.bits.ldw.l4_mode = 1;
2445 
2446 	if (cfg->use_sym)
2447 		flow_cfg_reg.bits.ldw.sym = 1;
2448 
2449 	if (cfg->use_proto) {
2450 		flow_cfg_reg.bits.ldw.proto = 1;
2451 	}
2452 
2453 	if (cfg->use_dport) {
2454 		flow_cfg_reg.bits.ldw.l4_1 = 2;
2455 		if (cfg->ip_opts_exist)
2456 			flow_cfg_reg.bits.ldw.l4_1 = 3;
2457 	}
2458 
2459 	if (cfg->use_sport) {
2460 		flow_cfg_reg.bits.ldw.l4_0 = 2;
2461 		if (cfg->ip_opts_exist)
2462 			flow_cfg_reg.bits.ldw.l4_0 = 3;
2463 	}
2464 
2465 	if (cfg->use_daddr) {
2466 		flow_cfg_reg.bits.ldw.ipda = BIT_ENABLE;
2467 	}
2468 
2469 	if (cfg->use_saddr) {
2470 		flow_cfg_reg.bits.ldw.ipsa = BIT_ENABLE;
2471 	}
2472 
2473 	if (cfg->use_vlan) {
2474 		flow_cfg_reg.bits.ldw.vlan = BIT_ENABLE;
2475 	}
2476 
2477 	if (cfg->use_l2da) {
2478 		flow_cfg_reg.bits.ldw.l2da = BIT_ENABLE;
2479 	}
2480 
2481 	if (cfg->use_portnum) {
2482 		flow_cfg_reg.bits.ldw.port = BIT_ENABLE;
2483 	}
2484 
2485 	REG_PIO_WRITE64(handle, offset, flow_cfg_reg.value);
2486 	return (NPI_SUCCESS);
2487 
2488 }
2489 
2490 npi_status_t
2491 npi_fflp_cfg_sym_ip_cls_flow_key(npi_handle_t handle, tcam_class_t l3_class,
2492 		boolean_t enable)
2493 {
2494 	uint64_t offset;
2495 	flow_class_key_ip_t flow_cfg_reg;
2496 
2497 	ASSERT(TCAM_L3_CLASS_VALID_RFNL(l3_class));
2498 	if (!(TCAM_L3_CLASS_VALID_RFNL(l3_class))) {
2499 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
2500 		    " npi_fflp_cfg_sym_ip_cls_flow_key:"
2501 		    " Invalid class %d \n",
2502 		    l3_class));
2503 		return (NPI_FFLP_TCAM_CLASS_INVALID);
2504 	}
2505 
2506 	if (l3_class == TCAM_CLASS_IPV6_FRAG) {
2507 		offset = FFLP_FLOW_KEY_IP6_FRAG_REG;
2508 	} else {
2509 		offset = GET_FLOW_KEY_OFFSET(l3_class);
2510 	}
2511 
2512 	REG_PIO_READ64(handle, offset, &flow_cfg_reg.value);
2513 
2514 	if (enable && flow_cfg_reg.bits.ldw.sym == 0) {
2515 		flow_cfg_reg.bits.ldw.sym = 1;
2516 		REG_PIO_WRITE64(handle, offset, flow_cfg_reg.value);
2517 	} else if (!enable && flow_cfg_reg.bits.ldw.sym == 1) {
2518 		flow_cfg_reg.bits.ldw.sym = 0;
2519 		REG_PIO_WRITE64(handle, offset, flow_cfg_reg.value);
2520 	}
2521 
2522 	return (NPI_SUCCESS);
2523 
2524 }
2525 
2526 npi_status_t
2527 npi_fflp_cfg_ip_cls_flow_key_get_rfnl(npi_handle_t handle,
2528 				    tcam_class_t l3_class,
2529 				    flow_key_cfg_t *cfg)
2530 {
2531 	uint64_t offset;
2532 	flow_class_key_ip_t flow_cfg_reg;
2533 
2534 	ASSERT(TCAM_L3_CLASS_VALID_RFNL(l3_class));
2535 	if (!(TCAM_L3_CLASS_VALID_RFNL(l3_class))) {
2536 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
2537 		    " npi_fflp_cfg_ip_cls_flow_key_get_rfnl:"
2538 		    " Invalid class %d \n",
2539 		    l3_class));
2540 		return (NPI_FFLP_TCAM_CLASS_INVALID);
2541 	}
2542 
2543 	if (l3_class == TCAM_CLASS_IPV6_FRAG) {
2544 		offset = FFLP_FLOW_KEY_IP6_FRAG_REG;
2545 	} else {
2546 		offset = GET_FLOW_KEY_OFFSET(l3_class);
2547 	}
2548 
2549 	cfg->l4_xor_sel = 0;
2550 	cfg->use_l4_md = 0;
2551 	cfg->use_sym = 0;
2552 	cfg->use_proto = 0;
2553 	cfg->use_dport = 0;
2554 	cfg->use_sport = 0;
2555 	cfg->ip_opts_exist = 0;
2556 	cfg->use_daddr = 0;
2557 	cfg->use_saddr = 0;
2558 	cfg->use_vlan = 0;
2559 	cfg->use_l2da = 0;
2560 	cfg->use_portnum  = 0;
2561 
2562 	REG_PIO_READ64(handle, offset, &flow_cfg_reg.value);
2563 
2564 	cfg->l4_xor_sel = flow_cfg_reg.bits.ldw.l4_xor;
2565 
2566 	if (flow_cfg_reg.bits.ldw.l4_mode)
2567 		cfg->use_l4_md = 1;
2568 
2569 	if (flow_cfg_reg.bits.ldw.sym)
2570 		cfg->use_sym = 1;
2571 
2572 	if (flow_cfg_reg.bits.ldw.proto) {
2573 		cfg->use_proto = 1;
2574 	}
2575 
2576 	if (flow_cfg_reg.bits.ldw.l4_1 == 2) {
2577 		cfg->use_dport = 1;
2578 	}
2579 
2580 	if (flow_cfg_reg.bits.ldw.l4_1 == 3) {
2581 		cfg->use_dport = 1;
2582 		cfg->ip_opts_exist = 1;
2583 	}
2584 
2585 	if (flow_cfg_reg.bits.ldw.l4_0 == 2) {
2586 		cfg->use_sport = 1;
2587 	}
2588 
2589 	if (flow_cfg_reg.bits.ldw.l4_0 == 3) {
2590 		cfg->use_sport = 1;
2591 		cfg->ip_opts_exist = 1;
2592 	}
2593 
2594 	if (flow_cfg_reg.bits.ldw.ipda) {
2595 		cfg->use_daddr = 1;
2596 	}
2597 
2598 	if (flow_cfg_reg.bits.ldw.ipsa) {
2599 		cfg->use_saddr = 1;
2600 	}
2601 
2602 	if (flow_cfg_reg.bits.ldw.vlan) {
2603 		cfg->use_vlan = 1;
2604 	}
2605 
2606 	if (flow_cfg_reg.bits.ldw.l2da) {
2607 		cfg->use_l2da = 1;
2608 	}
2609 
2610 	if (flow_cfg_reg.bits.ldw.port) {
2611 		cfg->use_portnum = 1;
2612 	}
2613 
2614 	NPI_DEBUG_MSG((handle.function, NPI_FFLP_CTL,
2615 	    " npi_fflp_cfg_ip_cls_flow_get %llx \n",
2616 	    flow_cfg_reg.value));
2617 
2618 	return (NPI_SUCCESS);
2619 
2620 }
2621 
2622 npi_status_t
2623 npi_fflp_cfg_ip_cls_tcam_key_get(npi_handle_t handle,
2624 			    tcam_class_t l3_class, tcam_key_cfg_t *cfg)
2625 {
2626 	uint64_t offset;
2627 	tcam_class_key_ip_t tcam_cls_cfg;
2628 
2629 	ASSERT(TCAM_L3_CLASS_VALID(l3_class));
2630 	if (!(TCAM_L3_CLASS_VALID(l3_class))) {
2631 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
2632 		    " npi_fflp_cfg_ip_cls_tcam_key_get:"
2633 		    " Invalid class %d \n",
2634 		    l3_class));
2635 		return (NPI_FFLP_TCAM_CLASS_INVALID);
2636 	}
2637 
2638 
2639 	offset = GET_TCAM_KEY_OFFSET(l3_class);
2640 
2641 	REG_PIO_READ64(handle, offset, &tcam_cls_cfg.value);
2642 
2643 	cfg->discard = 0;
2644 	cfg->use_ip_saddr = 0;
2645 	cfg->use_ip_daddr = 1;
2646 	cfg->lookup_enable = 0;
2647 
2648 	if (tcam_cls_cfg.bits.ldw.discard)
2649 			cfg->discard = 1;
2650 
2651 	if (tcam_cls_cfg.bits.ldw.ipaddr) {
2652 		cfg->use_ip_saddr = 1;
2653 		cfg->use_ip_daddr = 0;
2654 	}
2655 
2656 	if (tcam_cls_cfg.bits.ldw.tsel) {
2657 		cfg->lookup_enable = 1;
2658 	}
2659 
2660 	NPI_DEBUG_MSG((handle.function, NPI_CTL,
2661 	    " npi_fflp_cfg_ip_cls_tcam_key_get %llx \n",
2662 	    tcam_cls_cfg.value));
2663 	return (NPI_SUCCESS);
2664 }
2665 
2666 /*
2667  * npi_fflp_cfg_fcram_access ()
2668  *
2669  * Sets the ratio between the FCRAM pio and lookup access
2670  * Input:
2671  * handle:	opaque handle interpreted by the underlying OS
2672  * access_ratio: 0  Lookup has the highest priority
2673  *		 15 PIO has maximum possible priority
2674  *
2675  * Return
2676  * NPI success/failure status code
2677  */
2678 npi_status_t
2679 npi_fflp_cfg_fcram_access(npi_handle_t handle, uint8_t access_ratio)
2680 {
2681 
2682 	fflp_cfg_1_t fflp_cfg;
2683 	uint64_t offset;
2684 	offset = FFLP_CFG_1_REG;
2685 
2686 	if (access_ratio > 0xf) {
2687 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
2688 		    " npi_fflp_cfg_fcram_access:"
2689 		    " Invalid access ratio %d \n",
2690 		    access_ratio));
2691 		return (NPI_FFLP_ERROR | NPI_FFLP_SW_PARAM_ERROR);
2692 	}
2693 
2694 	REG_PIO_READ64(handle, offset, &fflp_cfg.value);
2695 	fflp_cfg.bits.ldw.fflpinitdone = 0;
2696 	fflp_cfg.bits.ldw.fcramratio = access_ratio;
2697 	REG_PIO_WRITE64(handle, offset, fflp_cfg.value);
2698 	REG_PIO_READ64(handle, offset, &fflp_cfg.value);
2699 	fflp_cfg.bits.ldw.fflpinitdone = 1;
2700 	REG_PIO_WRITE64(handle, offset, fflp_cfg.value);
2701 	return (NPI_SUCCESS);
2702 
2703 }
2704 
2705 /*
2706  * npi_fflp_cfg_tcam_access ()
2707  *
2708  * Sets the ratio between the TCAM pio and lookup access
2709  * Input:
2710  * handle:	opaque handle interpreted by the underlying OS
2711  * access_ratio: 0  Lookup has the highest priority
2712  *		 15 PIO has maximum possible priority
2713  * Return
2714  * NPI success/failure status code
2715  */
2716 npi_status_t
2717 npi_fflp_cfg_tcam_access(npi_handle_t handle, uint8_t access_ratio)
2718 {
2719 	fflp_cfg_1_t fflp_cfg;
2720 	uint64_t offset;
2721 	offset = FFLP_CFG_1_REG;
2722 
2723 	if (access_ratio > 0xf) {
2724 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
2725 		    " npi_fflp_cfg_tcram_access:"
2726 		    " Invalid access ratio %d \n",
2727 		    access_ratio));
2728 		return (NPI_FFLP_ERROR | NPI_FFLP_SW_PARAM_ERROR);
2729 	}
2730 
2731 	REG_PIO_READ64(handle, offset, &fflp_cfg.value);
2732 	fflp_cfg.bits.ldw.fflpinitdone = 0;
2733 	fflp_cfg.bits.ldw.camratio = access_ratio;
2734 
2735 	/* since the cam latency is fixed, we might set it here */
2736 	fflp_cfg.bits.ldw.camlatency = TCAM_DEFAULT_LATENCY;
2737 	REG_PIO_WRITE64(handle, offset, fflp_cfg.value);
2738 	REG_PIO_READ64(handle, offset, &fflp_cfg.value);
2739 	fflp_cfg.bits.ldw.fflpinitdone = 1;
2740 	REG_PIO_WRITE64(handle, offset, fflp_cfg.value);
2741 
2742 	return (NPI_SUCCESS);
2743 }
2744 
2745 /*
2746  * npi_fflp_cfg_hash_h1poly()
2747  * Initializes the H1 hash generation logic.
2748  *
2749  * Input
2750  *      handle:	opaque handle interpreted by the underlying OS
2751  *      init_value:       The initial value (seed)
2752  *
2753  * Return
2754  * NPI success/failure status code
2755  */
2756 npi_status_t
2757 npi_fflp_cfg_hash_h1poly(npi_handle_t handle, uint32_t init_value)
2758 {
2759 
2760 
2761 	hash_h1poly_t h1_cfg;
2762 	uint64_t offset;
2763 	offset = FFLP_H1POLY_REG;
2764 
2765 	h1_cfg.value = 0;
2766 	h1_cfg.bits.ldw.init_value = init_value;
2767 
2768 	REG_PIO_WRITE64(handle, offset, h1_cfg.value);
2769 	return (NPI_SUCCESS);
2770 }
2771 
2772 /*
2773  * npi_fflp_cfg_hash_h2poly()
2774  * Initializes the H2 hash generation logic.
2775  *
2776  * Input
2777  *      handle:	opaque handle interpreted by the underlying OS
2778  *      init_value:       The initial value (seed)
2779  *
2780  * Return
2781  * NPI_SUCCESS
2782  *
2783  */
2784 npi_status_t
2785 npi_fflp_cfg_hash_h2poly(npi_handle_t handle, uint16_t init_value)
2786 {
2787 
2788 
2789 	hash_h2poly_t h2_cfg;
2790 	uint64_t offset;
2791 	offset = FFLP_H2POLY_REG;
2792 
2793 	h2_cfg.value = 0;
2794 	h2_cfg.bits.ldw.init_value = init_value;
2795 
2796 	REG_PIO_WRITE64(handle, offset, h2_cfg.value);
2797 	return (NPI_SUCCESS);
2798 
2799 
2800 }
2801 
2802 /*
2803  *  npi_fflp_cfg_reset
2804  *  Initializes the FCRAM reset sequence.
2805  *
2806  *  Input
2807  *      handle:		opaque handle interpreted by the underlying OS
2808  *	strength:		FCRAM Drive strength
2809  *				   strong, weak or normal
2810  *				   HW recommended value:
2811  *	qs:			FCRAM QS mode selection
2812  *				   qs mode or free running
2813  *				   HW recommended value is:
2814  *
2815  * Return:
2816  * NPI success/failure status code
2817  */
2818 
2819 npi_status_t
2820 npi_fflp_cfg_fcram_reset(npi_handle_t handle,
2821 	fflp_fcram_output_drive_t strength, fflp_fcram_qs_t qs)
2822 {
2823 	fflp_cfg_1_t fflp_cfg;
2824 	uint64_t offset;
2825 	offset = FFLP_CFG_1_REG;
2826 
2827 	/* These bits have to be configured before FCRAM reset is issued */
2828 	fflp_cfg.value = 0;
2829 	fflp_cfg.bits.ldw.pio_fio_rst = 1;
2830 	REG_PIO_WRITE64(handle, offset, fflp_cfg.value);
2831 
2832 	NXGE_DELAY(5); /* TODO: What is the correct delay? */
2833 
2834 	fflp_cfg.bits.ldw.pio_fio_rst = 0;
2835 	REG_PIO_WRITE64(handle, offset, fflp_cfg.value);
2836 	fflp_cfg.bits.ldw.fcramqs = qs;
2837 	fflp_cfg.bits.ldw.fcramoutdr = strength;
2838 	fflp_cfg.bits.ldw.fflpinitdone = 1;
2839 	REG_PIO_WRITE64(handle, offset, fflp_cfg.value);
2840 
2841 	return (NPI_SUCCESS);
2842 }
2843 
2844 npi_status_t
2845 npi_fflp_cfg_init_done(npi_handle_t handle)
2846 
2847 {
2848 
2849 	fflp_cfg_1_t fflp_cfg;
2850 	uint64_t offset;
2851 	offset = FFLP_CFG_1_REG;
2852 
2853 	REG_PIO_READ64(handle, offset, &fflp_cfg.value);
2854 	fflp_cfg.bits.ldw.fflpinitdone = 1;
2855 	REG_PIO_WRITE64(handle, offset, fflp_cfg.value);
2856 	return (NPI_SUCCESS);
2857 
2858 }
2859 
2860 npi_status_t
2861 npi_fflp_cfg_init_start(npi_handle_t handle)
2862 
2863 {
2864 
2865 	fflp_cfg_1_t fflp_cfg;
2866 	uint64_t offset;
2867 	offset = FFLP_CFG_1_REG;
2868 
2869 	REG_PIO_READ64(handle, offset, &fflp_cfg.value);
2870 	fflp_cfg.bits.ldw.fflpinitdone = 0;
2871 	REG_PIO_WRITE64(handle, offset, fflp_cfg.value);
2872 	return (NPI_SUCCESS);
2873 
2874 }
2875 
2876 /*
2877  * Enables the TCAM search function.
2878  *
2879  */
2880 npi_status_t
2881 npi_fflp_cfg_tcam_enable(npi_handle_t handle)
2882 
2883 {
2884 
2885 	fflp_cfg_1_t fflp_cfg;
2886 	uint64_t offset;
2887 	offset = FFLP_CFG_1_REG;
2888 	REG_PIO_READ64(handle, offset, &fflp_cfg.value);
2889 	fflp_cfg.bits.ldw.tcam_disable = 0;
2890 	REG_PIO_WRITE64(handle, offset, fflp_cfg.value);
2891 	return (NPI_SUCCESS);
2892 
2893 }
2894 
2895 /*
2896  * Disables the TCAM search function.
2897  * While the TCAM is in disabled state, all TCAM matches would return NO_MATCH
2898  *
2899  */
2900 npi_status_t
2901 npi_fflp_cfg_tcam_disable(npi_handle_t handle)
2902 
2903 {
2904 
2905 	fflp_cfg_1_t fflp_cfg;
2906 	uint64_t offset;
2907 	offset = FFLP_CFG_1_REG;
2908 	REG_PIO_READ64(handle, offset, &fflp_cfg.value);
2909 	fflp_cfg.bits.ldw.tcam_disable = 1;
2910 	REG_PIO_WRITE64(handle, offset, fflp_cfg.value);
2911 	return (NPI_SUCCESS);
2912 
2913 }
2914 
2915 /*
2916  * npi_rxdma_event_mask_config():
2917  *	This function is called to operate on the event mask
2918  *	register which is used for generating interrupts
2919  *	and status register.
2920  */
2921 npi_status_t
2922 npi_fflp_event_mask_config(npi_handle_t handle, io_op_t op_mode,
2923 		fflp_event_mask_cfg_t *mask_cfgp)
2924 {
2925 	int		status = NPI_SUCCESS;
2926 	fflp_err_mask_t mask_reg;
2927 
2928 	switch (op_mode) {
2929 	case OP_GET:
2930 
2931 		REG_PIO_READ64(handle, FFLP_ERR_MSK_REG, &mask_reg.value);
2932 		*mask_cfgp = mask_reg.value & FFLP_ERR_MASK_ALL;
2933 		break;
2934 
2935 	case OP_SET:
2936 		mask_reg.value = (~(*mask_cfgp) & FFLP_ERR_MASK_ALL);
2937 		REG_PIO_WRITE64(handle, FFLP_ERR_MSK_REG, mask_reg.value);
2938 		break;
2939 
2940 	case OP_UPDATE:
2941 		REG_PIO_READ64(handle, FFLP_ERR_MSK_REG, &mask_reg.value);
2942 		mask_reg.value |=  (~(*mask_cfgp) & FFLP_ERR_MASK_ALL);
2943 		REG_PIO_WRITE64(handle, FFLP_ERR_MSK_REG, mask_reg.value);
2944 		break;
2945 
2946 	case OP_CLEAR:
2947 		mask_reg.value = FFLP_ERR_MASK_ALL;
2948 		REG_PIO_WRITE64(handle, FFLP_ERR_MSK_REG, mask_reg.value);
2949 		break;
2950 	default:
2951 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
2952 		    " npi_fflp_event_mask_config",
2953 		    " eventmask <0x%x>", op_mode));
2954 		return (NPI_FFLP_ERROR | NPI_FFLP_SW_PARAM_ERROR);
2955 	}
2956 
2957 	return (status);
2958 }
2959 
2960 /*
2961  * Read vlan error bits
2962  */
2963 void
2964 npi_fflp_vlan_error_get(npi_handle_t handle, p_vlan_par_err_t p_err)
2965 {
2966 	REG_PIO_READ64(handle, FFLP_VLAN_PAR_ERR_REG, &p_err->value);
2967 }
2968 
2969 /*
2970  * clear vlan error bits
2971  */
2972 void
2973 npi_fflp_vlan_error_clear(npi_handle_t handle)
2974 {
2975 	vlan_par_err_t p_err;
2976 	p_err.value  = 0;
2977 	p_err.bits.ldw.m_err = 0;
2978 	p_err.bits.ldw.err = 0;
2979 	REG_PIO_WRITE64(handle, FFLP_ERR_MSK_REG, p_err.value);
2980 
2981 }
2982 
2983 /*
2984  * Read TCAM error bits
2985  */
2986 void
2987 npi_fflp_tcam_error_get(npi_handle_t handle, p_tcam_err_t p_err)
2988 {
2989 	REG_PIO_READ64(handle, FFLP_TCAM_ERR_REG, &p_err->value);
2990 }
2991 
2992 /*
2993  * clear TCAM error bits
2994  */
2995 void
2996 npi_fflp_tcam_error_clear(npi_handle_t handle)
2997 {
2998 	tcam_err_t p_err;
2999 
3000 	p_err.value  = 0;
3001 	p_err.bits.ldw.p_ecc = 0;
3002 	p_err.bits.ldw.mult = 0;
3003 	p_err.bits.ldw.err = 0;
3004 	REG_PIO_WRITE64(handle, FFLP_TCAM_ERR_REG, p_err.value);
3005 
3006 }
3007 
3008 /*
3009  * Read FCRAM error bits
3010  */
3011 void
3012 npi_fflp_fcram_error_get(npi_handle_t handle,
3013 	p_hash_tbl_data_log_t p_err, uint8_t partition)
3014 {
3015 	uint64_t offset;
3016 
3017 	offset = FFLP_HASH_TBL_DATA_LOG_REG + partition * 8192;
3018 	REG_PIO_READ64(handle, offset, &p_err->value);
3019 }
3020 
3021 /*
3022  * clear FCRAM error bits
3023  */
3024 void
3025 npi_fflp_fcram_error_clear(npi_handle_t handle, uint8_t partition)
3026 {
3027 	hash_tbl_data_log_t p_err;
3028 	uint64_t offset;
3029 
3030 	p_err.value  = 0;
3031 	p_err.bits.ldw.pio_err = 0;
3032 	offset = FFLP_HASH_TBL_DATA_LOG_REG + partition * 8192;
3033 
3034 	REG_PIO_WRITE64(handle, offset,
3035 	    p_err.value);
3036 
3037 }
3038 
3039 /*
3040  * Read FCRAM lookup error log1 bits
3041  */
3042 void
3043 npi_fflp_fcram_error_log1_get(npi_handle_t handle,
3044 			    p_hash_lookup_err_log1_t log1)
3045 {
3046 	REG_PIO_READ64(handle, HASH_LKUP_ERR_LOG1_REG,
3047 	    &log1->value);
3048 }
3049 
3050 /*
3051  * Read FCRAM lookup error log2 bits
3052  */
3053 void
3054 npi_fflp_fcram_error_log2_get(npi_handle_t handle,
3055 		    p_hash_lookup_err_log2_t log2)
3056 {
3057 	REG_PIO_READ64(handle, HASH_LKUP_ERR_LOG2_REG,
3058 	    &log2->value);
3059 }
3060