blob: ca8690899e475fe0cb9b9d30136cdf16aca26ee3 [file] [log] [blame]
Harald Welte8470bf22008-12-25 23:28:35 +00001/* GSM Channel allocation routines
2 *
3 * (C) 2008 by Harald Welte <laforge@gnumonks.org>
4 *
5 * All Rights Reserved
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 */
22
23#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <errno.h>
27
28#include <openbsc/gsm_data.h>
29#include <openbsc/chan_alloc.h>
30
31struct gsm_bts_trx_ts *ts_c0_alloc(struct gsm_bts *bts,
32 enum gsm_phys_chan_config pchan)
33{
34 struct gsm_bts_trx *trx = &bts->trx[0];
35 struct gsm_bts_trx_ts *ts = &trx->ts[0];
36
37 if (pchan != GSM_PCHAN_CCCH &&
38 pchan != GSM_PCHAN_CCCH_SDCCH4)
39 return NULL;
40
41 if (ts->pchan != GSM_PCHAN_NONE)
42 return NULL;
43
44 ts->pchan = pchan;
45
46 return ts;
47}
48
49
50/* Allocate a logical channel (TS) */
51struct gsm_bts_trx_ts *ts_alloc(struct gsm_bts *bts,
52 enum gsm_phys_chan_config pchan)
53{
54 int i, j;
55 for (i = 0; i < bts->num_trx; i++) {
56 struct gsm_bts_trx *trx = &bts->trx[i];
57 for (j = 0; j < 8; j++) {
58 struct gsm_bts_trx_ts *ts = &trx->ts[j];
59 if (ts->pchan == GSM_PCHAN_NONE) {
60 ts->pchan = pchan;
61 return ts;
62 }
63 }
64 }
65 return NULL;
66}
67
68/* Free a physical channel (TS) */
69void ts_free(struct gsm_bts_trx_ts *ts)
70{
71 ts->pchan = GSM_PCHAN_NONE;
72}
73
74static const u_int8_t subslots_per_pchan[] = {
75 [GSM_PCHAN_NONE] = 0,
76 [GSM_PCHAN_CCCH] = 0,
77 [GSM_PCHAN_CCCH_SDCCH4] = 4,
78 [GSM_PCHAN_TCH_F] = 1,
79 [GSM_PCHAN_TCH_H] = 2,
80 [GSM_PCHAN_SDCCH8_SACCH8C] = 8.
81};
82
83static struct gsm_lchan *
84_lc_find(struct gsm_bts *bts, enum gsm_phys_chan_config pchan)
85{
86 struct gsm_bts_trx *trx;
87 struct gsm_bts_trx_ts *ts;
88 int i, j, ss;
89 for (i = 0; i < bts->num_trx; i++) {
90 trx = &bts->trx[i];
91 for (j = 0; j < 8; j++) {
92 ts = &trx->ts[j];
93 if (ts->pchan != pchan)
94 continue;
95 /* check if all sub-slots are allocated yet */
96 for (ss = 0; ss < subslots_per_pchan[pchan]; ss++) {
97 struct gsm_lchan *lc = &ts->lchan[ss];
98 if (lc->type == GSM_LCHAN_NONE)
99 return lc;
100 }
101 }
102 }
103 /* we cannot allocate more of these */
104 if (pchan == GSM_PCHAN_CCCH_SDCCH4)
105 return NULL;
106
107 /* if we've reached here, we need to allocate a new physical
108 * channel for the logical channel type requested */
109 ts = ts_alloc(bts, pchan);
110 if (!ts) {
111 /* no more radio resources */
112 return NULL;
113 }
114 return &ts->lchan[0];
115}
116
117/* Allocate a logical channel */
118struct gsm_lchan *lchan_alloc(struct gsm_bts *bts, enum gsm_chan_t type)
119{
120 struct gsm_lchan *lchan = NULL;
121
122 switch (type) {
123 case GSM_LCHAN_SDCCH:
124 lchan = _lc_find(bts, GSM_PCHAN_CCCH_SDCCH4);
125 if (lchan == NULL)
126 lchan = _lc_find(bts, GSM_PCHAN_SDCCH8_SACCH8C);
127 break;
128 case GSM_LCHAN_TCH_F:
129 lchan = _lc_find(bts, GSM_PCHAN_TCH_F);
130 break;
131 case GSM_LCHAN_TCH_H:
132 lchan =_lc_find(bts, GSM_PCHAN_TCH_H);
133 break;
134 default:
135 fprintf(stderr, "Unknown gsm_chan_t %u\n", type);
136 }
137
138 if (lchan)
139 lchan->type = type;
140
141 return lchan;
142}
143
144/* Free a logical channel */
145void lchan_free(struct gsm_lchan *lchan)
146{
147 lchan->type = GSM_LCHAN_NONE;
148 /* FIXME: ts_free() the timeslot, if we're the last logical
149 * channel using it */
150}