/* * 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 #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