summaryrefslogtreecommitdiff
path: root/mac/ca/src/alloc.c
blob: 4d0926ccaa79d23359a02eeb2512881096345766 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
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. */
}