xref: /illumos-gate/usr/src/uts/common/io/nxge/npi/npi_fflp.c (revision 08855964b9970604433f7b19dcd71cf5af5e5f14)
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 aligned */
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 aligned */
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 aligned */
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 aligned */
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 aligned */
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 aligned */
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 aligned */
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 aligned */
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 	 * assumes that the base mask and relocation are computed somewhere
964 	 * and kept in the state data structure. Alternativiely, one can pass
965 	 * a partition size and a starting address and this routine can compute
966 	 * the mask and reloc vlaues.
967 	 */
968 
969 	flow_prt_sel_t sel;
970 	uint64_t offset;
971 
972 	ASSERT(FCRAM_PARTITION_VALID(partid));
973 	if (!FCRAM_PARTITION_VALID(partid)) {
974 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
975 				    " npi_fflp_cfg_fcram_partition:"
976 				    " Invalid Partition %d \n",
977 				    partid));
978 		return (NPI_FFLP_FCRAM_PART_INVALID);
979 	}
980 
981 	offset = FFLP_PART_OFFSET(partid, FFLP_FLW_PRT_SEL_REG);
982 	sel.value = 0;
983 	sel.bits.ldw.mask = base_mask;
984 	sel.bits.ldw.base = base_reloc;
985 	sel.bits.ldw.ext = BIT_DISABLE; /* disable */
986 	REG_PIO_WRITE64(handle, offset, sel.value);
987 	return (NPI_SUCCESS);
988 }
989 
990 /*
991  * npi_fflp_fcram_partition_enable
992  * Enable previously configured FCRAM partition
993  *
994  * Input
995  *         handle:	opaque handle interpreted by the underlying OS
996  *         partid:	 partition ID, Corresponds to the RDC table
997  *
998  * Return
999  *      0			Successful
1000  *      Non zero  error code    Enable failed, and reason.
1001  *
1002  */
1003 npi_status_t
1004 npi_fflp_cfg_fcram_partition_enable  (npi_handle_t handle, part_id_t partid)
1005 
1006 {
1007 
1008     flow_prt_sel_t sel;
1009     uint64_t offset;
1010 
1011     ASSERT(FCRAM_PARTITION_VALID(partid));
1012     if (!FCRAM_PARTITION_VALID(partid)) {
1013 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
1014 				    " fcram_partition enable:"
1015 				    " Invalid Partition %d \n",
1016 				    partid));
1017 		return (NPI_FFLP_FCRAM_PART_INVALID);
1018 	}
1019 
1020     offset = FFLP_PART_OFFSET(partid, FFLP_FLW_PRT_SEL_REG);
1021 
1022     REG_PIO_READ64(handle, offset, &sel.value);
1023     sel.bits.ldw.ext = BIT_ENABLE; /* enable */
1024     REG_PIO_WRITE64(handle, offset, sel.value);
1025 
1026     return (NPI_SUCCESS);
1027 
1028 }
1029 
1030 /*
1031  * npi_fflp_fcram_partition_disable
1032  * Disable previously configured FCRAM partition
1033  *
1034  * Input
1035  *         handle:	opaque handle interpreted by the underlying OS
1036  *         partid:	partition ID, Corresponds to the RDC table
1037  *
1038  * Return:
1039  * NPI Success/Failure status code
1040  */
1041 npi_status_t
1042 npi_fflp_cfg_fcram_partition_disable(npi_handle_t handle, part_id_t partid)
1043 
1044 {
1045 
1046 	flow_prt_sel_t sel;
1047 	uint64_t offset;
1048 
1049 	ASSERT(FCRAM_PARTITION_VALID(partid));
1050 	if (!FCRAM_PARTITION_VALID(partid)) {
1051 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
1052 				    " fcram_partition disable:"
1053 				    " Invalid Partition %d \n",
1054 				    partid));
1055 		return (NPI_FFLP_FCRAM_PART_INVALID);
1056 	}
1057 	offset = FFLP_PART_OFFSET(partid, FFLP_FLW_PRT_SEL_REG);
1058 	REG_PIO_READ64(handle, offset, &sel.value);
1059 	sel.bits.ldw.ext = BIT_DISABLE; /* disable */
1060 	REG_PIO_WRITE64(handle, offset, sel.value);
1061 	return (NPI_SUCCESS);
1062 }
1063 
1064 /*
1065  *  npi_fflp_cam_errorcheck_disable
1066  *  Disables FCRAM and TCAM error checking
1067  */
1068 npi_status_t
1069 npi_fflp_cfg_cam_errorcheck_disable(npi_handle_t handle)
1070 
1071 {
1072 
1073 	fflp_cfg_1_t fflp_cfg;
1074 	uint64_t offset;
1075 	offset = FFLP_CFG_1_REG;
1076 
1077 	REG_PIO_READ64(handle, offset, &fflp_cfg.value);
1078 
1079 	fflp_cfg.bits.ldw.errordis = BIT_ENABLE;
1080 	REG_PIO_WRITE64(handle, offset, fflp_cfg.value);
1081 
1082 	return (NPI_SUCCESS);
1083 
1084 }
1085 
1086 /*
1087  *  npi_fflp_cam_errorcheck_enable
1088  *  Enables FCRAM and TCAM error checking
1089  */
1090 npi_status_t
1091 npi_fflp_cfg_cam_errorcheck_enable(npi_handle_t handle)
1092 
1093 {
1094 	fflp_cfg_1_t fflp_cfg;
1095 	uint64_t offset;
1096 	offset = FFLP_CFG_1_REG;
1097 
1098 	REG_PIO_READ64(handle, offset, &fflp_cfg.value);
1099 
1100 	fflp_cfg.bits.ldw.errordis = BIT_DISABLE;
1101 	REG_PIO_WRITE64(handle, offset, fflp_cfg.value);
1102 
1103 	return (NPI_SUCCESS);
1104 
1105 }
1106 
1107 /*
1108  *  npi_fflp_cam_llcsnap_enable
1109  *  Enables input parser llcsnap recognition
1110  */
1111 npi_status_t
1112 npi_fflp_cfg_llcsnap_enable(npi_handle_t handle)
1113 
1114 {
1115 
1116 	fflp_cfg_1_t fflp_cfg;
1117 	uint64_t offset;
1118 	offset = FFLP_CFG_1_REG;
1119 
1120 	REG_PIO_READ64(handle, offset, &fflp_cfg.value);
1121 
1122 	fflp_cfg.bits.ldw.llcsnap = BIT_ENABLE;
1123 	REG_PIO_WRITE64(handle, offset, fflp_cfg.value);
1124 
1125 	return (NPI_SUCCESS);
1126 
1127 }
1128 
1129 /*
1130  *  npi_fflp_cam_llcsnap_disable
1131  *  Disables input parser llcsnap recognition
1132  */
1133 npi_status_t
1134 npi_fflp_cfg_llcsnap_disable(npi_handle_t handle)
1135 
1136 {
1137 
1138 
1139 	fflp_cfg_1_t fflp_cfg;
1140 	uint64_t offset;
1141 	offset = FFLP_CFG_1_REG;
1142 
1143 	REG_PIO_READ64(handle, offset, &fflp_cfg.value);
1144 
1145 	fflp_cfg.bits.ldw.llcsnap = BIT_DISABLE;
1146 	REG_PIO_WRITE64(handle, offset, fflp_cfg.value);
1147 
1148 	return (NPI_SUCCESS);
1149 
1150 }
1151 
1152 /*
1153  * npi_fflp_config_fcram_refresh
1154  * Set FCRAM min and max refresh time.
1155  *
1156  * Input
1157  *      handle			opaque handle interpreted by the underlying OS
1158  *	min_time		Minimum Refresh time count
1159  *	max_time		maximum Refresh Time count
1160  *	sys_time		System Clock rate
1161  *
1162  *	The counters are 16 bit counters. The maximum refresh time is
1163  *      3.9us/clock cycle. The minimum is 400ns/clock cycle.
1164  *	Clock cycle is the FCRAM clock cycle?????
1165  *	If the cycle is FCRAM clock cycle, then sys_time parameter
1166  *      is not needed as there wont be configuration variation due to
1167  *      system clock cycle.
1168  *
1169  * Return:
1170  * NPI Success/Failure status code
1171  */
1172 npi_status_t
1173 npi_fflp_cfg_fcram_refresh_time(npi_handle_t handle, uint32_t min_time,
1174 				    uint32_t max_time, uint32_t sys_time)
1175 
1176 {
1177 
1178 	uint64_t offset;
1179 	fcram_ref_tmr_t refresh_timer_reg;
1180 	uint16_t max, min;
1181 
1182 	offset = FFLP_FCRAM_REF_TMR_REG;
1183 /* need to figure out how to dervive the numbers */
1184 	max = max_time * sys_time;
1185 	min = min_time * sys_time;
1186 /* for now, just set with #def values */
1187 
1188 	max = FCRAM_REFRESH_DEFAULT_MAX_TIME;
1189 	min = FCRAM_REFRESH_DEFAULT_MIN_TIME;
1190 	REG_PIO_READ64(handle, offset, &refresh_timer_reg.value);
1191 	refresh_timer_reg.bits.ldw.min = min;
1192 	refresh_timer_reg.bits.ldw.max = max;
1193 	REG_PIO_WRITE64(handle, offset, refresh_timer_reg.value);
1194 	return (NPI_SUCCESS);
1195 }
1196 
1197 /*
1198  *  npi_fflp_hash_lookup_err_report
1199  *  Reports hash table (fcram) lookup errors
1200  *
1201  *  Input
1202  *      handle			opaque handle interpreted by the underlying OS
1203  *      err_stat		Pointer to return Error bits
1204  *
1205  *
1206  * Return:
1207  * NPI success/failure status code
1208  */
1209 npi_status_t
1210 npi_fflp_fcram_get_lookup_err_log(npi_handle_t handle,
1211 				    hash_lookup_err_log_t *err_stat)
1212 
1213 {
1214 
1215 	hash_lookup_err_log1_t err_log1;
1216 	hash_lookup_err_log2_t err_log2;
1217 	uint64_t  err_log1_offset, err_log2_offset;
1218 	err_log1.value = 0;
1219 	err_log2.value = 0;
1220 
1221 	err_log1_offset = HASH_LKUP_ERR_LOG1_REG;
1222 	err_log2_offset = HASH_LKUP_ERR_LOG2_REG;
1223 
1224 	REG_PIO_READ64(handle, err_log1_offset, &err_log1.value);
1225 	REG_PIO_READ64(handle, err_log2_offset, &err_log2.value);
1226 
1227 	if (err_log1.value) {
1228 /* nonzero means there are some errors */
1229 		err_stat->lookup_err = BIT_ENABLE;
1230 		err_stat->syndrome = err_log2.bits.ldw.syndrome;
1231 		err_stat->subarea = err_log2.bits.ldw.subarea;
1232 		err_stat->h1 = err_log2.bits.ldw.h1;
1233 		err_stat->multi_bit = err_log1.bits.ldw.mult_bit;
1234 		err_stat->multi_lkup = err_log1.bits.ldw.mult_lk;
1235 		err_stat->ecc_err = err_log1.bits.ldw.ecc_err;
1236 		err_stat->uncor_err = err_log1.bits.ldw.cu;
1237 	} else {
1238 		err_stat->lookup_err = BIT_DISABLE;
1239 	}
1240 
1241 	return (NPI_SUCCESS);
1242 
1243 }
1244 
1245 /*
1246  * npi_fflp_fcram_get_pio_err_log
1247  * Reports hash table PIO read errors for the given partition.
1248  * by default, it clears the error bit which was set by the HW.
1249  *
1250  * Input
1251  *      handle:		opaque handle interpreted by the underlying OS
1252  *	partid:		partition ID
1253  *      err_stat	Pointer to return Error bits
1254  *
1255  * Return
1256  *	NPI success/failure status code
1257  */
1258 npi_status_t
1259 npi_fflp_fcram_get_pio_err_log(npi_handle_t handle, part_id_t partid,
1260 				    hash_pio_err_log_t *err_stat)
1261 {
1262 
1263 	hash_tbl_data_log_t err_log;
1264 	uint64_t offset;
1265 
1266 	ASSERT(FCRAM_PARTITION_VALID(partid));
1267 	if (!FCRAM_PARTITION_VALID(partid)) {
1268 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
1269 		    " fcram_get_pio_err_log:"
1270 		    " Invalid Partition %d \n",
1271 		    partid));
1272 		return (NPI_FFLP_FCRAM_PART_INVALID);
1273 	}
1274 
1275 	offset = GET_HASHTBL_PART_OFFSET_NVIR(partid,
1276 	    FFLP_HASH_TBL_DATA_LOG_REG);
1277 
1278 	REG_PIO_READ64(handle, offset, &err_log.value);
1279 
1280 	if (err_log.bits.ldw.pio_err == BIT_ENABLE) {
1281 /* nonzero means there are some errors */
1282 		err_stat->pio_err = BIT_ENABLE;
1283 		err_stat->syndrome = err_log.bits.ldw.syndrome;
1284 		err_stat->addr = err_log.bits.ldw.fcram_addr;
1285 		err_log.value = 0;
1286 		REG_PIO_WRITE64(handle, offset, err_log.value);
1287 	} else {
1288 		err_stat->pio_err = BIT_DISABLE;
1289 	}
1290 
1291 	return (NPI_SUCCESS);
1292 
1293 }
1294 
1295 /*
1296  * npi_fflp_fcram_clr_pio_err_log
1297  * Clears FCRAM PIO  error status for the partition.
1298  * If there are TCAM errors as indicated by err bit set by HW,
1299  *  then the SW will clear it by clearing the bit.
1300  *
1301  * Input
1302  *      handle:		opaque handle interpreted by the underlying OS
1303  *	partid:		partition ID
1304  *
1305  *
1306  * Return
1307  *	NPI success/failure status code
1308  */
1309 npi_status_t
1310 npi_fflp_fcram_clr_pio_err_log(npi_handle_t handle, part_id_t partid)
1311 {
1312 	uint64_t offset;
1313 
1314 	hash_tbl_data_log_t err_log;
1315 
1316 	ASSERT(FCRAM_PARTITION_VALID(partid));
1317 	if (!FCRAM_PARTITION_VALID(partid)) {
1318 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
1319 		    " fcram_clr_pio_err_log:"
1320 		    " Invalid Partition %d \n",
1321 		    partid));
1322 
1323 		return (NPI_FFLP_FCRAM_PART_INVALID);
1324 	}
1325 
1326 	offset = GET_HASHTBL_PART_OFFSET_NVIR(partid,
1327 	    FFLP_HASH_TBL_DATA_LOG_REG);
1328 
1329 	err_log.value = 0;
1330 	REG_PIO_WRITE64(handle, offset, err_log.value);
1331 
1332 
1333 	return (NPI_SUCCESS);
1334 
1335 }
1336 
1337 /*
1338  * npi_fflp_tcam_get_err_log
1339  * Reports TCAM PIO read and lookup errors.
1340  * If there are TCAM errors as indicated by err bit set by HW,
1341  *  then the SW will clear it by clearing the bit.
1342  *
1343  * Input
1344  *      handle:		opaque handle interpreted by the underlying OS
1345  *	err_stat:	 structure to report various TCAM errors.
1346  *                       will be updated if there are TCAM errors.
1347  *
1348  *
1349  * Return
1350  *	NPI_SUCCESS	Success
1351  *
1352  *
1353  */
1354 npi_status_t
1355 npi_fflp_tcam_get_err_log(npi_handle_t handle, tcam_err_log_t *err_stat)
1356 {
1357 	tcam_err_t err_log;
1358 	uint64_t offset;
1359 
1360 	offset = FFLP_TCAM_ERR_REG;
1361 	err_log.value = 0;
1362 
1363 	REG_PIO_READ64(handle, offset, &err_log.value);
1364 
1365 	if (err_log.bits.ldw.err == BIT_ENABLE) {
1366 /* non-zero means err */
1367 		err_stat->tcam_err = BIT_ENABLE;
1368 		if (err_log.bits.ldw.p_ecc) {
1369 			err_stat->parity_err = 0;
1370 			err_stat->ecc_err = 1;
1371 		} else {
1372 			err_stat->parity_err = 1;
1373 			err_stat->ecc_err = 0;
1374 
1375 		}
1376 		err_stat->syndrome = err_log.bits.ldw.syndrome;
1377 		err_stat->location = err_log.bits.ldw.addr;
1378 
1379 
1380 		err_stat->multi_lkup = err_log.bits.ldw.mult;
1381 			/* now clear the error */
1382 		err_log.value = 0;
1383 		REG_PIO_WRITE64(handle, offset, err_log.value);
1384 
1385 	} else {
1386 		err_stat->tcam_err = 0;
1387 	}
1388 	return (NPI_SUCCESS);
1389 
1390 }
1391 
1392 /*
1393  * npi_fflp_tcam_clr_err_log
1394  * Clears TCAM PIO read and lookup error status.
1395  * If there are TCAM errors as indicated by err bit set by HW,
1396  *  then the SW will clear it by clearing the bit.
1397  *
1398  * Input
1399  *         handle:	opaque handle interpreted by the underlying OS
1400  *
1401  *
1402  * Return
1403  *	NPI_SUCCESS	Success
1404  *
1405  *
1406  */
1407 npi_status_t
1408 npi_fflp_tcam_clr_err_log(npi_handle_t handle)
1409 {
1410 	tcam_err_t err_log;
1411 	uint64_t offset;
1412 
1413 	offset = FFLP_TCAM_ERR_REG;
1414 	err_log.value = 0;
1415 	REG_PIO_WRITE64(handle, offset, err_log.value);
1416 
1417 	return (NPI_SUCCESS);
1418 
1419 }
1420 
1421 /*
1422  * npi_fflp_fcram_err_synd_test
1423  * Tests the FCRAM error detection logic.
1424  * The error detection logic for the syndrome is tested.
1425  * tst0->synd (8bits) are set to select the syndrome bits
1426  * to be XOR'ed
1427  *
1428  * Input
1429  *      handle:	opaque handle interpreted by the underlying OS
1430  *	syndrome_bits:	 Syndrome bits to select bits to be xor'ed
1431  *
1432  *
1433  * Return
1434  *	NPI_SUCCESS	Success
1435  *
1436  *
1437  */
1438 npi_status_t
1439 npi_fflp_fcram_err_synd_test(npi_handle_t handle, uint8_t syndrome_bits)
1440 {
1441 
1442 	uint64_t t0_offset;
1443 	fcram_err_tst0_t tst0;
1444 	t0_offset = FFLP_FCRAM_ERR_TST0_REG;
1445 
1446 	tst0.value = 0;
1447 	tst0.bits.ldw.syndrome_mask = syndrome_bits;
1448 
1449 	REG_PIO_WRITE64(handle, t0_offset, tst0.value);
1450 
1451 	return (NPI_SUCCESS);
1452 
1453 }
1454 
1455 /*
1456  * npi_fflp_fcram_err_data_test
1457  * Tests the FCRAM error detection logic.
1458  * The error detection logic for the datapath is tested.
1459  * bits [63:0] are set to select the data bits to be xor'ed
1460  *
1461  * Input
1462  *      handle:	opaque handle interpreted by the underlying OS
1463  *	data:	 data bits to select bits to be xor'ed
1464  *
1465  *
1466  * Return
1467  *	NPI_SUCCESS	Success
1468  *
1469  *
1470  */
1471 npi_status_t
1472 npi_fflp_fcram_err_data_test(npi_handle_t handle, fcram_err_data_t *data)
1473 {
1474 
1475 	uint64_t t1_offset, t2_offset;
1476 	fcram_err_tst1_t tst1; /* for data bits [31:0] */
1477 	fcram_err_tst2_t tst2; /* for data bits [63:32] */
1478 
1479 	t1_offset = FFLP_FCRAM_ERR_TST1_REG;
1480 	t2_offset = FFLP_FCRAM_ERR_TST2_REG;
1481 	tst1.value = 0;
1482 	tst2.value = 0;
1483 	tst1.bits.ldw.dat = data->bits.ldw.dat;
1484 	tst2.bits.ldw.dat = data->bits.hdw.dat;
1485 
1486 	REG_PIO_WRITE64(handle, t1_offset, tst1.value);
1487 	REG_PIO_WRITE64(handle, t2_offset, tst2.value);
1488 
1489 	return (NPI_SUCCESS);
1490 
1491 }
1492 
1493 /*
1494  * npi_fflp_cfg_enet_vlan_table_assoc
1495  * associates port vlan id to rdc table.
1496  *
1497  * Input
1498  *     handle			opaque handle interpreted by the underlying OS
1499  *     mac_portn		port number
1500  *     vlan_id			VLAN ID
1501  *     rdc_table		RDC Table #
1502  *     priority			priority
1503  *
1504  * Output
1505  *
1506  *	NPI success/failure status code
1507  *
1508  */
1509 npi_status_t
1510 npi_fflp_cfg_enet_vlan_table_assoc(npi_handle_t handle, uint8_t mac_portn,
1511 				    vlan_id_t vlan_id, uint8_t rdc_table,
1512 				    uint8_t priority)
1513 {
1514 
1515 	fflp_enet_vlan_tbl_t cfg;
1516 	uint64_t offset;
1517 	uint8_t vlan_parity[8] = {0, 1, 1, 2, 1, 2, 2, 3};
1518 	uint8_t parity_bit;
1519 
1520 	ASSERT(FFLP_VLAN_VALID(vlan_id));
1521 	if (!FFLP_VLAN_VALID(vlan_id)) {
1522 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
1523 		    " fflp_cfg_enet_vlan_table:"
1524 		    " Invalid vlan ID %d \n",
1525 		    vlan_id));
1526 		return (NPI_FFLP_VLAN_INVALID);
1527 	}
1528 
1529 	ASSERT(FFLP_PORT_VALID(mac_portn));
1530 	if (!FFLP_PORT_VALID(mac_portn)) {
1531 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
1532 		    " fflp_cfg_enet_vlan_table:"
1533 		    " Invalid port num %d \n",
1534 		    mac_portn));
1535 		return (NPI_FFLP_PORT_INVALID);
1536 	}
1537 
1538 	ASSERT(FFLP_RDC_TABLE_VALID(rdc_table));
1539 	if (!FFLP_RDC_TABLE_VALID(rdc_table)) {
1540 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
1541 		    " fflp_cfg_enet_vlan_table:"
1542 		    " Invalid RDC Table %d \n",
1543 		    rdc_table));
1544 		return (NPI_FFLP_RDC_TABLE_INVALID);
1545 	}
1546 
1547 	offset = FFLP_VLAN_OFFSET(vlan_id, FFLP_ENET_VLAN_TBL_REG);
1548 	REG_PIO_READ64(handle, offset, &cfg.value);
1549 
1550 	switch (mac_portn) {
1551 		case 0:
1552 			cfg.bits.ldw.vlanrdctbln0 = rdc_table;
1553 			if (priority)
1554 				cfg.bits.ldw.vpr0 = BIT_ENABLE;
1555 			else
1556 				cfg.bits.ldw.vpr0 = BIT_DISABLE;
1557 				/* set the parity bits */
1558 			parity_bit = vlan_parity[cfg.bits.ldw.vlanrdctbln0] +
1559 			    vlan_parity[cfg.bits.ldw.vlanrdctbln1] +
1560 			    cfg.bits.ldw.vpr0 + cfg.bits.ldw.vpr1;
1561 			cfg.bits.ldw.parity0 = parity_bit & 0x1;
1562 			break;
1563 		case 1:
1564 			cfg.bits.ldw.vlanrdctbln1 = rdc_table;
1565 			if (priority)
1566 				cfg.bits.ldw.vpr1 = BIT_ENABLE;
1567 			else
1568 				cfg.bits.ldw.vpr1 = BIT_DISABLE;
1569 				/* set the parity bits */
1570 			parity_bit = vlan_parity[cfg.bits.ldw.vlanrdctbln0] +
1571 			    vlan_parity[cfg.bits.ldw.vlanrdctbln1] +
1572 			    cfg.bits.ldw.vpr0 + cfg.bits.ldw.vpr1;
1573 			cfg.bits.ldw.parity0 = parity_bit & 0x1;
1574 
1575 			break;
1576 		case 2:
1577 			cfg.bits.ldw.vlanrdctbln2 = rdc_table;
1578 			if (priority)
1579 				cfg.bits.ldw.vpr2 = BIT_ENABLE;
1580 			else
1581 				cfg.bits.ldw.vpr2 = BIT_DISABLE;
1582 				/* set the parity bits */
1583 			parity_bit = vlan_parity[cfg.bits.ldw.vlanrdctbln2] +
1584 			    vlan_parity[cfg.bits.ldw.vlanrdctbln3] +
1585 			    cfg.bits.ldw.vpr2 + cfg.bits.ldw.vpr3;
1586 			cfg.bits.ldw.parity1 = parity_bit & 0x1;
1587 
1588 			break;
1589 		case 3:
1590 			cfg.bits.ldw.vlanrdctbln3 = rdc_table;
1591 			if (priority)
1592 				cfg.bits.ldw.vpr3 = BIT_ENABLE;
1593 			else
1594 				cfg.bits.ldw.vpr3 = BIT_DISABLE;
1595 				/* set the parity bits */
1596 			parity_bit = vlan_parity[cfg.bits.ldw.vlanrdctbln2] +
1597 			    vlan_parity[cfg.bits.ldw.vlanrdctbln3] +
1598 			    cfg.bits.ldw.vpr2 + cfg.bits.ldw.vpr3;
1599 			cfg.bits.ldw.parity1 = parity_bit & 0x1;
1600 			break;
1601 		default:
1602 			return (NPI_FFLP_SW_PARAM_ERROR);
1603 	}
1604 
1605 	REG_PIO_WRITE64(handle, offset, cfg.value);
1606 	return (NPI_SUCCESS);
1607 }
1608 
1609 /*
1610  * npi_fflp_cfg_enet_vlan_table_set_pri
1611  * sets the  vlan based classification priority in respect to L2DA
1612  * classification.
1613  *
1614  * Input
1615  *     handle		opaque handle interpreted by the underlying OS
1616  *     mac_portn	port number
1617  *     vlan_id		VLAN ID
1618  *     priority 	priority
1619  *			1: vlan classification has higher priority
1620  *			0: l2da classification has higher priority
1621  *
1622  * Output
1623  *
1624  *	NPI success/failure status code
1625  */
1626 npi_status_t
1627 npi_fflp_cfg_enet_vlan_table_set_pri(npi_handle_t handle, uint8_t mac_portn,
1628 				    vlan_id_t vlan_id, uint8_t priority)
1629 {
1630 
1631 	fflp_enet_vlan_tbl_t cfg;
1632 	uint64_t offset;
1633 	uint64_t old_value;
1634 
1635 	ASSERT(FFLP_VLAN_VALID(vlan_id));
1636 	if (!FFLP_VLAN_VALID(vlan_id)) {
1637 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
1638 		    " enet_vlan_table set pri:"
1639 		    " Invalid vlan ID %d \n",
1640 		    vlan_id));
1641 		return (NPI_FFLP_VLAN_INVALID);
1642 	}
1643 
1644 	ASSERT(FFLP_PORT_VALID(mac_portn));
1645 	if (!FFLP_PORT_VALID(mac_portn)) {
1646 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
1647 		    " enet_vlan_table set pri:"
1648 		    " Invalid port num %d \n",
1649 		    mac_portn));
1650 		return (NPI_FFLP_PORT_INVALID);
1651 	}
1652 
1653 
1654 	offset = FFLP_ENET_VLAN_TBL_REG + (vlan_id  << 3);
1655 	REG_PIO_READ64(handle, offset, &cfg.value);
1656 	old_value = cfg.value;
1657 	switch (mac_portn) {
1658 		case 0:
1659 			if (priority)
1660 				cfg.bits.ldw.vpr0 = BIT_ENABLE;
1661 			else
1662 				cfg.bits.ldw.vpr0 = BIT_DISABLE;
1663 			break;
1664 		case 1:
1665 			if (priority)
1666 				cfg.bits.ldw.vpr1 = BIT_ENABLE;
1667 			else
1668 				cfg.bits.ldw.vpr1 = BIT_DISABLE;
1669 			break;
1670 		case 2:
1671 			if (priority)
1672 				cfg.bits.ldw.vpr2 = BIT_ENABLE;
1673 			else
1674 				cfg.bits.ldw.vpr2 = BIT_DISABLE;
1675 			break;
1676 		case 3:
1677 			if (priority)
1678 				cfg.bits.ldw.vpr3 = BIT_ENABLE;
1679 			else
1680 				cfg.bits.ldw.vpr3 = BIT_DISABLE;
1681 			break;
1682 		default:
1683 			return (NPI_FFLP_SW_PARAM_ERROR);
1684 	}
1685 	if (old_value != cfg.value) {
1686 		if (mac_portn > 1)
1687 			cfg.bits.ldw.parity1++;
1688 		else
1689 			cfg.bits.ldw.parity0++;
1690 
1691 		REG_PIO_WRITE64(handle, offset, cfg.value);
1692 	}
1693 	return (NPI_SUCCESS);
1694 }
1695 
1696 /*
1697  * npi_fflp_cfg_vlan_table_clear
1698  * Clears the vlan RDC table
1699  *
1700  * Input
1701  *     handle		opaque handle interpreted by the underlying OS
1702  *     vlan_id		VLAN ID
1703  *
1704  * Output
1705  *
1706  *	NPI success/failure status code
1707  *
1708  */
1709 npi_status_t
1710 npi_fflp_cfg_vlan_table_clear(npi_handle_t handle, vlan_id_t vlan_id)
1711 {
1712 
1713 	uint64_t offset;
1714 	uint64_t clear = 0ULL;
1715 	vlan_id_t start_vlan = 0;
1716 
1717 	if ((vlan_id < start_vlan) || (vlan_id >= NXGE_MAX_VLANS)) {
1718 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
1719 		    " enet_vlan_table clear:"
1720 		    " Invalid vlan ID %d \n",
1721 		    vlan_id));
1722 		return (NPI_FFLP_VLAN_INVALID);
1723 	}
1724 
1725 
1726 	offset = FFLP_VLAN_OFFSET(vlan_id, FFLP_ENET_VLAN_TBL_REG);
1727 
1728 	REG_PIO_WRITE64(handle, offset, clear);
1729 	return (NPI_SUCCESS);
1730 }
1731 
1732 /*
1733  * npi_fflp_vlan_tbl_get_err_log
1734  * Reports VLAN Table  errors.
1735  * If there are VLAN Table errors as indicated by err bit set by HW,
1736  *  then the SW will clear it by clearing the bit.
1737  *
1738  * Input
1739  *      handle:		opaque handle interpreted by the underlying OS
1740  *	err_stat:	 structure to report various VLAN table errors.
1741  *                       will be updated if there are errors.
1742  *
1743  *
1744  * Return
1745  *	NPI_SUCCESS	Success
1746  *
1747  *
1748  */
1749 npi_status_t
1750 npi_fflp_vlan_tbl_get_err_log(npi_handle_t handle, vlan_tbl_err_log_t *err_stat)
1751 {
1752 	vlan_par_err_t err_log;
1753 	uint64_t offset;
1754 
1755 
1756 	offset = FFLP_VLAN_PAR_ERR_REG;
1757 	err_log.value = 0;
1758 
1759 	REG_PIO_READ64(handle, offset, &err_log.value);
1760 
1761 	if (err_log.bits.ldw.err == BIT_ENABLE) {
1762 /* non-zero means err */
1763 		err_stat->err = BIT_ENABLE;
1764 		err_stat->multi = err_log.bits.ldw.m_err;
1765 		err_stat->addr = err_log.bits.ldw.addr;
1766 		err_stat->data = err_log.bits.ldw.data;
1767 /* now clear the error */
1768 		err_log.value = 0;
1769 		REG_PIO_WRITE64(handle, offset, err_log.value);
1770 
1771 	} else {
1772 		err_stat->err = 0;
1773 	}
1774 
1775 	return (NPI_SUCCESS);
1776 }
1777 
1778 /*
1779  * npi_fflp_vlan_tbl_clr_err_log
1780  * Clears VLAN Table PIO  error status.
1781  * If there are VLAN Table errors as indicated by err bit set by HW,
1782  *  then the SW will clear it by clearing the bit.
1783  *
1784  * Input
1785  *         handle:	opaque handle interpreted by the underlying OS
1786  *
1787  *
1788  * Return
1789  *	NPI_SUCCESS	Success
1790  *
1791  *
1792  */
1793 npi_status_t
1794 npi_fflp_vlan_tbl_clr_err_log(npi_handle_t handle)
1795 {
1796 	vlan_par_err_t err_log;
1797 	uint64_t offset;
1798 
1799 	offset = FFLP_VLAN_PAR_ERR_REG;
1800 	err_log.value = 0;
1801 
1802 	REG_PIO_WRITE64(handle, offset, err_log.value);
1803 
1804 	return (NPI_SUCCESS);
1805 }
1806 
1807 /*
1808  * npi_fflp_cfg_enet_usr_cls_set()
1809  * Configures a user configurable ethernet class
1810  *
1811  * Input
1812  *      handle:		opaque handle interpreted by the underlying OS
1813  *      class:       Ethernet Class  class
1814  *		     (TCAM_CLASS_ETYPE or  TCAM_CLASS_ETYPE_2)
1815  *      enet_type:   16 bit Ethernet Type value, corresponding ethernet bytes
1816  *                        [13:14] in the frame.
1817  *
1818  *  by default, the class will be disabled until explicitly enabled.
1819  *
1820  * Return
1821  * NPI success/failure status code
1822  */
1823 npi_status_t
1824 npi_fflp_cfg_enet_usr_cls_set(npi_handle_t handle,
1825 			    tcam_class_t class, uint16_t enet_type)
1826 {
1827 	uint64_t offset;
1828 	tcam_class_prg_ether_t cls_cfg;
1829 	cls_cfg.value = 0x0;
1830 
1831 /* check if etype is valid */
1832 	ASSERT(TCAM_L2_USR_CLASS_VALID(class));
1833 	if (!TCAM_L2_USR_CLASS_VALID(class)) {
1834 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
1835 		    " npi_fflp_cfg_enet_usr_cls_set:"
1836 		    " Invalid class %d \n",
1837 		    class));
1838 		return (NPI_FFLP_TCAM_CLASS_INVALID);
1839 	}
1840 	offset = GET_TCAM_CLASS_OFFSET(class);
1841 
1842 /*
1843  * etype check code
1844  *
1845  * if (check_fail)
1846  *  return (NPI_FAILURE | NPI_SW_ERROR);
1847  */
1848 
1849 	cls_cfg.bits.ldw.etype = enet_type;
1850 	cls_cfg.bits.ldw.valid = BIT_DISABLE;
1851 	REG_PIO_WRITE64(handle, offset, cls_cfg.value);
1852 	return (NPI_SUCCESS);
1853 }
1854 
1855 /*
1856  * npi_fflp_cfg_enet_usr_cls_enable()
1857  * Enable previously configured TCAM user configurable Ethernet classes.
1858  *
1859  * Input
1860  *      handle:	opaque handle interpreted by the underlying OS
1861  *      class:       Ethernet Class  class
1862  *		     (TCAM_CLASS_ETYPE or  TCAM_CLASS_ETYPE_2)
1863  *
1864  * Return
1865  * NPI success/failure status code
1866  */
1867 npi_status_t
1868 npi_fflp_cfg_enet_usr_cls_enable(npi_handle_t handle, tcam_class_t class)
1869 {
1870 	uint64_t offset;
1871 	tcam_class_prg_ether_t cls_cfg;
1872 
1873 	ASSERT(TCAM_L2_USR_CLASS_VALID(class));
1874 	if (!TCAM_L2_USR_CLASS_VALID(class)) {
1875 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
1876 		    " npi_fflp_cfg_enet_usr_cls_enable:"
1877 		    " Invalid class %d \n",
1878 		    class));
1879 		return (NPI_FFLP_TCAM_CLASS_INVALID);
1880 	}
1881 
1882 	offset = GET_TCAM_CLASS_OFFSET(class);
1883 
1884 	REG_PIO_READ64(handle, offset, &cls_cfg.value);
1885 	cls_cfg.bits.ldw.valid = BIT_ENABLE;
1886 	REG_PIO_WRITE64(handle, offset, cls_cfg.value);
1887 	return (NPI_SUCCESS);
1888 }
1889 
1890 /*
1891  * npi_fflp_cfg_enet_usr_cls_disable()
1892  * Disables previously configured TCAM user configurable Ethernet classes.
1893  *
1894  * Input
1895  *      handle:	opaque handle interpreted by the underlying OS
1896  *      class:       Ethernet Class  class
1897  *		     (TCAM_CLASS_ETYPE or  TCAM_CLASS_ETYPE_2)
1898  *
1899  * Return
1900  * NPI success/failure status code
1901  */
1902 npi_status_t
1903 npi_fflp_cfg_enet_usr_cls_disable(npi_handle_t handle, tcam_class_t class)
1904 {
1905 	uint64_t offset;
1906 	tcam_class_prg_ether_t cls_cfg;
1907 
1908 	ASSERT(TCAM_L2_USR_CLASS_VALID(class));
1909 	if (!TCAM_L2_USR_CLASS_VALID(class)) {
1910 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
1911 		    " npi_fflp_cfg_enet_usr_cls_disable:"
1912 		    " Invalid class %d \n",
1913 		    class));
1914 		return (NPI_FFLP_TCAM_CLASS_INVALID);
1915 	}
1916 
1917 	offset = GET_TCAM_CLASS_OFFSET(class);
1918 
1919 	REG_PIO_READ64(handle, offset, &cls_cfg.value);
1920 	cls_cfg.bits.ldw.valid = BIT_DISABLE;
1921 
1922 	REG_PIO_WRITE64(handle, offset, cls_cfg.value);
1923 	return (NPI_SUCCESS);
1924 }
1925 
1926 /*
1927  * npi_fflp_cfg_ip_usr_cls_set()
1928  * Configures the TCAM user configurable IP classes.
1929  *
1930  * Input
1931  *      handle:		opaque handle interpreted by the underlying OS
1932  *      class:       IP Class  class
1933  *		     (TCAM_CLASS_IP_USER_4 <= class <= TCAM_CLASS_IP_USER_7)
1934  *      tos:         IP TOS bits
1935  *      tos_mask:    IP TOS bits mask. bits with mask bits set will be used
1936  *      proto:       IP Proto
1937  *      ver:         IP Version
1938  * by default, will the class is disabled until explicitly enabled
1939  *
1940  * Return
1941  * NPI success/failure status code
1942  */
1943 npi_status_t
1944 npi_fflp_cfg_ip_usr_cls_set(npi_handle_t handle, tcam_class_t class,
1945 			    uint8_t tos, uint8_t tos_mask,
1946 			    uint8_t proto, uint8_t ver)
1947 {
1948 	uint64_t offset;
1949 	tcam_class_prg_ip_t ip_cls_cfg;
1950 
1951 	ASSERT(TCAM_L3_USR_CLASS_VALID(class));
1952 	if (!TCAM_L3_USR_CLASS_VALID(class)) {
1953 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
1954 		    " npi_fflp_cfg_ip_usr_cls_set:"
1955 		    " Invalid class %d \n",
1956 		    class));
1957 		return (NPI_FFLP_TCAM_CLASS_INVALID);
1958 	}
1959 
1960 	offset = GET_TCAM_CLASS_OFFSET(class);
1961 
1962 	ip_cls_cfg.bits.ldw.pid = proto;
1963 	ip_cls_cfg.bits.ldw.ipver = ver;
1964 	ip_cls_cfg.bits.ldw.tos = tos;
1965 	ip_cls_cfg.bits.ldw.tosmask = tos_mask;
1966 	ip_cls_cfg.bits.ldw.valid = 0;
1967 	REG_PIO_WRITE64(handle, offset, ip_cls_cfg.value);
1968 	return (NPI_SUCCESS);
1969 
1970 }
1971 
1972 /*
1973  * npi_fflp_cfg_ip_usr_cls_set_iptun()
1974  * Configures the TCAM user configurable IP classes. This function sets the
1975  * new fields that were added for IP tunneling support
1976  *
1977  * Input
1978  *      handle:		opaque handle interpreted by the underlying OS
1979  *      class:       IP Class  class
1980  *		     (TCAM_CLASS_IP_USER_4 <= class <= TCAM_CLASS_IP_USER_7)
1981  *	l4b0_val	value of the first L4 byte to be compared
1982  *	l4b0_msk	mask to apply to compare byte 0 of L4
1983  *	l4b23_val	values of L4 bytes 2 and 3 to compare
1984  *	l4b23_sel	set to 1 to compare L4 bytes 2 and 3.
1985  * by default, the class is disabled until explicitly enabled
1986  *
1987  * Return
1988  * NPI success/failure status code
1989  */
1990 npi_status_t
1991 npi_fflp_cfg_ip_usr_cls_set_iptun(npi_handle_t handle, tcam_class_t class,
1992 			    uint8_t l4b0_val, uint8_t l4b0_msk,
1993 			    uint16_t l4b23_val, uint8_t l4b23_sel)
1994 {
1995 	uint64_t offset, val;
1996 	tcam_class_prg_ip_t ip_cls_cfg;
1997 
1998 	ASSERT(TCAM_L3_USR_CLASS_VALID(class));
1999 	if (!TCAM_L3_USR_CLASS_VALID(class)) {
2000 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
2001 		    " npi_fflp_cfg_ip_usr_cls_set:"
2002 		    " Invalid class %d \n",
2003 		    class));
2004 		return (NPI_FFLP_TCAM_CLASS_INVALID);
2005 	}
2006 
2007 	offset = GET_TCAM_CLASS_OFFSET(class);
2008 	REG_PIO_READ64(handle, offset, &ip_cls_cfg.value);
2009 
2010 	val = 1;
2011 	ip_cls_cfg.value |= (val << L3_UCLS_L4_MODE_SH);
2012 	val = l4b0_val;
2013 	ip_cls_cfg.value |= (val << L3_UCLS_L4B0_VAL_SH);
2014 	val = l4b0_msk;
2015 	ip_cls_cfg.value |= (val << L3_UCLS_L4B0_MASK_SH);
2016 	val = l4b23_sel;
2017 	ip_cls_cfg.value |= (val << L3_UCLS_L4B23_SEL_SH);
2018 	val = l4b23_val;
2019 	ip_cls_cfg.value |= (val << L3_UCLS_L4B23_VAL_SH);
2020 
2021 	ip_cls_cfg.bits.ldw.valid = 0;
2022 	REG_PIO_WRITE64(handle, offset, ip_cls_cfg.value);
2023 	return (NPI_SUCCESS);
2024 }
2025 
2026 /*
2027  * npi_fflp_cfg_ip_usr_cls_get_iptun()
2028  * Retrieves the IP tunneling related settings for the given TCAM user
2029  * configurable IP classe.
2030  *
2031  * Input
2032  *      handle:		opaque handle interpreted by the underlying OS
2033  *      class:       IP Class  class
2034  *		     (TCAM_CLASS_IP_USER_4 <= class <= TCAM_CLASS_IP_USER_7)
2035  *	l4b0_val	value of the first L4 byte to be compared
2036  *	l4b0_msk	mask to apply to compare byte 0 of L4
2037  *	l4b23_val	values of L4 bytes 2 and 3 to compare
2038  *	l4b23_sel	set to 1 to compare L4 bytes 2 and 3.
2039  * by default, the class is disabled until explicitly enabled
2040  *
2041  * Return
2042  * NPI success/failure status code
2043  */
2044 npi_status_t
2045 npi_fflp_cfg_ip_usr_cls_get_iptun(npi_handle_t handle, tcam_class_t class,
2046 			    uint8_t *l4b0_val, uint8_t *l4b0_msk,
2047 			    uint16_t *l4b23_val, uint8_t *l4b23_sel)
2048 {
2049 	uint64_t offset;
2050 	tcam_class_prg_ip_t ip_cls_cfg;
2051 
2052 	ASSERT(TCAM_L3_USR_CLASS_VALID(class));
2053 	if (!TCAM_L3_USR_CLASS_VALID(class)) {
2054 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
2055 		    " npi_fflp_cfg_ip_usr_cls_set:"
2056 		    " Invalid class %d \n",
2057 		    class));
2058 		return (NPI_FFLP_TCAM_CLASS_INVALID);
2059 	}
2060 
2061 	offset = GET_TCAM_CLASS_OFFSET(class);
2062 	REG_PIO_READ64(handle, offset, &ip_cls_cfg.value);
2063 
2064 	*l4b0_val = (ip_cls_cfg.value >> L3_UCLS_L4B0_VAL_SH) &
2065 	    L3_UCLS_L4B0_VAL_MSK;
2066 	*l4b0_msk = (ip_cls_cfg.value >> L3_UCLS_L4B0_MASK_SH) &
2067 	    L3_UCLS_L4B0_MASK_MSK;
2068 	*l4b23_sel = (ip_cls_cfg.value >> L3_UCLS_L4B23_SEL_SH) &
2069 	    L3_UCLS_L4B23_SEL_MSK;
2070 	*l4b23_val = (ip_cls_cfg.value >> L3_UCLS_L4B23_VAL_SH) &
2071 	    L3_UCLS_L4B23_VAL_MSK;
2072 
2073 	return (NPI_SUCCESS);
2074 
2075 }
2076 
2077 /*
2078  * npi_fflp_cfg_ip_usr_cls_enable()
2079  * Enable previously configured TCAM user configurable IP classes.
2080  *
2081  * Input
2082  *      handle:	opaque handle interpreted by the underlying OS
2083  *      class:       IP Class  class
2084  *		     (TCAM_CLASS_IP_USER_4 <= class <= TCAM_CLASS_IP_USER_7)
2085  *
2086  * Return
2087  * NPI success/failure status code
2088  */
2089 npi_status_t
2090 npi_fflp_cfg_ip_usr_cls_enable(npi_handle_t handle, tcam_class_t class)
2091 {
2092 	uint64_t offset;
2093 	tcam_class_prg_ip_t ip_cls_cfg;
2094 
2095 	ASSERT(TCAM_L3_USR_CLASS_VALID(class));
2096 	if (!TCAM_L3_USR_CLASS_VALID(class)) {
2097 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
2098 		    " npi_fflp_cfg_ip_usr_cls_enable:"
2099 		    " Invalid class %d \n",
2100 		    class));
2101 		return (NPI_FFLP_TCAM_CLASS_INVALID);
2102 	}
2103 
2104 	offset = GET_TCAM_CLASS_OFFSET(class);
2105 	REG_PIO_READ64(handle, offset, &ip_cls_cfg.value);
2106 	ip_cls_cfg.bits.ldw.valid = 1;
2107 
2108 	REG_PIO_WRITE64(handle, offset, ip_cls_cfg.value);
2109 	return (NPI_SUCCESS);
2110 
2111 }
2112 
2113 /*
2114  * npi_fflp_cfg_ip_usr_cls_disable()
2115  * Disables previously configured TCAM user configurable IP classes.
2116  *
2117  * Input
2118  *      handle:	opaque handle interpreted by the underlying OS
2119  *      class:       IP Class  class
2120  *		     (TCAM_CLASS_IP_USER_4 <= class <= TCAM_CLASS_IP_USER_7)
2121  *
2122  * Return
2123  * NPI success/failure status code
2124  */
2125 npi_status_t
2126 npi_fflp_cfg_ip_usr_cls_disable(npi_handle_t handle, tcam_class_t class)
2127 {
2128 	uint64_t offset;
2129 	tcam_class_prg_ip_t ip_cls_cfg;
2130 
2131 	ASSERT(TCAM_L3_USR_CLASS_VALID(class));
2132 	if (!TCAM_L3_USR_CLASS_VALID(class)) {
2133 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
2134 		    " npi_fflp_cfg_ip_usr_cls_disable:"
2135 		    " Invalid class %d \n",
2136 		    class));
2137 		return (NPI_FFLP_TCAM_CLASS_INVALID);
2138 	}
2139 
2140 	offset = GET_TCAM_CLASS_OFFSET(class);
2141 
2142 	REG_PIO_READ64(handle, offset, &ip_cls_cfg.value);
2143 	ip_cls_cfg.bits.ldw.valid = 0;
2144 
2145 	REG_PIO_WRITE64(handle, offset, ip_cls_cfg.value);
2146 	return (NPI_SUCCESS);
2147 
2148 }
2149 
2150 /*
2151  * npi_fflp_cfg_ip_cls_tcam_key ()
2152  *
2153  * Configures the TCAM key generation for the IP classes
2154  *
2155  * Input
2156  *      handle:	opaque handle interpreted by the underlying OS
2157  *      l3_class:        IP class to configure key generation
2158  *      cfg:             Configuration bits:
2159  *                   discard:      Discard all frames of this class
2160  *                   use_ip_saddr: use ip src address (for ipv6)
2161  *                   use_ip_daddr: use ip dest address (for ipv6)
2162  *                   lookup_enable: Enable Lookup
2163  *
2164  *
2165  * Return
2166  * NPI success/failure status code
2167  */
2168 npi_status_t
2169 npi_fflp_cfg_ip_cls_tcam_key(npi_handle_t handle,
2170 			    tcam_class_t l3_class, tcam_key_cfg_t *cfg)
2171 {
2172 	uint64_t offset;
2173 	tcam_class_key_ip_t tcam_cls_cfg;
2174 
2175 	ASSERT(TCAM_L3_CLASS_VALID(l3_class));
2176 	if (!(TCAM_L3_CLASS_VALID(l3_class))) {
2177 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
2178 		    " npi_fflp_cfg_ip_cls_tcam_key:"
2179 		    " Invalid class %d \n",
2180 		    l3_class));
2181 		return (NPI_FFLP_TCAM_CLASS_INVALID);
2182 	}
2183 
2184 	if ((cfg->use_ip_daddr) &&
2185 	    (cfg->use_ip_saddr == cfg->use_ip_daddr)) {
2186 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
2187 		    " npi_fflp_cfg_ip_cls_tcam_key:"
2188 		    " Invalid configuration %x for class %d \n",
2189 		    *cfg, l3_class));
2190 		return (NPI_FFLP_SW_PARAM_ERROR);
2191 	}
2192 
2193 
2194 	offset = GET_TCAM_KEY_OFFSET(l3_class);
2195 	tcam_cls_cfg.value = 0;
2196 
2197 	if (cfg->discard) {
2198 		tcam_cls_cfg.bits.ldw.discard = 1;
2199 	}
2200 
2201 	if (cfg->use_ip_saddr) {
2202 		tcam_cls_cfg.bits.ldw.ipaddr = 1;
2203 	}
2204 
2205 	if (cfg->use_ip_daddr) {
2206 		tcam_cls_cfg.bits.ldw.ipaddr = 0;
2207 	}
2208 
2209 	if (cfg->lookup_enable) {
2210 		tcam_cls_cfg.bits.ldw.tsel = 1;
2211 	}
2212 
2213 	REG_PIO_WRITE64(handle, offset, tcam_cls_cfg.value);
2214 	return (NPI_SUCCESS);
2215 }
2216 
2217 /*
2218  * npi_fflp_cfg_ip_cls_flow_key ()
2219  *
2220  * Configures the flow key generation for the IP classes
2221  * Flow key is used to generate the H1 hash function value
2222  * The fields used for the generation are configured using this
2223  * NPI function.
2224  *
2225  * Input
2226  *      handle:	opaque handle interpreted by the underlying OS
2227  *      l3_class:        IP class to configure flow key generation
2228  *      cfg:             Configuration bits:
2229  *                   use_proto:     Use IP proto field
2230  *                   use_dport:     use l4 destination port
2231  *                   use_sport:     use l4 source port
2232  *                   ip_opts_exist: IP Options Present
2233  *                   use_daddr:     use ip dest address
2234  *                   use_saddr:     use ip source address
2235  *                   use_vlan:      use VLAN ID
2236  *                   use_l2da:      use L2 Dest MAC Address
2237  *                   use_portnum:   use L2 virtual port number
2238  *
2239  *
2240  * Return
2241  * NPI success/failure status code
2242  */
2243 npi_status_t
2244 npi_fflp_cfg_ip_cls_flow_key(npi_handle_t handle, tcam_class_t l3_class,
2245 							    flow_key_cfg_t *cfg)
2246 {
2247 	uint64_t offset;
2248 	flow_class_key_ip_t flow_cfg_reg;
2249 
2250 	ASSERT(TCAM_L3_CLASS_VALID(l3_class));
2251 	if (!(TCAM_L3_CLASS_VALID(l3_class))) {
2252 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
2253 		    " npi_fflp_cfg_ip_cls_flow_key:"
2254 		    " Invalid class %d \n",
2255 		    l3_class));
2256 		return (NPI_FFLP_TCAM_CLASS_INVALID);
2257 	}
2258 
2259 
2260 	offset = GET_FLOW_KEY_OFFSET(l3_class);
2261 	flow_cfg_reg.value = 0; /* default */
2262 
2263 	if (cfg->use_proto) {
2264 		flow_cfg_reg.bits.ldw.proto = 1;
2265 	}
2266 
2267 	if (cfg->use_dport) {
2268 		flow_cfg_reg.bits.ldw.l4_1 = 2;
2269 		if (cfg->ip_opts_exist)
2270 			flow_cfg_reg.bits.ldw.l4_1 = 3;
2271 	}
2272 
2273 	if (cfg->use_sport) {
2274 		flow_cfg_reg.bits.ldw.l4_0 = 2;
2275 		if (cfg->ip_opts_exist)
2276 			flow_cfg_reg.bits.ldw.l4_0 = 3;
2277 	}
2278 
2279 	if (cfg->use_daddr) {
2280 		flow_cfg_reg.bits.ldw.ipda = BIT_ENABLE;
2281 	}
2282 
2283 	if (cfg->use_saddr) {
2284 		flow_cfg_reg.bits.ldw.ipsa = BIT_ENABLE;
2285 	}
2286 
2287 	if (cfg->use_vlan) {
2288 		flow_cfg_reg.bits.ldw.vlan = BIT_ENABLE;
2289 	}
2290 
2291 	if (cfg->use_l2da) {
2292 		flow_cfg_reg.bits.ldw.l2da = BIT_ENABLE;
2293 	}
2294 
2295 	if (cfg->use_portnum) {
2296 		flow_cfg_reg.bits.ldw.port = BIT_ENABLE;
2297 	}
2298 
2299 	REG_PIO_WRITE64(handle, offset, flow_cfg_reg.value);
2300 	return (NPI_SUCCESS);
2301 
2302 }
2303 
2304 npi_status_t
2305 npi_fflp_cfg_ip_cls_flow_key_get(npi_handle_t handle,
2306 				    tcam_class_t l3_class,
2307 				    flow_key_cfg_t *cfg)
2308 {
2309 	uint64_t offset;
2310 	flow_class_key_ip_t flow_cfg_reg;
2311 
2312 	ASSERT(TCAM_L3_CLASS_VALID(l3_class));
2313 	if (!(TCAM_L3_CLASS_VALID(l3_class))) {
2314 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
2315 		    " npi_fflp_cfg_ip_cls_flow_key:"
2316 		    " Invalid class %d \n",
2317 		    l3_class));
2318 		return (NPI_FFLP_TCAM_CLASS_INVALID);
2319 	}
2320 
2321 	offset = GET_FLOW_KEY_OFFSET(l3_class);
2322 
2323 	cfg->use_proto = 0;
2324 	cfg->use_dport = 0;
2325 	cfg->use_sport = 0;
2326 	cfg->ip_opts_exist = 0;
2327 	cfg->use_daddr = 0;
2328 	cfg->use_saddr = 0;
2329 	cfg->use_vlan = 0;
2330 	cfg->use_l2da = 0;
2331 	cfg->use_portnum  = 0;
2332 
2333 	REG_PIO_READ64(handle, offset, &flow_cfg_reg.value);
2334 
2335 	if (flow_cfg_reg.bits.ldw.proto) {
2336 		cfg->use_proto = 1;
2337 	}
2338 
2339 	if (flow_cfg_reg.bits.ldw.l4_1 == 2) {
2340 		cfg->use_dport = 1;
2341 	}
2342 
2343 	if (flow_cfg_reg.bits.ldw.l4_1 == 3) {
2344 		cfg->use_dport = 1;
2345 		cfg->ip_opts_exist = 1;
2346 	}
2347 
2348 	if (flow_cfg_reg.bits.ldw.l4_0 == 2) {
2349 		cfg->use_sport = 1;
2350 	}
2351 
2352 	if (flow_cfg_reg.bits.ldw.l4_0 == 3) {
2353 		cfg->use_sport = 1;
2354 		cfg->ip_opts_exist = 1;
2355 	}
2356 
2357 	if (flow_cfg_reg.bits.ldw.ipda) {
2358 		cfg->use_daddr = 1;
2359 	}
2360 
2361 	if (flow_cfg_reg.bits.ldw.ipsa) {
2362 		cfg->use_saddr = 1;
2363 	}
2364 
2365 	if (flow_cfg_reg.bits.ldw.vlan) {
2366 		cfg->use_vlan = 1;
2367 	}
2368 
2369 	if (flow_cfg_reg.bits.ldw.l2da) {
2370 		cfg->use_l2da = 1;
2371 	}
2372 
2373 	if (flow_cfg_reg.bits.ldw.port) {
2374 		cfg->use_portnum = 1;
2375 	}
2376 
2377 	NPI_DEBUG_MSG((handle.function, NPI_FFLP_CTL,
2378 	    " npi_fflp_cfg_ip_cls_flow_get %llx \n",
2379 	    flow_cfg_reg.value));
2380 
2381 	return (NPI_SUCCESS);
2382 
2383 }
2384 
2385 /*
2386  * npi_fflp_cfg_ip_cls_flow_key_rfnl ()
2387  *
2388  * Configures the flow key generation for the IP classes
2389  * Flow key is used to generate the H1 hash function value
2390  * The fields used for the generation are configured using this
2391  * NPI function.
2392  *
2393  * Input
2394  *      handle:	opaque handle interpreted by the underlying OS
2395  *      l3_class:        IP class to configure flow key generation
2396  *      cfg:             Configuration bits:
2397  *		     l4_xor_sel:    bit field to select the L4 payload
2398  *				    bytes for X-OR to get hash key.
2399  *		     use_l4_md:	    Set to 1 for enabling L4-mode.
2400  *		     use_sym:	    Set to 1 to use symmetric mode.
2401  *                   use_proto:     Use IP proto field
2402  *                   use_dport:     use l4 destination port
2403  *                   use_sport:     use l4 source port
2404  *                   ip_opts_exist: IP Options Present
2405  *                   use_daddr:     use ip dest address
2406  *                   use_saddr:     use ip source address
2407  *                   use_vlan:      use VLAN ID
2408  *                   use_l2da:      use L2 Dest MAC Address
2409  *                   use_portnum:   use L2 virtual port number
2410  *
2411  *
2412  * Return
2413  * NPI success/failure status code
2414  */
2415 npi_status_t
2416 npi_fflp_cfg_ip_cls_flow_key_rfnl(npi_handle_t handle, tcam_class_t l3_class,
2417 		flow_key_cfg_t *cfg)
2418 {
2419 	uint64_t offset;
2420 	flow_class_key_ip_t flow_cfg_reg;
2421 
2422 	ASSERT(TCAM_L3_CLASS_VALID_RFNL(l3_class));
2423 	if (!(TCAM_L3_CLASS_VALID_RFNL(l3_class))) {
2424 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
2425 		    " npi_fflp_cfg_ip_cls_flow_key_rfnl:"
2426 		    " Invalid class %d \n",
2427 		    l3_class));
2428 		return (NPI_FFLP_TCAM_CLASS_INVALID);
2429 	}
2430 
2431 	if (l3_class == TCAM_CLASS_IPV6_FRAG) {
2432 		offset = FFLP_FLOW_KEY_IP6_FRAG_REG;
2433 	} else {
2434 		offset = GET_FLOW_KEY_OFFSET(l3_class);
2435 	}
2436 
2437 	flow_cfg_reg.value = 0;
2438 
2439 	flow_cfg_reg.bits.ldw.l4_xor = cfg->l4_xor_sel;
2440 
2441 	if (cfg->use_l4_md)
2442 		flow_cfg_reg.bits.ldw.l4_mode = 1;
2443 
2444 	if (cfg->use_sym)
2445 		flow_cfg_reg.bits.ldw.sym = 1;
2446 
2447 	if (cfg->use_proto) {
2448 		flow_cfg_reg.bits.ldw.proto = 1;
2449 	}
2450 
2451 	if (cfg->use_dport) {
2452 		flow_cfg_reg.bits.ldw.l4_1 = 2;
2453 		if (cfg->ip_opts_exist)
2454 			flow_cfg_reg.bits.ldw.l4_1 = 3;
2455 	}
2456 
2457 	if (cfg->use_sport) {
2458 		flow_cfg_reg.bits.ldw.l4_0 = 2;
2459 		if (cfg->ip_opts_exist)
2460 			flow_cfg_reg.bits.ldw.l4_0 = 3;
2461 	}
2462 
2463 	if (cfg->use_daddr) {
2464 		flow_cfg_reg.bits.ldw.ipda = BIT_ENABLE;
2465 	}
2466 
2467 	if (cfg->use_saddr) {
2468 		flow_cfg_reg.bits.ldw.ipsa = BIT_ENABLE;
2469 	}
2470 
2471 	if (cfg->use_vlan) {
2472 		flow_cfg_reg.bits.ldw.vlan = BIT_ENABLE;
2473 	}
2474 
2475 	if (cfg->use_l2da) {
2476 		flow_cfg_reg.bits.ldw.l2da = BIT_ENABLE;
2477 	}
2478 
2479 	if (cfg->use_portnum) {
2480 		flow_cfg_reg.bits.ldw.port = BIT_ENABLE;
2481 	}
2482 
2483 	REG_PIO_WRITE64(handle, offset, flow_cfg_reg.value);
2484 	return (NPI_SUCCESS);
2485 
2486 }
2487 
2488 npi_status_t
2489 npi_fflp_cfg_sym_ip_cls_flow_key(npi_handle_t handle, tcam_class_t l3_class,
2490 		boolean_t enable)
2491 {
2492 	uint64_t offset;
2493 	flow_class_key_ip_t flow_cfg_reg;
2494 
2495 	ASSERT(TCAM_L3_CLASS_VALID_RFNL(l3_class));
2496 	if (!(TCAM_L3_CLASS_VALID_RFNL(l3_class))) {
2497 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
2498 		    " npi_fflp_cfg_sym_ip_cls_flow_key:"
2499 		    " Invalid class %d \n",
2500 		    l3_class));
2501 		return (NPI_FFLP_TCAM_CLASS_INVALID);
2502 	}
2503 
2504 	if (l3_class == TCAM_CLASS_IPV6_FRAG) {
2505 		offset = FFLP_FLOW_KEY_IP6_FRAG_REG;
2506 	} else {
2507 		offset = GET_FLOW_KEY_OFFSET(l3_class);
2508 	}
2509 
2510 	REG_PIO_READ64(handle, offset, &flow_cfg_reg.value);
2511 
2512 	if (enable && flow_cfg_reg.bits.ldw.sym == 0) {
2513 		flow_cfg_reg.bits.ldw.sym = 1;
2514 		REG_PIO_WRITE64(handle, offset, flow_cfg_reg.value);
2515 	} else if (!enable && flow_cfg_reg.bits.ldw.sym == 1) {
2516 		flow_cfg_reg.bits.ldw.sym = 0;
2517 		REG_PIO_WRITE64(handle, offset, flow_cfg_reg.value);
2518 	}
2519 
2520 	return (NPI_SUCCESS);
2521 
2522 }
2523 
2524 npi_status_t
2525 npi_fflp_cfg_ip_cls_flow_key_get_rfnl(npi_handle_t handle,
2526 				    tcam_class_t l3_class,
2527 				    flow_key_cfg_t *cfg)
2528 {
2529 	uint64_t offset;
2530 	flow_class_key_ip_t flow_cfg_reg;
2531 
2532 	ASSERT(TCAM_L3_CLASS_VALID_RFNL(l3_class));
2533 	if (!(TCAM_L3_CLASS_VALID_RFNL(l3_class))) {
2534 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
2535 		    " npi_fflp_cfg_ip_cls_flow_key_get_rfnl:"
2536 		    " Invalid class %d \n",
2537 		    l3_class));
2538 		return (NPI_FFLP_TCAM_CLASS_INVALID);
2539 	}
2540 
2541 	if (l3_class == TCAM_CLASS_IPV6_FRAG) {
2542 		offset = FFLP_FLOW_KEY_IP6_FRAG_REG;
2543 	} else {
2544 		offset = GET_FLOW_KEY_OFFSET(l3_class);
2545 	}
2546 
2547 	cfg->l4_xor_sel = 0;
2548 	cfg->use_l4_md = 0;
2549 	cfg->use_sym = 0;
2550 	cfg->use_proto = 0;
2551 	cfg->use_dport = 0;
2552 	cfg->use_sport = 0;
2553 	cfg->ip_opts_exist = 0;
2554 	cfg->use_daddr = 0;
2555 	cfg->use_saddr = 0;
2556 	cfg->use_vlan = 0;
2557 	cfg->use_l2da = 0;
2558 	cfg->use_portnum  = 0;
2559 
2560 	REG_PIO_READ64(handle, offset, &flow_cfg_reg.value);
2561 
2562 	cfg->l4_xor_sel = flow_cfg_reg.bits.ldw.l4_xor;
2563 
2564 	if (flow_cfg_reg.bits.ldw.l4_mode)
2565 		cfg->use_l4_md = 1;
2566 
2567 	if (flow_cfg_reg.bits.ldw.sym)
2568 		cfg->use_sym = 1;
2569 
2570 	if (flow_cfg_reg.bits.ldw.proto) {
2571 		cfg->use_proto = 1;
2572 	}
2573 
2574 	if (flow_cfg_reg.bits.ldw.l4_1 == 2) {
2575 		cfg->use_dport = 1;
2576 	}
2577 
2578 	if (flow_cfg_reg.bits.ldw.l4_1 == 3) {
2579 		cfg->use_dport = 1;
2580 		cfg->ip_opts_exist = 1;
2581 	}
2582 
2583 	if (flow_cfg_reg.bits.ldw.l4_0 == 2) {
2584 		cfg->use_sport = 1;
2585 	}
2586 
2587 	if (flow_cfg_reg.bits.ldw.l4_0 == 3) {
2588 		cfg->use_sport = 1;
2589 		cfg->ip_opts_exist = 1;
2590 	}
2591 
2592 	if (flow_cfg_reg.bits.ldw.ipda) {
2593 		cfg->use_daddr = 1;
2594 	}
2595 
2596 	if (flow_cfg_reg.bits.ldw.ipsa) {
2597 		cfg->use_saddr = 1;
2598 	}
2599 
2600 	if (flow_cfg_reg.bits.ldw.vlan) {
2601 		cfg->use_vlan = 1;
2602 	}
2603 
2604 	if (flow_cfg_reg.bits.ldw.l2da) {
2605 		cfg->use_l2da = 1;
2606 	}
2607 
2608 	if (flow_cfg_reg.bits.ldw.port) {
2609 		cfg->use_portnum = 1;
2610 	}
2611 
2612 	NPI_DEBUG_MSG((handle.function, NPI_FFLP_CTL,
2613 	    " npi_fflp_cfg_ip_cls_flow_get %llx \n",
2614 	    flow_cfg_reg.value));
2615 
2616 	return (NPI_SUCCESS);
2617 
2618 }
2619 
2620 npi_status_t
2621 npi_fflp_cfg_ip_cls_tcam_key_get(npi_handle_t handle,
2622 			    tcam_class_t l3_class, tcam_key_cfg_t *cfg)
2623 {
2624 	uint64_t offset;
2625 	tcam_class_key_ip_t tcam_cls_cfg;
2626 
2627 	ASSERT(TCAM_L3_CLASS_VALID(l3_class));
2628 	if (!(TCAM_L3_CLASS_VALID(l3_class))) {
2629 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
2630 		    " npi_fflp_cfg_ip_cls_tcam_key_get:"
2631 		    " Invalid class %d \n",
2632 		    l3_class));
2633 		return (NPI_FFLP_TCAM_CLASS_INVALID);
2634 	}
2635 
2636 
2637 	offset = GET_TCAM_KEY_OFFSET(l3_class);
2638 
2639 	REG_PIO_READ64(handle, offset, &tcam_cls_cfg.value);
2640 
2641 	cfg->discard = 0;
2642 	cfg->use_ip_saddr = 0;
2643 	cfg->use_ip_daddr = 1;
2644 	cfg->lookup_enable = 0;
2645 
2646 	if (tcam_cls_cfg.bits.ldw.discard)
2647 			cfg->discard = 1;
2648 
2649 	if (tcam_cls_cfg.bits.ldw.ipaddr) {
2650 		cfg->use_ip_saddr = 1;
2651 		cfg->use_ip_daddr = 0;
2652 	}
2653 
2654 	if (tcam_cls_cfg.bits.ldw.tsel) {
2655 		cfg->lookup_enable = 1;
2656 	}
2657 
2658 	NPI_DEBUG_MSG((handle.function, NPI_CTL,
2659 	    " npi_fflp_cfg_ip_cls_tcam_key_get %llx \n",
2660 	    tcam_cls_cfg.value));
2661 	return (NPI_SUCCESS);
2662 }
2663 
2664 /*
2665  * npi_fflp_cfg_fcram_access ()
2666  *
2667  * Sets the ratio between the FCRAM pio and lookup access
2668  * Input:
2669  * handle:	opaque handle interpreted by the underlying OS
2670  * access_ratio: 0  Lookup has the highest priority
2671  *		 15 PIO has maximum possible priority
2672  *
2673  * Return
2674  * NPI success/failure status code
2675  */
2676 npi_status_t
2677 npi_fflp_cfg_fcram_access(npi_handle_t handle, uint8_t access_ratio)
2678 {
2679 
2680 	fflp_cfg_1_t fflp_cfg;
2681 	uint64_t offset;
2682 	offset = FFLP_CFG_1_REG;
2683 
2684 	if (access_ratio > 0xf) {
2685 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
2686 		    " npi_fflp_cfg_fcram_access:"
2687 		    " Invalid access ratio %d \n",
2688 		    access_ratio));
2689 		return (NPI_FFLP_ERROR | NPI_FFLP_SW_PARAM_ERROR);
2690 	}
2691 
2692 	REG_PIO_READ64(handle, offset, &fflp_cfg.value);
2693 	fflp_cfg.bits.ldw.fflpinitdone = 0;
2694 	fflp_cfg.bits.ldw.fcramratio = access_ratio;
2695 	REG_PIO_WRITE64(handle, offset, fflp_cfg.value);
2696 	REG_PIO_READ64(handle, offset, &fflp_cfg.value);
2697 	fflp_cfg.bits.ldw.fflpinitdone = 1;
2698 	REG_PIO_WRITE64(handle, offset, fflp_cfg.value);
2699 	return (NPI_SUCCESS);
2700 
2701 }
2702 
2703 /*
2704  * npi_fflp_cfg_tcam_access ()
2705  *
2706  * Sets the ratio between the TCAM pio and lookup access
2707  * Input:
2708  * handle:	opaque handle interpreted by the underlying OS
2709  * access_ratio: 0  Lookup has the highest priority
2710  *		 15 PIO has maximum possible priority
2711  * Return
2712  * NPI success/failure status code
2713  */
2714 npi_status_t
2715 npi_fflp_cfg_tcam_access(npi_handle_t handle, uint8_t access_ratio)
2716 {
2717 	fflp_cfg_1_t fflp_cfg;
2718 	uint64_t offset;
2719 	offset = FFLP_CFG_1_REG;
2720 
2721 	if (access_ratio > 0xf) {
2722 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
2723 		    " npi_fflp_cfg_tcram_access:"
2724 		    " Invalid access ratio %d \n",
2725 		    access_ratio));
2726 		return (NPI_FFLP_ERROR | NPI_FFLP_SW_PARAM_ERROR);
2727 	}
2728 
2729 	REG_PIO_READ64(handle, offset, &fflp_cfg.value);
2730 	fflp_cfg.bits.ldw.fflpinitdone = 0;
2731 	fflp_cfg.bits.ldw.camratio = access_ratio;
2732 
2733 	/* since the cam latency is fixed, we might set it here */
2734 	fflp_cfg.bits.ldw.camlatency = TCAM_DEFAULT_LATENCY;
2735 	REG_PIO_WRITE64(handle, offset, fflp_cfg.value);
2736 	REG_PIO_READ64(handle, offset, &fflp_cfg.value);
2737 	fflp_cfg.bits.ldw.fflpinitdone = 1;
2738 	REG_PIO_WRITE64(handle, offset, fflp_cfg.value);
2739 
2740 	return (NPI_SUCCESS);
2741 }
2742 
2743 /*
2744  * npi_fflp_cfg_hash_h1poly()
2745  * Initializes the H1 hash generation logic.
2746  *
2747  * Input
2748  *      handle:	opaque handle interpreted by the underlying OS
2749  *      init_value:       The initial value (seed)
2750  *
2751  * Return
2752  * NPI success/failure status code
2753  */
2754 npi_status_t
2755 npi_fflp_cfg_hash_h1poly(npi_handle_t handle, uint32_t init_value)
2756 {
2757 
2758 
2759 	hash_h1poly_t h1_cfg;
2760 	uint64_t offset;
2761 	offset = FFLP_H1POLY_REG;
2762 
2763 	h1_cfg.value = 0;
2764 	h1_cfg.bits.ldw.init_value = init_value;
2765 
2766 	REG_PIO_WRITE64(handle, offset, h1_cfg.value);
2767 	return (NPI_SUCCESS);
2768 }
2769 
2770 /*
2771  * npi_fflp_cfg_hash_h2poly()
2772  * Initializes the H2 hash generation logic.
2773  *
2774  * Input
2775  *      handle:	opaque handle interpreted by the underlying OS
2776  *      init_value:       The initial value (seed)
2777  *
2778  * Return
2779  * NPI_SUCCESS
2780  *
2781  */
2782 npi_status_t
2783 npi_fflp_cfg_hash_h2poly(npi_handle_t handle, uint16_t init_value)
2784 {
2785 
2786 
2787 	hash_h2poly_t h2_cfg;
2788 	uint64_t offset;
2789 	offset = FFLP_H2POLY_REG;
2790 
2791 	h2_cfg.value = 0;
2792 	h2_cfg.bits.ldw.init_value = init_value;
2793 
2794 	REG_PIO_WRITE64(handle, offset, h2_cfg.value);
2795 	return (NPI_SUCCESS);
2796 
2797 
2798 }
2799 
2800 /*
2801  *  npi_fflp_cfg_reset
2802  *  Initializes the FCRAM reset sequence.
2803  *
2804  *  Input
2805  *      handle:		opaque handle interpreted by the underlying OS
2806  *	strength:		FCRAM Drive strength
2807  *				   strong, weak or normal
2808  *				   HW recommended value:
2809  *	qs:			FCRAM QS mode selection
2810  *				   qs mode or free running
2811  *				   HW recommended value is:
2812  *
2813  * Return:
2814  * NPI success/failure status code
2815  */
2816 
2817 npi_status_t
2818 npi_fflp_cfg_fcram_reset(npi_handle_t handle,
2819 	fflp_fcram_output_drive_t strength, fflp_fcram_qs_t qs)
2820 {
2821 	fflp_cfg_1_t fflp_cfg;
2822 	uint64_t offset;
2823 	offset = FFLP_CFG_1_REG;
2824 
2825 	/* These bits have to be configured before FCRAM reset is issued */
2826 	fflp_cfg.value = 0;
2827 	fflp_cfg.bits.ldw.pio_fio_rst = 1;
2828 	REG_PIO_WRITE64(handle, offset, fflp_cfg.value);
2829 
2830 	NXGE_DELAY(5); /* TODO: What is the correct delay? */
2831 
2832 	fflp_cfg.bits.ldw.pio_fio_rst = 0;
2833 	REG_PIO_WRITE64(handle, offset, fflp_cfg.value);
2834 	fflp_cfg.bits.ldw.fcramqs = qs;
2835 	fflp_cfg.bits.ldw.fcramoutdr = strength;
2836 	fflp_cfg.bits.ldw.fflpinitdone = 1;
2837 	REG_PIO_WRITE64(handle, offset, fflp_cfg.value);
2838 
2839 	return (NPI_SUCCESS);
2840 }
2841 
2842 npi_status_t
2843 npi_fflp_cfg_init_done(npi_handle_t handle)
2844 
2845 {
2846 
2847 	fflp_cfg_1_t fflp_cfg;
2848 	uint64_t offset;
2849 	offset = FFLP_CFG_1_REG;
2850 
2851 	REG_PIO_READ64(handle, offset, &fflp_cfg.value);
2852 	fflp_cfg.bits.ldw.fflpinitdone = 1;
2853 	REG_PIO_WRITE64(handle, offset, fflp_cfg.value);
2854 	return (NPI_SUCCESS);
2855 
2856 }
2857 
2858 npi_status_t
2859 npi_fflp_cfg_init_start(npi_handle_t handle)
2860 
2861 {
2862 
2863 	fflp_cfg_1_t fflp_cfg;
2864 	uint64_t offset;
2865 	offset = FFLP_CFG_1_REG;
2866 
2867 	REG_PIO_READ64(handle, offset, &fflp_cfg.value);
2868 	fflp_cfg.bits.ldw.fflpinitdone = 0;
2869 	REG_PIO_WRITE64(handle, offset, fflp_cfg.value);
2870 	return (NPI_SUCCESS);
2871 
2872 }
2873 
2874 /*
2875  * Enables the TCAM search function.
2876  *
2877  */
2878 npi_status_t
2879 npi_fflp_cfg_tcam_enable(npi_handle_t handle)
2880 
2881 {
2882 
2883 	fflp_cfg_1_t fflp_cfg;
2884 	uint64_t offset;
2885 	offset = FFLP_CFG_1_REG;
2886 	REG_PIO_READ64(handle, offset, &fflp_cfg.value);
2887 	fflp_cfg.bits.ldw.tcam_disable = 0;
2888 	REG_PIO_WRITE64(handle, offset, fflp_cfg.value);
2889 	return (NPI_SUCCESS);
2890 
2891 }
2892 
2893 /*
2894  * Disables the TCAM search function.
2895  * While the TCAM is in disabled state, all TCAM matches would return NO_MATCH
2896  *
2897  */
2898 npi_status_t
2899 npi_fflp_cfg_tcam_disable(npi_handle_t handle)
2900 
2901 {
2902 
2903 	fflp_cfg_1_t fflp_cfg;
2904 	uint64_t offset;
2905 	offset = FFLP_CFG_1_REG;
2906 	REG_PIO_READ64(handle, offset, &fflp_cfg.value);
2907 	fflp_cfg.bits.ldw.tcam_disable = 1;
2908 	REG_PIO_WRITE64(handle, offset, fflp_cfg.value);
2909 	return (NPI_SUCCESS);
2910 
2911 }
2912 
2913 /*
2914  * npi_rxdma_event_mask_config():
2915  *	This function is called to operate on the event mask
2916  *	register which is used for generating interrupts
2917  *	and status register.
2918  */
2919 npi_status_t
2920 npi_fflp_event_mask_config(npi_handle_t handle, io_op_t op_mode,
2921 		fflp_event_mask_cfg_t *mask_cfgp)
2922 {
2923 	int		status = NPI_SUCCESS;
2924 	fflp_err_mask_t mask_reg;
2925 
2926 	switch (op_mode) {
2927 	case OP_GET:
2928 
2929 		REG_PIO_READ64(handle, FFLP_ERR_MSK_REG, &mask_reg.value);
2930 		*mask_cfgp = mask_reg.value & FFLP_ERR_MASK_ALL;
2931 		break;
2932 
2933 	case OP_SET:
2934 		mask_reg.value = (~(*mask_cfgp) & FFLP_ERR_MASK_ALL);
2935 		REG_PIO_WRITE64(handle, FFLP_ERR_MSK_REG, mask_reg.value);
2936 		break;
2937 
2938 	case OP_UPDATE:
2939 		REG_PIO_READ64(handle, FFLP_ERR_MSK_REG, &mask_reg.value);
2940 		mask_reg.value |=  (~(*mask_cfgp) & FFLP_ERR_MASK_ALL);
2941 		REG_PIO_WRITE64(handle, FFLP_ERR_MSK_REG, mask_reg.value);
2942 		break;
2943 
2944 	case OP_CLEAR:
2945 		mask_reg.value = FFLP_ERR_MASK_ALL;
2946 		REG_PIO_WRITE64(handle, FFLP_ERR_MSK_REG, mask_reg.value);
2947 		break;
2948 	default:
2949 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
2950 		    " npi_fflp_event_mask_config",
2951 		    " eventmask <0x%x>", op_mode));
2952 		return (NPI_FFLP_ERROR | NPI_FFLP_SW_PARAM_ERROR);
2953 	}
2954 
2955 	return (status);
2956 }
2957 
2958 /*
2959  * Read vlan error bits
2960  */
2961 void
2962 npi_fflp_vlan_error_get(npi_handle_t handle, p_vlan_par_err_t p_err)
2963 {
2964 	REG_PIO_READ64(handle, FFLP_VLAN_PAR_ERR_REG, &p_err->value);
2965 }
2966 
2967 /*
2968  * clear vlan error bits
2969  */
2970 void
2971 npi_fflp_vlan_error_clear(npi_handle_t handle)
2972 {
2973 	vlan_par_err_t p_err;
2974 	p_err.value  = 0;
2975 	p_err.bits.ldw.m_err = 0;
2976 	p_err.bits.ldw.err = 0;
2977 	REG_PIO_WRITE64(handle, FFLP_ERR_MSK_REG, p_err.value);
2978 
2979 }
2980 
2981 /*
2982  * Read TCAM error bits
2983  */
2984 void
2985 npi_fflp_tcam_error_get(npi_handle_t handle, p_tcam_err_t p_err)
2986 {
2987 	REG_PIO_READ64(handle, FFLP_TCAM_ERR_REG, &p_err->value);
2988 }
2989 
2990 /*
2991  * clear TCAM error bits
2992  */
2993 void
2994 npi_fflp_tcam_error_clear(npi_handle_t handle)
2995 {
2996 	tcam_err_t p_err;
2997 
2998 	p_err.value  = 0;
2999 	p_err.bits.ldw.p_ecc = 0;
3000 	p_err.bits.ldw.mult = 0;
3001 	p_err.bits.ldw.err = 0;
3002 	REG_PIO_WRITE64(handle, FFLP_TCAM_ERR_REG, p_err.value);
3003 
3004 }
3005 
3006 /*
3007  * Read FCRAM error bits
3008  */
3009 void
3010 npi_fflp_fcram_error_get(npi_handle_t handle,
3011 	p_hash_tbl_data_log_t p_err, uint8_t partition)
3012 {
3013 	uint64_t offset;
3014 
3015 	offset = FFLP_HASH_TBL_DATA_LOG_REG + partition * 8192;
3016 	REG_PIO_READ64(handle, offset, &p_err->value);
3017 }
3018 
3019 /*
3020  * clear FCRAM error bits
3021  */
3022 void
3023 npi_fflp_fcram_error_clear(npi_handle_t handle, uint8_t partition)
3024 {
3025 	hash_tbl_data_log_t p_err;
3026 	uint64_t offset;
3027 
3028 	p_err.value  = 0;
3029 	p_err.bits.ldw.pio_err = 0;
3030 	offset = FFLP_HASH_TBL_DATA_LOG_REG + partition * 8192;
3031 
3032 	REG_PIO_WRITE64(handle, offset,
3033 	    p_err.value);
3034 
3035 }
3036 
3037 /*
3038  * Read FCRAM lookup error log1 bits
3039  */
3040 void
3041 npi_fflp_fcram_error_log1_get(npi_handle_t handle,
3042 			    p_hash_lookup_err_log1_t log1)
3043 {
3044 	REG_PIO_READ64(handle, HASH_LKUP_ERR_LOG1_REG,
3045 	    &log1->value);
3046 }
3047 
3048 /*
3049  * Read FCRAM lookup error log2 bits
3050  */
3051 void
3052 npi_fflp_fcram_error_log2_get(npi_handle_t handle,
3053 		    p_hash_lookup_err_log2_t log2)
3054 {
3055 	REG_PIO_READ64(handle, HASH_LKUP_ERR_LOG2_REG,
3056 	    &log2->value);
3057 }
3058