blob: 8803232653f3292997f6e2b6464eb9cf4bc7d121 [file] [log] [blame]
/*
* Copyright (c) 2011 Mindspeed Technologies, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*
*/
#ifndef _UTIL_MTD_H_
#define _UTIL_MTD_H_
#include "types.h"
#include "hal.h"
#define NUM_MTDS 64
#define NUM_FRAG_MTDS (NUM_FRAG4_Q*2*2)
typedef struct tMetadata {
struct tMetadata *next;
u16 length;
u16 offset; /**< data offset, both in DDR (relative to mtd->rx_next) and DMEM (relative to mtd->data) */
u8 *data; /**< Points to packet data in DMEM */
void *rx_next; /** Points to packet data in DDR, _not_ 2K aligned */
void *rx_dmem_end; /** Points to end of packet data in DMEM */
u16 flags;
u8 input_port;
u8 base_offset; /**< DMEM base offset where packet is fetched to */
union {
// FIXME -- is this right???? problem with c2k???
struct { U32 pad_double; U64 dword;} __attribute__((packed));
U32 word[MTD_PRIV];
struct socket_info {
U16 id;
U32 l4cksum;
U32 l4offset;
} socket;
struct frag_info {
U16 offset;
U16 l4offset; /* Set by class */
U16 end;
U16 l3offset; /* Set by class */
} frag;
struct sec_path {
U8 l2_len[SA_MAX_OP];
U8 output_port;
U8 queue;
U8 sec_outitf;
U8 sec_L4off;
U8 sec_L4_proto;
S8 sec_sa_op;
U16 sec_sa_h[SA_MAX_OP];
} sec;
struct rtpqos_info {
U32 client;
BOOL udp_check;
} rtpqos;
} priv;
//SAEntry dmem_sa;
} Metadata, *PMetadata;
#define priv_sa_outitf priv.sec.sec_outitf
#define priv_l2len priv.sec.l2_len
#define priv_queue priv.sec.queue
#define priv_outport priv.sec.output_port
#define priv_sa_op priv.sec.sec_sa_op
#define priv_sa_handle priv.sec.sec_sa_h
#define priv_L4_offset priv.sec.sec_L4off
#define priv_L4_proto priv.sec.sec_L4_proto
extern Metadata util_mtd_rtp;
extern Metadata g_util_mtd_table[];
extern Metadata g_util_frag_mtd_table[];
extern PMetadata gmtd_head;
extern PMetadata g_frag_mtd_head;
/* Returns the DDR buffer offset corresponding to the DMEM address */
#define ddr_offset(mtd, dmem_addr) ((void *)(dmem_addr) - (void*)((mtd)->data + BaseOffset(mtd)))
/* Returns the DDR buffer address corresponding to the DMEM address */
#define ddr_addr(mtd, dmem_addr) ((mtd)->rx_next + ddr_offset(mtd, dmem_addr))
static __inline void mtd_init()
{
int i;
gmtd_head = NULL;
for (i = 0; i < NUM_MTDS; i++)
{
g_util_mtd_table[i].next = gmtd_head;
gmtd_head = &g_util_mtd_table[i];
}
/*TODO Is it a good idea to move to FPART model?? */
g_frag_mtd_head = NULL;
for(i = 0; i < NUM_FRAG_MTDS; i++)
{
g_util_frag_mtd_table[i].next = g_frag_mtd_head;
g_frag_mtd_head = &g_util_frag_mtd_table[i];
}
}
static __inline PMetadata mtd_alloc()
{
PMetadata mtd = NULL;
if (gmtd_head)
{
mtd = gmtd_head;
gmtd_head = gmtd_head->next;
//mtd->next =NULL;
}
return (mtd);
}
static __inline PMetadata frag_mtd_alloc()
{
PMetadata mtd = NULL;
if (g_frag_mtd_head)
{
mtd = g_frag_mtd_head;
g_frag_mtd_head = g_frag_mtd_head->next;
//mtd->next =NULL;
}
return (mtd);
}
static __inline void frag_mtd_free(PMetadata pMetaData)
{
pMetaData->next = g_frag_mtd_head;
g_frag_mtd_head = pMetaData;
}
static __inline void mtd_free(PMetadata pMetaData)
{
if (pMetaData == &util_mtd_rtp)
return;
if(pMetaData >= g_util_frag_mtd_table) {
frag_mtd_free(pMetaData);
}else {
pMetaData->next = gmtd_head;
gmtd_head = pMetaData;
}
return;
}
#endif /* UTIL_MTD_H_ */