blob: 8f4a6eafd1115b1a0d4f4305827e64feba4c7ccc [file] [log] [blame]
/*
* Copyright (C) 2010 Samsung Electronics.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* 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.
*
*/
#ifndef __SIPC5_H__
#define __SIPC5_H__
#include <linux/types.h>
#include "../modem_v1.h"
/* SIPC5 link-layer header */
struct __packed sipc5_link_header {
u8 cfg;
u8 ch;
u16 len;
union {
struct multi_frame_control ctrl;
u16 ext_len;
};
};
#define SIPC5_START_MASK (0b11111000)
#define SIPC5_CONFIG_MASK (0b00000111)
#define SIPC5_EXT_FIELD_MASK (0b00000011)
#define SIPC5_PADDING_EXIST (0b00000100)
#define SIPC5_EXT_FIELD_EXIST (0b00000010)
#define SIPC5_CTL_FIELD_EXIST (0b00000001)
#define SIPC5_MULTI_FRAME_CFG (0b00000011)
#define SIPC5_EXT_LENGTH_CFG (0b00000010)
#define SIPC5_CONFIG_OFFSET 0
#define SIPC5_CONFIG_SIZE 1
#define SIPC5_CH_ID_OFFSET 1
#define SIPC5_CH_ID_SIZE 1
#define SIPC5_LEN_OFFSET 2
#define SIPC5_LEN_SIZE 2
#define SIPC5_CTRL_OFFSET 4
#define SIPC5_CTRL_SIZE 1
#define SIPC5_EXT_LEN_OFFSET 4
#define SIPC5_EXT_LEN_SIZE 2
#define SIPC5_MIN_HEADER_SIZE 4
#define SIPC5_HEADER_SIZE_WITH_CTL_FLD 5
#define SIPC5_HEADER_SIZE_WITH_EXT_LEN 6
#define SIPC5_MAX_HEADER_SIZE SIPC5_HEADER_SIZE_WITH_EXT_LEN
static inline bool sipc5_start_valid(u8 *frm)
{
return (*frm & SIPC5_START_MASK) == SIPC5_START_MASK;
}
static inline bool sipc5_padding_exist(u8 *frm)
{
return (*frm & SIPC5_PADDING_EXIST) ? true : false;
}
static inline bool sipc5_multi_frame(u8 *frm)
{
return (*frm & SIPC5_EXT_FIELD_MASK) == SIPC5_MULTI_FRAME_CFG;
}
static inline bool sipc5_ext_len(u8 *frm)
{
return (*frm & SIPC5_EXT_FIELD_MASK) == SIPC5_EXT_LENGTH_CFG;
}
static inline u8 sipc5_get_ch(u8 *frm)
{
return frm[SIPC5_CH_ID_OFFSET];
}
static inline u8 sipc5_get_ctrl(u8 *frm)
{
return frm[SIPC5_CTRL_OFFSET];
}
static inline unsigned int sipc5_calc_padding_size(unsigned int len)
{
unsigned int residue = len & (BITS_PER_LONG / 8 - 1);
return residue ? (BITS_PER_LONG / 8 - residue) : 0;
}
/**
@brief get the length of the header of an SIPC5 link frame
@param frm the pointer to an SIPC5 link frame
@return the size of the header of an SIPC5 link frame
*/
static inline unsigned int sipc5_get_hdr_len(u8 *frm)
{
if (unlikely(frm[0] & SIPC5_EXT_FIELD_EXIST)) {
if (sipc5_multi_frame(frm))
return SIPC5_HEADER_SIZE_WITH_CTL_FLD;
else
return SIPC5_HEADER_SIZE_WITH_EXT_LEN;
} else {
return SIPC5_MIN_HEADER_SIZE;
}
}
/**
@brief get the real length of an SIPC5 link frame WITHOUT padding
@param frm the pointer to an SIPC5 link frame
@return the real length of an SIPC5 link frame WITHOUT padding
*/
static inline unsigned int sipc5_get_frame_len(u8 *frm)
{
u16 *sz16 = (u16 *)(frm + SIPC5_LEN_OFFSET);
u32 *sz32 = (u32 *)(frm + SIPC5_LEN_OFFSET);
if (unlikely(frm[0] & SIPC5_EXT_FIELD_EXIST)) {
if (sipc5_multi_frame(frm))
return *sz16;
else
return *sz32;
} else {
return *sz16;
}
}
/**
@brief get the total length of an SIPC5 link frame with padding
@param frm the pointer to an SIPC5 link frame
@return the total length of an SIPC5 link frame with padding
*/
static inline unsigned int sipc5_get_total_len(u8 *frm)
{
unsigned int len;
unsigned int pad;
len = sipc5_get_frame_len(frm);
pad = sipc5_padding_exist(frm) ? sipc5_calc_padding_size(len) : 0;
return len + pad;
}
/**
@param ch the channel ID
@return true if the channel ID is for FMT channel
*/
static inline bool sipc5_fmt_ch(u8 ch)
{
return (ch >= SIPC5_CH_ID_FMT_0 && ch <= SIPC5_CH_ID_FMT_9) ?
true : false;
}
/**
@param ch the channel ID
@return true if the channel ID is for RFS channel
*/
static inline bool sipc5_rfs_ch(u8 ch)
{
return (ch >= SIPC5_CH_ID_RFS_0 && ch <= SIPC5_CH_ID_RFS_9) ?
true : false;
}
/**
@param ch the channel ID
@return true if the channel ID is for BOOT channel
*/
static inline bool sipc5_boot_ch(u8 ch)
{
return (ch >= SIPC5_CH_ID_BOOT_0 && ch <= SIPC5_CH_ID_BOOT_9) ?
true : false;
}
/**
@param ch the channel ID
@return true if the channel ID is for DUMP channel
*/
static inline bool sipc5_dump_ch(u8 ch)
{
return (ch >= SIPC5_CH_ID_DUMP_0 && ch <= SIPC5_CH_ID_DUMP_9) ?
true : false;
}
/**
@param ch the channel ID
@return true if the channel ID is for BOOT/DUMP channel
*/
static inline bool sipc5_udl_ch(u8 ch)
{
return (ch >= SIPC5_CH_ID_BOOT_0 && ch <= SIPC5_CH_ID_DUMP_9) ?
true : false;
}
/**
@param ch the channel ID
@return true if the channel ID is for IPC channel
*/
static inline bool sipc5_ipc_ch(u8 ch)
{
return (ch > 0 && (ch < SIPC5_CH_ID_BOOT_0 || ch > SIPC5_CH_ID_DUMP_9))
? true : false;
}
/**
@param ch the channel ID
@return true if the channel ID is for MISC channel want to logging
*/
static inline bool sipc5_misc_ch(u8 ch)
{
return (ch == SIPC_CH_ID_CASS)
? true : false;
}
/**
@param ch the channel ID
@return true if the channel ID is for LOG channel want to logging
*/
static inline bool sipc5_log_ch(u8 ch)
{
return (ch >= SIPC_CH_ID_CPLOG1 && ch <= SIPC_CH_ID_CPLOG2)
? true : false;
}
struct sipc5_frame_data {
/* Frame length calculated from the length fields */
unsigned int len;
/* The length of link layer header */
unsigned int hdr_len;
/* The length of received header */
unsigned int hdr_rcvd;
/* The length of link layer payload */
unsigned int pay_len;
/* The length of received data */
unsigned int pay_rcvd;
/* The length of link layer padding */
unsigned int pad_len;
/* The length of received padding */
unsigned int pad_rcvd;
/* Header buffer */
u8 hdr[SIPC5_MAX_HEADER_SIZE];
};
#if 1
#endif
#define STD_UDL_STEP_MASK 0x0000000F
#define STD_UDL_SEND 0x1
#define STD_UDL_CRC 0xC
struct std_dload_info {
u32 size;
u32 mtu;
u32 num_frames;
} __packed;
/**
@brief get BOOT/DUMP command
@param frm the pointer to an SIPC5 link frame
@return the standard BOOT/DUMP command in an SIPC5 BOOT/DUMP frame
*/
static inline u32 std_udl_get_cmd(u8 *frm)
{
u8 *cmd = frm + sipc5_get_hdr_len(frm);
return *((u32 *)cmd);
}
/**
@brief check whether or not a command came with a payload
@param cmd the standard BOOT/DUMP command
@retval "true" if the STD_UDL command has a payload
@retval "false" otherwise
*/
static inline bool std_udl_with_payload(u32 cmd)
{
u32 mask = cmd & STD_UDL_STEP_MASK;
return (mask && mask < STD_UDL_CRC) ? true : false;
}
#endif