]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sys/contrib/octeon-sdk/cvmx-dfa.h
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / sys / contrib / octeon-sdk / cvmx-dfa.h
1 /***********************license start***************
2  * Copyright (c) 2003-2010  Cavium Inc. (support@cavium.com). All rights
3  * reserved.
4  *
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are
8  * met:
9  *
10  *   * Redistributions of source code must retain the above copyright
11  *     notice, this list of conditions and the following disclaimer.
12  *
13  *   * Redistributions in binary form must reproduce the above
14  *     copyright notice, this list of conditions and the following
15  *     disclaimer in the documentation and/or other materials provided
16  *     with the distribution.
17
18  *   * Neither the name of Cavium Inc. nor the names of
19  *     its contributors may be used to endorse or promote products
20  *     derived from this software without specific prior written
21  *     permission.
22
23  * This Software, including technical data, may be subject to U.S. export  control
24  * laws, including the U.S. Export Administration Act and its  associated
25  * regulations, and may be subject to export or import  regulations in other
26  * countries.
27
28  * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
29  * AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
30  * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO
31  * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR
32  * DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM
33  * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE,
34  * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF
35  * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR
36  * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE  RISK ARISING OUT OF USE OR
37  * PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
38  ***********************license end**************************************/
39
40
41
42
43
44
45
46 /**
47  * @file
48  *
49  * Interface to the CN31XX, CN38XX, and CN58XX hardware DFA engine.
50  *
51  * <hr>$Revision: 70030 $<hr>
52  */
53
54 #ifndef __CVMX_DFA_H__
55 #define __CVMX_DFA_H__
56 #include "cvmx-llm.h"
57 #include "cvmx-wqe.h"
58 #include "cvmx-fpa.h"
59
60 #include "executive-config.h"
61 #ifdef CVMX_ENABLE_DFA_FUNCTIONS
62 #include "cvmx-config.h"
63 #endif
64
65 #define ENABLE_DEPRECATED   /* Set to enable the old 18/36 bit names */
66
67 #ifdef  __cplusplus
68 extern "C" {
69 #endif
70
71
72 /* Maximum nodes available in a small encoding */
73 #define CVMX_DFA_NODESM_MAX_NODES       ((OCTEON_IS_MODEL(OCTEON_CN31XX)) ? 0x8000 : 0x20000)
74 #define CVMX_DFA_NODESM_SIZE            512     /* Size of each node for small encoding */
75 #define CVMX_DFA_NODELG_SIZE            1024    /* Size of each node for large encoding */
76 #define CVMX_DFA_NODESM_LAST_TERMINAL  (CVMX_DFA_NODESM_MAX_NODES-1)
77
78 #ifdef ENABLE_DEPRECATED
79 /* These defines are for compatability with old code. They are deprecated */
80 #define CVMX_DFA_NODE18_SIZE            CVMX_DFA_NODESM_SIZE
81 #define CVMX_DFA_NODE36_SIZE            CVMX_DFA_NODELG_SIZE
82 #define CVMX_DFA_NODE18_MAX_NODES       CVMX_DFA_NODESM_MAX_NODES
83 #define CVMX_DFA_NODE18_LAST_TERMINAL   CVMX_DFA_NODESM_LAST_TERMINAL
84 #endif
85
86 /**
87  * Which type of memory encoding is this graph using. Make sure you setup
88  * the LLM to match.
89  */
90 typedef enum
91 {
92     CVMX_DFA_GRAPH_TYPE_SM              = 0,
93     CVMX_DFA_GRAPH_TYPE_LG              = 1,
94 #ifdef ENABLE_DEPRECATED
95     CVMX_DFA_GRAPH_TYPE_18b             = 0,    /* Deprecated */
96     CVMX_DFA_GRAPH_TYPE_36b             = 1     /* Deprecated */
97 #endif
98 } cvmx_dfa_graph_type_t;
99
100 /**
101  * The possible node types.
102  */
103 typedef enum
104 {
105     CVMX_DFA_NODE_TYPE_NORMAL           = 0,    /**< Node is a branch */
106     CVMX_DFA_NODE_TYPE_MARKED           = 1,    /**< Node is marked special */
107     CVMX_DFA_NODE_TYPE_TERMINAL         = 2     /**< Node is a terminal leaf */
108 } cvmx_dfa_node_type_t;
109
110 /**
111  * The possible reasons the DFA stopped processing.
112  */
113 typedef enum
114 {
115     CVMX_DFA_STOP_REASON_DATA_GONE      = 0,    /**< DFA ran out of data */
116     CVMX_DFA_STOP_REASON_PARITY_ERROR   = 1,    /**< DFA encountered a memory error */
117     CVMX_DFA_STOP_REASON_FULL           = 2,    /**< DFA is full */
118     CVMX_DFA_STOP_REASON_TERMINAL       = 3     /**< DFA hit a terminal */
119 } cvmx_dfa_stop_reason_t;
120
121 /**
122  * This format describes the DFA pointers in small mode
123  */
124 typedef union
125 {
126     uint64_t u64;
127     struct
128     {
129         uint64_t                mbz         :32;/**< Must be zero */
130         uint64_t                p1          : 1;/**< Set if next_node1 is odd parity */
131         uint64_t                next_node1  :15;/**< Next node if an odd character match */
132         uint64_t                p0          : 1;/**< Set if next_node0 is odd parity */
133         uint64_t                next_node0  :15;/**< Next node if an even character match */
134     } w32;
135     struct
136     {
137         uint64_t                mbz         :28;/**< Must be zero */
138         uint64_t                p1          : 1;/**< Set if next_node1 is odd parity */
139         uint64_t                next_node1  :17;/**< Next node if an odd character match */
140         uint64_t                p0          : 1;/**< Set if next_node0 is odd parity */
141         uint64_t                next_node0  :17;/**< Next node if an even character match */
142     } w36;
143     struct /**< @ this structure only applies starting in CN58XX and if DFA_CFG[NRPL_ENA] == 1 and IWORD0[NREPLEN] == 1.  */
144     {
145         uint64_t                mbz         :28;/**< Must be zero */
146         uint64_t                p1          : 1;/**< Set if next_node1 is odd parity */
147         uint64_t                per_node_repl1  : 1;/**< enable for extra replicaiton for next node (CN58XX) */
148         uint64_t                next_node_repl1 : 2;/**< extra replicaiton for next node (CN58XX) (if per_node_repl1 is set) */
149         uint64_t                next_node1  :14;/**< Next node if an odd character match - IWORD3[Msize], if per_node_repl1==1. */
150         uint64_t                p0          : 1;/**< Set if next_node0 is odd parity */
151         uint64_t                per_node_repl0  : 1;/**< enable for extra replicaiton for next node (CN58XX) */
152         uint64_t                next_node_repl0 : 2;/**< extra replicaiton for next node (CN58XX) (if per_node_repl0 is set) */
153         uint64_t                next_node0  :14;/**< Next node if an odd character match - IWORD3[Msize], if per_node_repl0==1. */
154     } w36nrepl_en; /**< use when next_node_repl[01] is 1. */
155     struct /**< this structure only applies starting in CN58XX and if DFA_CFG[NRPL_ENA] == 1 and IWORD0[NREPLEN] == 1.  */
156     {
157         uint64_t                mbz         :28;/**< Must be zero */
158         uint64_t                p1          : 1;/**< Set if next_node1 is odd parity */
159         uint64_t                per_node_repl1  : 1;/**< enable for extra replicaiton for next node (CN58XX) */
160         uint64_t                next_node1  :16;/**< Next node if an odd character match, if per_node_repl1==0. */
161         uint64_t                p0          : 1;/**< Set if next_node0 is odd parity */
162         uint64_t                per_node_repl0  : 1;/**< enable for extra replicaiton for next node (CN58XX) */
163         uint64_t                next_node0  :16;/**< Next node if an odd character match, if per_node_repl0==0. */
164     } w36nrepl_dis; /**< use when next_node_repl[01] is 0. */
165 #if defined(ENABLE_DEPRECATED) && !OCTEON_IS_COMMON_BINARY()
166 #if CVMX_COMPILED_FOR(OCTEON_CN31XX)
167     struct /**< @deprecated unnamed reference to members */
168     {
169         uint64_t                mbz         :32;/**< Must be zero */
170         uint64_t                p1          : 1;/**< Set if next_node1 is odd parity */
171         uint64_t                next_node1  :15;/**< Next node if an odd character match */
172         uint64_t                p0          : 1;/**< Set if next_node0 is odd parity */
173         uint64_t                next_node0  :15;/**< Next node if an even character match */
174     };
175 #elif CVMX_COMPILED_FOR(OCTEON_CN38XX)
176     struct /**< @deprecated unnamed reference to members */
177     {
178         uint64_t                mbz         :28;/**< Must be zero */
179         uint64_t                p1          : 1;/**< Set if next_node1 is odd parity */
180         uint64_t                next_node1  :17;/**< Next node if an odd character match */
181         uint64_t                p0          : 1;/**< Set if next_node0 is odd parity */
182         uint64_t                next_node0  :17;/**< Next node if an even character match */
183     };
184 #else
185     /* Other chips don't support the deprecated unnamed unions */
186 #endif
187 #endif
188 } cvmx_dfa_node_next_sm_t;
189
190 /**
191  * This format describes the DFA pointers in large mode
192  */
193 typedef union
194 {
195     uint64_t u64;
196     struct
197     {
198         uint64_t                mbz         :32;/**< Must be zero */
199         uint64_t                ecc         : 7;/**< ECC checksum on the rest of the bits */
200         cvmx_dfa_node_type_t    type        : 2;/**< Node type */
201         uint64_t                mbz2        : 3;/**< Must be zero */
202         uint64_t                next_node   :20;/**< Next node */
203     } w32;
204     struct
205     {
206         uint64_t                mbz         :28;/**< Must be zero */
207         uint64_t                ecc         : 7;/**< ECC checksum on the rest of the bits */
208         cvmx_dfa_node_type_t    type        : 2;/**< Node type */
209         uint64_t                extra_bits     : 5;/**< bits copied to report (PASS3/CN58XX), Must be zero previously */
210         uint64_t                next_node_repl : 2;/**< extra replicaiton for next node (PASS3/CN58XX), Must be zero previously */
211         uint64_t                next_node   :20;/**< Next node ID,  Note, combine with next_node_repl to use as start_node
212                                                      for continuation, as in cvmx_dfa_node_next_lgb_t. */
213     } w36;
214 #if defined(ENABLE_DEPRECATED) && !OCTEON_IS_COMMON_BINARY()
215 #if CVMX_COMPILED_FOR(OCTEON_CN31XX)
216     struct /**< @deprecated unnamed reference to members */
217     {
218         uint64_t                mbz         :32;/**< Must be zero */
219         uint64_t                ecc         : 7;/**< ECC checksum on the rest of the bits */
220         cvmx_dfa_node_type_t    type        : 2;/**< Node type */
221         uint64_t                mbz2        : 3;/**< Must be zero */
222         uint64_t                next_node   :20;/**< Next node */
223     };
224 #elif CVMX_COMPILED_FOR(OCTEON_CN38XX)
225     struct /**< @deprecated unnamed reference to members */
226     {
227         uint64_t                mbz         :28;/**< Must be zero */
228         uint64_t                ecc         : 7;/**< ECC checksum on the rest of the bits */
229         cvmx_dfa_node_type_t    type        : 2;/**< Node type */
230         uint64_t                extra_bits     : 5;/**< bits copied to report (PASS3/CN58XX), Must be zero previously */
231         uint64_t                next_node_repl : 2;/**< extra replicaiton for next node (PASS3/CN58XX), Must be zero previously */
232         uint64_t                next_node   :20;/**< Next node ID,  Note, combine with next_node_repl to use as start_node
233                                                      for continuation, as in cvmx_dfa_node_next_lgb_t. */
234     };
235 #else
236     /* Other chips don't support the deprecated unnamed unions */
237 #endif
238 #endif
239 } cvmx_dfa_node_next_lg_t;
240
241 /**
242  * This format describes the DFA pointers in large mode, another way
243  */
244 typedef union
245 {
246     uint64_t u64;
247     struct
248     {
249         uint64_t                mbz         :32;/**< Must be zero */
250         uint64_t                ecc         : 7;/**< ECC checksum on the rest of the bits */
251         uint64_t                type_terminal : 1;/**< Node type */
252         uint64_t                type_marked   : 1;/**< Node type */
253         uint64_t                mbz2        : 3;/**< Must be zero */
254         uint64_t                next_node   :20;/**< Next node */
255     } w32;
256     struct
257     {
258         uint64_t                mbz         :28;/**< Must be zero */
259         uint64_t                ecc         : 7;/**< ECC checksum on the rest of the bits */
260         uint64_t                type_terminal : 1;/**< Node type */
261         uint64_t                type_marked   : 1;/**< Node type */
262         uint64_t                extra_bits     : 5;/**< bits copied to report (PASS3/CN58XX), Must be zero previously */
263         uint64_t                next_node_id_and_repl   :22;/**< Next node ID (and repl for PASS3/CN58XX or repl=0 if not),
264                                                                  use this as start node for continuation. */
265     } w36;
266 #if defined(ENABLE_DEPRECATED) && !OCTEON_IS_COMMON_BINARY()
267 #if CVMX_COMPILED_FOR(OCTEON_CN31XX)
268     struct /**< @deprecated unnamed reference to members */
269     {
270         uint64_t                mbz         :32;/**< Must be zero */
271         uint64_t                ecc         : 7;/**< ECC checksum on the rest of the bits */
272         uint64_t                type_terminal : 1;/**< Node type */
273         uint64_t                type_marked   : 1;/**< Node type */
274         uint64_t                mbz2        : 3;/**< Must be zero */
275         uint64_t                next_node   :20;/**< Next node */
276     };
277 #elif CVMX_COMPILED_FOR(OCTEON_CN38XX)
278     struct /**< @deprecated unnamed reference to members */
279     {
280         uint64_t                mbz         :28;/**< Must be zero */
281         uint64_t                ecc         : 7;/**< ECC checksum on the rest of the bits */
282         uint64_t                type_terminal : 1;/**< Node type */
283         uint64_t                type_marked   : 1;/**< Node type */
284         uint64_t                extra_bits     : 5;/**< bits copied to report (PASS3/CN58XX), Must be zero previously */
285         uint64_t                next_node_id_and_repl   :22;/**< Next node ID (and repl for PASS3/CN58XX or repl=0 if not),
286                                                                  use this as start node for continuation. */
287     };
288 #else
289     /* Other chips don't support the deprecated unnamed unions */
290 #endif
291 #endif
292 } cvmx_dfa_node_next_lgb_t;
293
294 /**
295  * This format describes the DFA pointers in large mode
296  */
297 typedef union
298 {
299     uint64_t u64;
300     struct
301     {
302         uint64_t                mbz         :27;/**< Must be zero */
303         uint64_t                x0          : 1;/**< XOR of the rest of the bits */
304         uint64_t                reserved    : 4;/**< Must be zero */
305         uint64_t                data        :32;/**< LLM Data */
306     } w32;
307     struct
308     {
309         uint64_t                mbz         :27;/**< Must be zero */
310         uint64_t                x0          : 1;/**< XOR of the rest of the bits */
311         uint64_t                data        :36;/**< LLM Data */
312     } w36;
313 #if defined(ENABLE_DEPRECATED) && !OCTEON_IS_COMMON_BINARY()
314 #if CVMX_COMPILED_FOR(OCTEON_CN31XX)
315     struct /**< @deprecated unnamed reference to members */
316     {
317         uint64_t                mbz         :27;/**< Must be zero */
318         uint64_t                x0          : 1;/**< XOR of the rest of the bits */
319         uint64_t                reserved    : 4;/**< Must be zero */
320         uint64_t                data        :32;/**< LLM Data */
321     };
322 #elif CVMX_COMPILED_FOR(OCTEON_CN38XX)
323     struct /**< @deprecated unnamed reference to members */
324     {
325         uint64_t                mbz         :27;/**< Must be zero */
326         uint64_t                x0          : 1;/**< XOR of the rest of the bits */
327         uint64_t                data        :36;/**< LLM Data */
328     };
329 #else
330     /* Other chips don't support the deprecated unnamed unions */
331 #endif
332 #endif
333 } cvmx_dfa_node_next_read_t;
334
335 /**
336  * This structure defines the data format in the low-latency memory
337  */
338 typedef union
339 {
340     uint64_t u64;
341     cvmx_dfa_node_next_sm_t     sm;     /**< This format describes the DFA pointers in small mode */
342     cvmx_dfa_node_next_lg_t     lg;     /**< This format describes the DFA pointers in large mode */
343     cvmx_dfa_node_next_lgb_t    lgb;    /**< This format describes the DFA pointers in large mode, another way */
344     cvmx_dfa_node_next_read_t   read;   /**< This format describes the DFA pointers in large mode */
345 #ifdef ENABLE_DEPRECATED
346     cvmx_dfa_node_next_sm_t     s18;    /**< Deprecated */
347     cvmx_dfa_node_next_lg_t     s36;    /**< Deprecated */
348     cvmx_dfa_node_next_lgb_t    s36b;   /**< Deprecated */
349 #endif
350 } cvmx_dfa_node_next_t;
351
352 /**
353  * These structures define a DFA instruction
354  */
355 typedef union
356 {
357     uint64_t u64[4];
358     uint32_t u32;
359     struct
360     {
361         // WORD 0
362         uint64_t gxor                   : 8;   /**< Graph XOR value (PASS3/CN58XX), Must be zero for other chips
363                                                      or if DFA_CFG[GXOR_ENA] == 0.  */
364         uint64_t nxoren                 : 1;   /**< Node XOR enable (PASS3/CN58XX), Must be zero for other chips
365                                                      or if DFA_CFG[NXOR_ENA] == 0.  */
366         uint64_t nreplen                : 1;   /**< Node Replication mode enable (PASS3/CN58XX), Must be zero for other chips
367                                                      or if DFA_CFG[NRPL_ENA] == 0 or IWORD0[Ty] == 0.  */
368 #if 0
369         uint64_t snrepl                 : 2;   /**< Start_Node Replication (PASS3/CN58XX), Must be zero for other chips
370                                                      or if DFA_CFG[NRPL_ENA] == 0 or IWORD0[Ty] == 0 or IWORD0[NREPLEN] == 0.  */
371         uint64_t start_node_id          : 20;   /**< Node to start the walk from */
372 #else
373         uint64_t start_node             : 22;   /**< Node to start the walk from, includes ID and snrepl, see notes above. */
374 #endif
375
376         uint64_t unused02               :  2;   /**< Must be zero */
377         cvmx_llm_replication_t replication : 2; /**< Type of memory replication to use */
378         uint64_t unused03               :  3;   /**< Must be zero */
379         cvmx_dfa_graph_type_t type      :  1;   /**< Type of graph */
380         uint64_t unused04               :  4;   /**< Must be zero */
381         uint64_t base                   : 20;   /**< All tables start on 1KB boundary */
382
383         // WORD 1
384         uint64_t input_length           : 16;   /**< In bytes, # pointers in gather case */
385         uint64_t use_gather             :  1;   /**< Set to use gather */
386         uint64_t no_L2_alloc            :  1;   /**< Set to disable loading of the L2 cache by the DFA */
387         uint64_t full_block_write       :  1;   /**< If set, HW can write entire cache blocks @ result_ptr */
388         uint64_t little_endian          :  1;   /**< Affects only packet data, not instruction, gather list, or result */
389         uint64_t unused1                :  8;   /**< Must be zero */
390         uint64_t data_ptr               : 36;   /**< Either directly points to data or the gather list. If gather list,
391                                                     data_ptr<2:0> must be zero (i.e. 8B aligned) */
392         // WORD 2
393         uint64_t max_results            : 16;   /**< in 64-bit quantities, mbz for store */
394         uint64_t unused2                : 12;   /**< Must be zero */
395         uint64_t result_ptr             : 36;   /**< must be 128 byte aligned */
396
397         // WORD 3
398         uint64_t tsize                  :  8;   /**< tsize*256 is the number of terminal nodes for GRAPH_TYPE_SM */
399         uint64_t msize                  : 16;   /**< msize is the number of marked nodes for GRAPH_TYPE_SM */
400         uint64_t unused3                :  4;   /**< Must be zero */
401         uint64_t wq_ptr                 : 36;   /**< 0 for no work queue entry creation */
402     } s;
403 } cvmx_dfa_command_t;
404
405 /**
406  * Format of the first result word written by the hardware.
407  */
408 typedef union
409 {
410     uint64_t u64;
411     struct
412     {
413         cvmx_dfa_stop_reason_t  reas        : 2;/**< Reason the DFA stopped */
414         uint64_t                mbz         :44;/**< Zero */
415         uint64_t                last_marked : 1;/**< Set if the last entry written is marked */
416         uint64_t                done        : 1;/**< Set to 1 when the DFA completes */
417         uint64_t                num_entries :16;/**< Number of result words written */
418     } s;
419 } cvmx_dfa_result0_t;
420
421 /**
422  * Format of the second result word and subsequent result words written by the hardware.
423  */
424 typedef union
425 {
426     uint64_t u64;
427     struct
428     {
429         uint64_t byte_offset    : 16;   /**< Number of bytes consumed */
430         uint64_t extra_bits_high:  4;   /**< If PASS3 or CN58XX and DFA_CFG[NRPL_ENA] == 1 and IWORD0[Ty] == 1,
431                                              then set to <27:24> of the last next-node pointer. Else set to 0x0.  */
432         uint64_t prev_node      : 20;   /**< Index of the previous node */
433         uint64_t extra_bits_low :  2;   /**< If PASS3 or CN58XX and DFA_CFG[NRPL_ENA] == 1 and IWORD0[Ty] == 1,
434                                              then set to <23:22> of the last next-node pointer. Else set to 0x0.  */
435         uint64_t next_node_repl :  2;   /**< If PASS3 or CN58XX and DFA_CFG[NRPL_ENA] == 1 and IWORD0[Ty] == 1, then set
436                                              to next_node_repl (<21:20>) of the last next-node pointer. Else set to 0x0.  */
437         uint64_t current_node   : 20;   /**< Index of the current node */
438     } s;
439     struct
440     {
441         uint64_t byte_offset    : 16;   /**< Number of bytes consumed */
442         uint64_t extra_bits_high:  4;   /**< If PASS3 or CN58XX and DFA_CFG[NRPL_ENA] == 1 and IWORD0[Ty] == 1,
443                                              then set to <27:24> of the last next-node pointer. Else set to 0x0.  */
444         uint64_t prev_node      : 20;   /**< Index of the previous node */
445         uint64_t extra_bits_low :  2;   /**< If PASS3 or CN58XX and DFA_CFG[NRPL_ENA] == 1 and IWORD0[Ty] == 1,
446                                              then set to <23:22> of the last next-node pointer. Else set to 0x0.  */
447         uint64_t curr_id_and_repl:22;   /**< Use ths as start_node for continuation. */
448     } s2;
449 } cvmx_dfa_result1_t;
450
451 /**
452  * Abstract DFA graph
453  */
454 typedef struct
455 {
456     cvmx_llm_replication_t      replication;        /**< Level of memory replication to use. Must match the LLM setup */
457     cvmx_dfa_graph_type_t       type;               /**< Type of graph */
458     uint64_t                    base_address;       /**< LLM start address of the graph */
459     union {
460         struct {
461             uint64_t            gxor         : 8;   /**< Graph XOR value (PASS3/CN58XX), Must be zero for other chips
462                                                           or if DFA_CFG[GXOR_ENA] == 0.  */
463             uint64_t            nxoren       : 1;   /**< Node XOR enable (PASS3/CN58XX), Must be zero for other chips
464                                                           or if DFA_CFG[NXOR_ENA] == 0.  */
465             uint64_t            nreplen      : 1;   /**< Node Replication mode enable (PASS3/CN58XX), Must be zero for other chips
466                                                           or if DFA_CFG[NRPL_ENA] == 0 or IWORD0[Ty] == 0.  */
467             uint64_t            snrepl       : 2;   /**< Start_Node Replication (PASS3/CN58XX), Must be zero for other chips
468                                                           or if DFA_CFG[NRPL_ENA] == 0 or IWORD0[Ty] == 0 or IWORD0[NREPLEN] == 0.*/
469             uint64_t            start_node_id : 20; /**< Start node index for the root of the graph */
470         };
471         uint32_t                start_node;         /**< Start node index for the root of the graph, incl. snrepl (PASS3/CN58XX)
472                                                            NOTE: for backwards compatibility this name includes the the
473                                                                  gxor, nxoren, nreplen, and snrepl fields which will all be
474                                                                  zero in applicaitons existing before the introduction of these
475                                                                  fields, so that existing applicaiton do not need to change. */
476     };
477     int                         num_terminal_nodes; /**< Number of terminal nodes in the graph. Only needed for small graphs. */
478     int                         num_marked_nodes;   /**< Number of marked nodes in the graph. Only needed for small graphs. */
479 } cvmx_dfa_graph_t;
480
481 /**
482  * DFA internal global state -- stored in 8 bytes of FAU
483  */
484 typedef union
485 {
486     uint64_t u64;
487     struct {
488 #define CVMX_DFA_STATE_TICKET_BIT_POS 16
489 #ifdef __BIG_ENDIAN_BITFIELD
490         // NOTE:  must clear LSB of base_address_div16 due to ticket overflow
491         uint32_t                base_address_div16;  /**< Current DFA instruction queue chunck base address/16 (clear LSB). */
492         uint8_t                 ticket_loops;        /**< bits [15:8] of total number of tickets requested. */
493         uint8_t                 ticket;              /**< bits [7:0] of total number of tickets requested (current ticket held). */
494         // NOTE: index and now_serving are written together
495         uint8_t                 now_serving;         /**< current ticket being served (or ready to be served). */
496         uint8_t                 index;               /**< index into current chunk: (base_address_div16*16)[index] = next entry. */
497 #else   // NOTE: little endian mode probably won't work
498         uint8_t                 index;
499         uint8_t                 now_serving;
500         uint8_t                 ticket;
501         uint8_t                 ticket_loops;
502         uint32_t                base_address_div16;
503 #endif
504     } s;
505     struct {    // a bitfield version of the same thing to extract base address while clearing carry.
506 #ifdef __BIG_ENDIAN_BITFIELD
507         uint64_t                base_address_div32      : 31;   /**< Current DFA instruction queue chunck base address/32. */
508         uint64_t                carry                   : 1;    /**< Carry out from total_tickets. */
509         uint64_t                total_tickets           : 16;   /**< Total tickets. */
510         uint64_t                now_serving             : 8 ;   /**< current ticket being served (or ready to be served). */
511         uint64_t                index                   : 8 ;   /**< index into current chunk. */
512 #else   // NOTE: little endian mode probably won't work
513         uint64_t                index                   : 8 ;
514         uint64_t                now_serving             : 8 ;
515         uint64_t                total_tickets           : 16;
516         uint64_t                carry                   : 1;
517         uint64_t                base_address_div32      : 31;
518 #endif
519     } s2;
520 } cvmx_dfa_state_t;
521
522 /* CSR typedefs have been moved to cvmx-dfa-defs.h */
523
524 /**
525  * Write a small node edge to LLM.
526  *
527  * @param graph  Graph to modify
528  * @param source_node
529  *               Source node for this edge
530  * @param match_index
531  *               Index into the node edge table. This is the match character/2.
532  * @param destination_node0
533  *               Destination if the character matches (match_index*2).
534  * @param destination_node1
535  *               Destination if the character matches (match_index*2+1).
536  */
537 static inline void cvmx_dfa_write_edge_sm(const cvmx_dfa_graph_t *graph,
538                                          uint64_t source_node, uint64_t match_index,
539                                          uint64_t destination_node0, uint64_t destination_node1)
540 {
541     cvmx_llm_address_t address;
542     cvmx_dfa_node_next_t    next_ptr;
543
544     address.u64 = graph->base_address + source_node * CVMX_DFA_NODESM_SIZE + match_index * 4;
545
546     next_ptr.u64 = 0;
547     if (OCTEON_IS_MODEL(OCTEON_CN31XX))
548     {
549         next_ptr.sm.w32.next_node0 = destination_node0;
550         next_ptr.sm.w32.p0 = cvmx_llm_parity(destination_node0);
551
552         next_ptr.sm.w32.next_node1 = destination_node1;
553         next_ptr.sm.w32.p1 = cvmx_llm_parity(destination_node1);
554     }
555     else
556     {
557         next_ptr.sm.w36.next_node0 = destination_node0;
558         next_ptr.sm.w36.p0 = cvmx_llm_parity(destination_node0);
559
560         next_ptr.sm.w36.next_node1 = destination_node1;
561         next_ptr.sm.w36.p1 = cvmx_llm_parity(destination_node1);
562     }
563
564     cvmx_llm_write36(address, next_ptr.u64, 0);
565 }
566 #ifdef ENABLE_DEPRECATED
567 #define cvmx_dfa_write_edge18 cvmx_dfa_write_edge_sm
568 #endif
569
570
571 /**
572  * Write a large node edge to LLM.
573  *
574  * @param graph  Graph to modify
575  * @param source_node
576  *               Source node for this edge
577  * @param match  Character to match before taking this edge.
578  * @param destination_node
579  *               Destination node of the edge.
580  * @param destination_type
581  *               Node type at the end of this edge.
582  */
583 static inline void cvmx_dfa_write_node_lg(const cvmx_dfa_graph_t *graph,
584                                          uint64_t source_node, unsigned char match,
585                                          uint64_t destination_node, cvmx_dfa_node_type_t destination_type)
586 {
587     cvmx_llm_address_t      address;
588     cvmx_dfa_node_next_t    next_ptr;
589
590     address.u64 = graph->base_address + source_node * CVMX_DFA_NODELG_SIZE + (uint64_t)match * 4;
591
592     next_ptr.u64 = 0;
593     if (OCTEON_IS_MODEL(OCTEON_CN31XX))
594     {
595         next_ptr.lg.w32.type = destination_type;
596         next_ptr.lg.w32.next_node = destination_node;
597         next_ptr.lg.w32.ecc = cvmx_llm_ecc(next_ptr.u64);
598     }
599     else
600     {
601         next_ptr.lg.w36.type = destination_type;
602         next_ptr.lg.w36.next_node = destination_node;
603         next_ptr.lg.w36.ecc = cvmx_llm_ecc(next_ptr.u64);
604     }
605
606     cvmx_llm_write36(address, next_ptr.u64, 0);
607 }
608 #ifdef ENABLE_DEPRECATED
609 #define cvmx_dfa_write_node36 cvmx_dfa_write_node_lg
610 #endif
611
612 /**
613  * Ring the DFA doorbell telling it that new commands are
614  * available.
615  *
616  * @param num_commands
617  *               Number of new commands
618  */
619 static inline void cvmx_dfa_write_doorbell(uint64_t num_commands)
620 {
621     CVMX_SYNCWS;
622     cvmx_write_csr(CVMX_DFA_DBELL, num_commands);
623 }
624
625 /**
626  * @INTERNAL
627  * Write a new command to the DFA. Calls to this function
628  * are internally synchronized across all processors, and
629  * the doorbell is rung during this function.
630  *
631  * @param command Command to write
632  */
633
634 #ifdef CVMX_ENABLE_DFA_FUNCTIONS
635 static inline void __cvmx_dfa_write_command(cvmx_dfa_command_t *command)
636 {
637     cvmx_dfa_state_t cvmx_dfa_state;
638     uint64_t my_ticket; // needs to wrap to 8 bits
639     uint64_t index;
640     cvmx_dfa_command_t *head;
641
642     CVMX_PREFETCH0(command);
643     // take a ticket.
644     cvmx_dfa_state.u64 = cvmx_fau_fetch_and_add64(CVMX_FAU_DFA_STATE, 1ull<<CVMX_DFA_STATE_TICKET_BIT_POS);
645     my_ticket = cvmx_dfa_state.s.ticket;
646
647     // see if it is our turn
648     while (my_ticket != cvmx_dfa_state.s.now_serving) {
649         int delta = my_ticket - cvmx_dfa_state.s.now_serving;
650         if (delta < 0) delta += 256;
651         cvmx_wait(10*delta);    // reduce polling load on system
652         cvmx_dfa_state.u64 = cvmx_fau_fetch_and_add64(CVMX_FAU_DFA_STATE, 0);           // poll for my_ticket==now_serving
653     }
654
655     // compute index and instruction queue head pointer
656     index = cvmx_dfa_state.s.index;
657
658     // NOTE: the DFA only supports 36-bit addressing
659     head = &((CASTPTR(cvmx_dfa_command_t, (cvmx_dfa_state.s2.base_address_div32 * 32ull))[index]));
660     head = (cvmx_dfa_command_t*)cvmx_phys_to_ptr(CAST64(head)); // NOTE: since we are not storing bit 63 of address, we must set it now
661
662     // copy the command to the instruction queue
663     *head++ = *command;
664
665     // check if a new chunk is needed
666     if (cvmx_unlikely((++index >= ((CVMX_FPA_DFA_POOL_SIZE-8)/sizeof(cvmx_dfa_command_t))))) {
667         uint64_t *new_base = (uint64_t*)cvmx_fpa_alloc(CVMX_FPA_DFA_POOL);      // could make this async
668         if (new_base) {
669             // put the link into the instruction queue's "Next Chunk Buffer Ptr"
670             *(uint64_t *)head = cvmx_ptr_to_phys(new_base);
671             // update our state (note 32-bit write to not disturb other fields)
672             cvmx_fau_atomic_write32((cvmx_fau_reg_32_t)(CVMX_FAU_DFA_STATE + (CAST64(&cvmx_dfa_state.s.base_address_div16)-CAST64(&cvmx_dfa_state))),
673                     (CAST64(new_base))/16);
674         }
675         else {
676             cvmx_dprintf("__cvmx_dfa_write_command: Out of memory. Expect crashes.\n");
677         }
678         index=0;
679     }
680
681     cvmx_dfa_write_doorbell(1);
682
683     // update index and now_serving in the DFA state FAU location (NOTE: this write16 updates to 8-bit values.)
684     // NOTE: my_ticket+1 carry out is lost due to write16 and index has already been wrapped to fit in uint8.
685     cvmx_fau_atomic_write16((cvmx_fau_reg_16_t)(CVMX_FAU_DFA_STATE+(CAST64(&cvmx_dfa_state.s.now_serving) - CAST64(&cvmx_dfa_state))),
686             ((my_ticket+1)<<8) | index);
687 }
688
689
690 /**
691  * Submit work to the DFA units for processing
692  *
693  * @param graph   Graph to process
694  * @param start_node
695  *                The node to start (or continue) walking from
696  *                includes. start_node_id and snrepl (PASS3/CN58XX), but gxor,
697  *                nxoren, and nreplen are taken from the graph structure
698  * @param input   The input to match against
699  * @param input_length
700  *                The length of the input in bytes
701  * @param use_gather
702  *                The input and input_length are of a gather list
703  * @param is_little_endian
704  *                Set to 1 if the input is in little endian format and must
705  *                be swapped before compare.
706  * @param result  Location the DFA should put the results in. This must be
707  *                an area sized in multiples of a cache line.
708  * @param max_results
709  *                The maximum number of 64-bit result1 words after result0.
710  *                That is, "size of the result area in 64-bit words" - 1.
711  *                max_results must be at least 1.
712  * @param work    Work queue entry to submit when DFA completes. Can be NULL.
713  */
714 static inline void cvmx_dfa_submit(const cvmx_dfa_graph_t *graph, int start_node,
715                                   void *input, int input_length, int use_gather, int is_little_endian,
716                                   cvmx_dfa_result0_t *result, int max_results, cvmx_wqe_t *work)
717 {
718     cvmx_dfa_command_t command;
719
720     /* Make sure the result's first 64bit word is zero so we can tell when the
721         DFA is done. */
722     result->u64 = 0;
723
724     // WORD 0
725     command.u64[0] = 0;
726     command.s.gxor          = graph->gxor;      // (PASS3/CN58XX)
727     command.s.nxoren        = graph->nxoren;    // (PASS3/CN58XX)
728     command.s.nreplen       = graph->nreplen;   // (PASS3/CN58XX)
729     command.s.start_node    = start_node;       // includes snrepl (PASS3/CN58XX)
730     command.s.replication   = graph->replication;
731     command.s.type          = graph->type;
732     command.s.base          = graph->base_address>>10;
733
734     // WORD 1
735     command.u64[1] = 0;
736     command.s.input_length  = input_length;
737     command.s.use_gather   = use_gather;
738     command.s.no_L2_alloc   = 0;
739     command.s.full_block_write = 1;
740     command.s.little_endian = is_little_endian;
741     command.s.data_ptr      = cvmx_ptr_to_phys(input);
742
743     // WORD 2
744     command.u64[2] = 0;
745     command.s.max_results   = max_results;
746     command.s.result_ptr    = cvmx_ptr_to_phys(result);
747
748     // WORD 3
749     command.u64[3] = 0;
750     if (graph->type == CVMX_DFA_GRAPH_TYPE_SM)
751     {
752         command.s.tsize     = (graph->num_terminal_nodes + 255) / 256;
753         command.s.msize     = graph->num_marked_nodes;
754     }
755     command.s.wq_ptr        = cvmx_ptr_to_phys(work);
756
757     __cvmx_dfa_write_command(&command); // NOTE: this does synchronization and rings doorbell
758 }
759 #endif
760
761 /**
762  * DFA gather list element
763  */
764 typedef struct {
765     uint64_t length         : 16;   /**< length of piece of data at addr */
766     uint64_t reserved       : 12;   /**< reserved, set to 0 */
767     uint64_t addr           : 36;   /**< pointer to piece of data */
768 } cvmx_dfa_gather_entry_t;
769
770
771 /**
772  * Check if a DFA has completed processing
773  *
774  * @param result_ptr Result area the DFA is using
775  * @return Non zero if the DFA is done
776  */
777 static inline uint64_t cvmx_dfa_is_done(cvmx_dfa_result0_t *result_ptr)
778 {
779     /* DFA sets the first result 64bit word to non zero when it's done */
780     return ((volatile cvmx_dfa_result0_t *)result_ptr)->s.done;
781 }
782
783
784 #ifdef CVMX_ENABLE_DFA_FUNCTIONS
785 /**
786  * Initialize the DFA hardware before use
787  * Returns 0 on success, -1 on failure
788  */
789 int cvmx_dfa_initialize(void);
790
791
792 /**
793  * Shutdown and cleanup resources used by the DFA
794  */
795 void cvmx_dfa_shutdown(void);
796 #endif
797
798 #ifdef  __cplusplus
799 }
800 #endif
801
802 #endif /* __CVMX_DFA_H__ */