| /* sba.cpp |
| * |
| * Copyright (C) 2012 Ivan Klyuchnikov |
| * Copyright (C) 2012 Andreas Eversberg <jolly@eversberg.eu> |
| * Copyright (C) 2013 by Holger Hans Peter Freyther |
| * |
| * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
| */ |
| |
| #include <sba.h> |
| #include <gprs_debug.h> |
| #include <bts.h> |
| #include <pcu_utils.h> |
| #include <pdch.h> |
| |
| extern "C" { |
| #include <osmocom/core/logging.h> |
| #include <osmocom/core/talloc.h> |
| #include <osmocom/gsm/protocol/gsm_04_08.h> |
| #include <osmocom/gsm/gsm_utils.h> |
| } |
| |
| #include <errno.h> |
| |
| extern void *tall_pcu_ctx; |
| |
| /* starting time for assigning single slot |
| * This offset must be a multiple of 13. */ |
| #define AGCH_START_OFFSET 52 |
| |
| SBAController::SBAController(BTS &bts) |
| : m_bts(bts) |
| { |
| INIT_LLIST_HEAD(&m_sbas); |
| } |
| |
| int SBAController::alloc( |
| uint8_t *_trx, uint8_t *_ts, uint32_t *_fn, uint8_t ta) |
| { |
| |
| struct gprs_rlcmac_pdch *pdch; |
| struct gprs_rlcmac_sba *sba; |
| int8_t trx, ts; |
| uint32_t fn; |
| |
| if (!gsm48_ta_is_valid(ta)) |
| return -EINVAL; |
| |
| sba = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_sba); |
| if (!sba) |
| return -ENOMEM; |
| |
| for (trx = 0; trx < 8; trx++) { |
| for (ts = 7; ts >= 0; ts--) { |
| pdch = &m_bts.bts_data()->trx[trx].pdch[ts]; |
| if (!pdch->is_enabled()) |
| continue; |
| break; |
| } |
| if (ts >= 0) |
| break; |
| } |
| if (trx == 8) { |
| LOGP(DRLCMAC, LOGL_NOTICE, "No PDCH available.\n"); |
| talloc_free(sba); |
| return -EINVAL; |
| } |
| |
| fn = next_fn(pdch->last_rts_fn, AGCH_START_OFFSET); |
| |
| sba->trx_no = trx; |
| sba->ts_no = ts; |
| sba->fn = fn; |
| sba->ta = ta; |
| |
| llist_add(&sba->list, &m_sbas); |
| m_bts.sba_allocated(); |
| |
| *_trx = trx; |
| *_ts = ts; |
| *_fn = fn; |
| return 0; |
| } |
| |
| gprs_rlcmac_sba *SBAController::find(uint8_t trx, uint8_t ts, uint32_t fn) |
| { |
| struct gprs_rlcmac_sba *sba; |
| |
| llist_for_each_entry(sba, &m_sbas, list) { |
| if (sba->trx_no == trx && sba->ts_no == ts && sba->fn == fn) |
| return sba; |
| } |
| |
| return NULL; |
| } |
| |
| gprs_rlcmac_sba *SBAController::find(const gprs_rlcmac_pdch *pdch, uint32_t fn) |
| { |
| return find(pdch->trx_no(), pdch->ts_no, fn); |
| } |
| |
| uint32_t SBAController::sched(uint8_t trx, uint8_t ts, uint32_t fn, uint8_t block_nr) |
| { |
| uint32_t sba_fn = fn + 4; |
| struct gprs_rlcmac_sba *sba; |
| |
| /* check special TBF for events */ |
| if ((block_nr % 3) == 2) |
| sba_fn++; |
| sba_fn = sba_fn % GSM_MAX_FN; |
| sba = find(trx, ts, sba_fn); |
| if (sba) |
| return sba_fn; |
| |
| return 0xffffffff; |
| } |
| |
| int SBAController::timeout(struct gprs_rlcmac_sba *sba) |
| { |
| LOGP(DRLCMAC, LOGL_NOTICE, |
| "Poll timeout for SBA (TRX=%u, TS=%u, FN=%u, TA=%u)\n", sba->trx_no, |
| sba->ts_no, sba->fn, sba->ta); |
| m_bts.sba_timedout(); |
| free_sba(sba); |
| return 0; |
| } |
| |
| void SBAController::free_sba(gprs_rlcmac_sba *sba) |
| { |
| m_bts.sba_freed(); |
| llist_del(&sba->list); |
| talloc_free(sba); |
| } |
| |
| void SBAController::free_resources(struct gprs_rlcmac_pdch *pdch) |
| { |
| struct gprs_rlcmac_sba *sba, *sba2; |
| const uint8_t trx_no = pdch->trx->trx_no; |
| const uint8_t ts_no = pdch->ts_no; |
| |
| llist_for_each_entry_safe(sba, sba2, &m_sbas, list) { |
| if (sba->trx_no == trx_no && sba->ts_no == ts_no) |
| free_sba(sba); |
| } |
| } |