110 lines
2.7 KiB
C
110 lines
2.7 KiB
C
|
|
/* helper routines to determine the logical channel type based on
|
|
* physical channel configuration and frame number */
|
|
|
|
#include "gsmstack.h"
|
|
#include "get_lctype.h"
|
|
|
|
#define GSM_FN_51 (fn / 51)
|
|
|
|
#define GSM_TC(fn) ((fn / 51) % 8)
|
|
|
|
|
|
/* parameters determined from CCCH_CONF (octet 2 of control channel description
|
|
* in System Information Type 3:
|
|
* BS_CC_CHANS defines if we have CCCH on ts 2/4/6
|
|
* BS_CCCH_SDCCH_COMB defines if we have SDCCH/8 SACCH/C8 on TS0
|
|
* BS_AG_BLKS_RES defines which CCCH blocks are reserved for AGCH
|
|
* if BCCH Ext. is used, BS_AS_BLKS_RES has to be non-zero
|
|
*/
|
|
|
|
static int get_lctype_for_ccch(unsigned int fnr)
|
|
{
|
|
unsigned int fnr51 = GSM_FN_51(fnr);
|
|
int lc_type;
|
|
|
|
if (fnr51 % 10 == 0)
|
|
lc_type = GSM_LCHAN_FCCH;
|
|
else if (fnr51 % 10 == 1)
|
|
lc_type = GSM_LCHAN_SCH;
|
|
else if (fnr51 >= 2 && fnr_mod_51 <= 5)
|
|
lc_type = GSM_LCHAN_BCCH;
|
|
else if (fnr51 >= 6 && fnr51 <= 9) {
|
|
if (flags & CCCH_F_BCCH_EXT)
|
|
lc_type = GSM_LCHAN_BCCH;
|
|
else
|
|
lc_ctype = GSM_LCHAN_PCH;
|
|
} else
|
|
lc_ctype = GSM_LCHAN_PCH;
|
|
|
|
/* FIXME: what about AGCH ? */
|
|
/* FIXME: what about NCH ? */
|
|
/* FIXME: what about CBCH ? */
|
|
|
|
return lc_ctype;
|
|
}
|
|
|
|
static int get_lctype_for_sdcch8(unsigned int fnr)
|
|
{
|
|
unsigned int fnr51 = GSM_FN_51(fnr);
|
|
unsigned int fnr102 = fnr % 102;
|
|
int lc_type;
|
|
|
|
/* the lower 32 bursts are evenly divided between SDCCH8 0..7 */
|
|
if (fnr51 % < 32) {
|
|
lc_type = GSM_LCHAN_SDCCH8;
|
|
subc = fnr51 / 4;
|
|
} else {
|
|
/* the upper 16 bursts are bundles of four bursts for
|
|
* alternating either SACCH0..3 or SACCH4..7 */
|
|
lc_type = GSM_LCHAN_SACCH8C;
|
|
subc = (fnr51 - 32) / 4;
|
|
if (fnr102 > 50)
|
|
subc += 4;
|
|
}
|
|
|
|
return lc_type;
|
|
}
|
|
|
|
static int get_lctype_for_tch_f(unsigned int fnr)
|
|
{
|
|
unsigned int fnr52 = fnr % 52;
|
|
int lc_type = GSM_LCHAN_TCH;
|
|
|
|
/* only burst number 12 and 51 are be SACCH */
|
|
if (fnr52 == 12 || fnr52 == 51)
|
|
lc_ctype = GSM_LCHAN_SACCH;
|
|
/* burst number 26 and 39 are empty (for measurements) */
|
|
else if (fnr52 == 26 || fnr52 == 39)
|
|
lc_ctype = GSM_LCHAN_NONE;
|
|
|
|
return lc_type;
|
|
}
|
|
|
|
/* get the logical channel type based on frame number and
|
|
* physical channel configuration */
|
|
int get_lctype(struct gsm_phys_chan *pchan, int fnr)
|
|
{
|
|
switch (pchan->config) {
|
|
case GSM_PCHAN_CCCH:
|
|
return get_lctype_for_ccch(fnr);
|
|
break;
|
|
case GSM_PCHAN_TCH_F:
|
|
return get_lctype_for_tch_f(fnr);
|
|
break;
|
|
case GSM_PCHAN_SDCCH8_SACCH8C:
|
|
return get_lctype_for_sdcch8(fnr);
|
|
break;
|
|
}
|
|
|
|
return -EINVAL;
|
|
}
|
|
|
|
/* get a pointer to the logical channel structure based on frame number
|
|
* and physical channel configuration */
|
|
struct gsm_logi_chan *get_lchan(struct gsm_phys_chan *pchan, int fnr)
|
|
{
|
|
int lctype = get_lctype(pchan, fnr);
|
|
return &pchan->logi_chan[lctype];
|
|
}
|