diff options
-rw-r--r-- | src/target/firmware/include/layer1/sched_gsmtime.h | 22 | ||||
-rw-r--r-- | src/target/firmware/layer1/Makefile | 3 | ||||
-rw-r--r-- | src/target/firmware/layer1/sched_gsmtime.c | 106 |
3 files changed, 130 insertions, 1 deletions
diff --git a/src/target/firmware/include/layer1/sched_gsmtime.h b/src/target/firmware/include/layer1/sched_gsmtime.h new file mode 100644 index 00000000..d241fe05 --- /dev/null +++ b/src/target/firmware/include/layer1/sched_gsmtime.h @@ -0,0 +1,22 @@ +#ifndef _L1_SCHED_GSMTIME_H +#define _L1_SCHED_GSMTIME_H + +#include <stdint.h> +#include <linuxlist.h> + +struct sched_gsmtime_event { + struct llist_head list; + struct tdma_sched_item *si; + uint32_t fn; +}; + +/* initialize the GSMTIME scheduler */ +void sched_gsmtime_init(void); + +/* Scheduling of a single event at a givnen GSM time */ +int sched_gsmtime(struct tdma_sched_item *si, uint32_t fn); + +/* execute all GSMTIME one-shot events pending for 'current_fn' */ +int sched_gsmtime_execute(uint32_t current_fn); + +#endif diff --git a/src/target/firmware/layer1/Makefile b/src/target/firmware/layer1/Makefile index dadf7e32..d04573ed 100644 --- a/src/target/firmware/layer1/Makefile +++ b/src/target/firmware/layer1/Makefile @@ -2,7 +2,8 @@ INCLUDES=-I../include/ -I../../../../include -include ../Makefile.inc LIBNAME=layer1 -OBJS=avg.o agc.o afc.o sync.o gsm.o tdma_sched.o tpu_window.o init.o l23_api.o mframe_sched.o +OBJS=avg.o agc.o afc.o sync.o gsm.o tdma_sched.o tpu_window.o init.o l23_api.o \ + mframe_sched.o sched_gsmtime.o LST=$(OBJS:.o=.lst) diff --git a/src/target/firmware/layer1/sched_gsmtime.c b/src/target/firmware/layer1/sched_gsmtime.c new file mode 100644 index 00000000..86b51039 --- /dev/null +++ b/src/target/firmware/layer1/sched_gsmtime.c @@ -0,0 +1,106 @@ +/* GSM-Time One-shot Event Scheduler Implementation (on top of TDMA sched) */ + +/* (C) 2010 by Harald Welte <laforge@gnumonks.org> + * + * All Rights Reserved + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include <stdint.h> +#include <errno.h> + +#include <debug.h> +#include <linuxlist.h> + +#include <layer1/tdma_sched.h> +#include <layer1/sched_gsmtime.h> + +static struct sched_gsmtime_event sched_gsmtime_events[16]; +static LLIST_HEAD(active_evts); +static LLIST_HEAD(inactive_evts); + +/* Scheduling of a tdma_sched_item list one-shot at a givnen GSM time */ +int sched_gsmtime(struct tdma_sched_item *si, uint32_t fn) +{ + struct llist_head *lh; + struct sched_gsmtime_event *evt, *cur; + + printd("sched_gsmtime(si=%p, fn=%u)\n", si, fn); + + /* obtain a free/inactive event structure */ + if (llist_empty(&inactive_evts)) + return -EBUSY; + lh = inactive_evts.next; + llist_del(lh); + evt = llist_entry(lh, struct sched_gsmtime_event, list); + + evt->fn = fn; + evt->si = si; + + /* do a sorted insert into the list, i.e. insert the new + * event _before_ the first entry that has a higher fn */ + llist_for_each_entry(cur, &active_evts, list) { + if (cur->fn > evt->fn) { + llist_add_tail(lh, &cur->list); + return 0; + } + } + + /* if we reach here, active_evts is empty _OR_ new event + * is after all the other events: append at end of list */ + llist_add_tail(lh, &active_evts); + + return 0; +} + +/* how many TDMA frame ticks should we schedule events ahead? */ +#define SCHEDULE_AHEAD 2 + +/* how long do we need to tell the DSP in advance what we want to do? */ +#define SCHEDULE_LATENCY 1 + +/* execute all GSMTIME one-shot events pending for 'fn' */ +int sched_gsmtime_execute(uint32_t fn) +{ + struct sched_gsmtime_event *evt, *evt2; + int num = 0; + + llist_for_each_entry_safe(evt, evt2, &active_evts, list) { + if (evt->fn == fn + SCHEDULE_AHEAD) { + printd("sched_gsmtime_execute(time=%u): fn=%u si=%p\n", fn, evt->fn, evt->si); + tdma_schedule_set(SCHEDULE_AHEAD-SCHEDULE_LATENCY, evt->si); + llist_del(&evt->list); + /* put event back in list of inactive (free) events */ + llist_add(&evt->list, &inactive_evts); + num++; + } if (evt->fn > fn + SCHEDULE_AHEAD) { + /* break the loop as our list is ordered */ + break; + } + } + return num; +} + +void sched_gsmtime_init(void) +{ + unsigned int i; + + printd("sched_gsmtime_init()\n"); + + for (i = 0; i < ARRAY_SIZE(sched_gsmtime_events); i++) + llist_add(&sched_gsmtime_events[i].list, &inactive_evts); +} |