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