summaryrefslogtreecommitdiff
path: root/mac/ca/src/alloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'mac/ca/src/alloc.c')
-rw-r--r--mac/ca/src/alloc.c123
1 files changed, 123 insertions, 0 deletions
diff --git a/mac/ca/src/alloc.c b/mac/ca/src/alloc.c
new file mode 100644
index 0000000000..4d0926ccaa
--- /dev/null
+++ b/mac/ca/src/alloc.c
@@ -0,0 +1,123 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file mac/ca/src/alloc.c
+ * \brief Beacon period and schedule related functions.
+ * \ingroup mac_ca
+ */
+#include "common/std.h"
+
+#include "mac/ca/inc/context.h"
+#include "mac/ca/inc/alloc.h"
+#include "hal/phy/phy.h"
+
+uint
+ca_alloc_find_beacon_period (const ca_t *ctx, u32 date)
+{
+ uint pi, i;
+ dbg_assert (ctx);
+ pi = ctx->beacon_periods_tail;
+ for (i = ctx->beacon_periods_head;
+ i != ctx->beacon_periods_tail
+ && lesseq_mod2p32 (ctx->beacon_periods[i].start_date, date);
+ pi = i, i = CA_ALLOC_NEXT_BEACON_PERIOD (i))
+ ;
+ return pi;
+}
+
+uint
+ca_alloc_find (const ca_schedule_t *sched, uint offset_tck)
+{
+ uint a, b, m;
+ /* Dichotomy search. */
+ a = 0;
+ b = sched->allocations_nb;
+ while (a != b)
+ {
+ m = (a + b) / 2;
+ if (less_mod2p32 (offset_tck, sched->allocations[m].end_offset_tck))
+ b = m;
+ else
+ a = m + 1;
+ }
+ return a;
+}
+
+ca_schedule_t *
+ca_alloc_get_schedule (ca_t *ctx, uint index)
+{
+ uint i;
+ dbg_assert (ctx);
+ /* Check this schedule is not used. */
+ for (i = ctx->beacon_periods_head;
+ i != ctx->beacon_periods_tail;
+ i = CA_ALLOC_NEXT_BEACON_PERIOD (i))
+ dbg_assert (ctx->beacon_periods[i].schedule_index != index);
+ return &ctx->schedules[index];
+}
+
+void
+ca_alloc_update_beacon_periods (ca_t *ctx,
+ ca_beacon_period_t *beacon_periods,
+ uint beacon_periods_nb)
+{
+ u32 now;
+ uint i, j;
+ bool non_smooth = false;
+ dbg_assert (ctx);
+ dbg_assert (beacon_periods);
+ dbg_assert (beacon_periods_nb > 0
+ && beacon_periods_nb < CA_BEACON_PERIOD_NB - 1);
+ /* Eliminate expired beacon period from context. */
+ for (i = ctx->beacon_periods_head;
+ i != ctx->beacon_periods_tail
+ && less_mod2p32 (ctx->beacon_periods[i].start_date,
+ beacon_periods[0].start_date);
+ i = CA_ALLOC_NEXT_BEACON_PERIOD (i))
+ ;
+ ctx->beacon_periods_head = i;
+ /* First beacon period provided should be the current one (actually, it
+ * might be the second one...). */
+ now = phy_date (ctx->phy);
+ dbg_assert (lesseq_mod2p32 (beacon_periods[0].start_date, now)
+ && (beacon_periods_nb < 2
+ || less_mod2p32 (now, beacon_periods[1].start_date)));
+ /* Update the first and second period.
+ * This step aims at checking whether the current scheduled access should
+ * be updated. TODO It should be reworked. For example, a better
+ * approach could process as a regular update to work out if the same
+ * results are obtained. I suspect the current approach to give both
+ * false positives and negatives, to not work anymore as soon as NTB plays
+ * against us, or actually, to not work at all... */
+ for (j = 0, i = ctx->beacon_periods_head;
+ j < 2 && j < beacon_periods_nb && i != ctx->beacon_periods_tail;
+ j++, i = CA_ALLOC_NEXT_BEACON_PERIOD (i))
+ {
+ if (ctx->beacon_periods[i].start_date != beacon_periods[j].start_date
+ || (ctx->beacon_periods[i].schedule_index
+ != beacon_periods[j].schedule_index))
+ {
+ /* Non-smooth update. */
+ non_smooth = true;
+ break;
+ }
+ }
+ /* Update other periods. */
+ for (; j < beacon_periods_nb; j++, i = CA_ALLOC_NEXT_BEACON_PERIOD (i))
+ {
+ ctx->beacon_periods[i].start_date = beacon_periods[j].start_date;
+ ctx->beacon_periods[i].schedule_index =
+ beacon_periods[j].schedule_index;
+ }
+ ctx->beacon_periods_tail = i;
+ dbg_assert ((ctx->beacon_periods_tail - ctx->beacon_periods_head +
+ CA_BEACON_PERIOD_NB) % CA_BEACON_PERIOD_NB ==
+ beacon_periods_nb);
+ /* TODO Handle non-smooth updates. */
+}
+