extend TDMA scheduler functions to use third parameter (p3)
authorHarald Welte <laforge@gnumonks.org>
Sun, 28 Feb 2010 21:58:30 +0000 (22:58 +0100)
committerHarald Welte <laforge@gnumonks.org>
Mon, 1 Mar 2010 22:48:45 +0000 (23:48 +0100)
The idea of the third parameter is that it can be specified on a
tdma_schedule_set() level.  The multi-frame scheduler can thus use
it to pass some context information into the l1s_{cmd,resp}_*()
functions, such as the MF TASK and whether or not it is SDCCH or
SACCH.

src/target/firmware/include/layer1/sched_gsmtime.h
src/target/firmware/include/layer1/tdma_sched.h
src/target/firmware/layer1/async.c
src/target/firmware/layer1/mframe_sched.c
src/target/firmware/layer1/sched_gsmtime.c
src/target/firmware/layer1/sync.c
src/target/firmware/layer1/tdma_sched.c

index d241fe0..5e9ec13 100644 (file)
@@ -8,13 +8,14 @@ struct sched_gsmtime_event {
        struct llist_head list;
        struct tdma_sched_item *si;
        uint32_t fn;
+       uint16_t p3;    /* parameter for TDMA scheduler */
 };
 
 /* 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);
+int sched_gsmtime(struct tdma_sched_item *si, uint32_t fn, uint16_t p3);
 
 /* execute all GSMTIME one-shot events pending for 'current_fn' */
 int sched_gsmtime_execute(uint32_t current_fn);
index 2f32a18..40fcb47 100644 (file)
 #define TDMASCHED_NUM_FRAMES   25
 #define TDMASCHED_NUM_CB       5
 
-typedef int tdma_sched_cb(uint16_t p1, uint16_t p2);
+typedef int tdma_sched_cb(uint8_t p1, uint8_t p2, uint16_t p3);
 
 /* A single item in a TDMA scheduler bucket */
 struct tdma_sched_item {
        tdma_sched_cb *cb;
-       uint16_t p1;
-       uint16_t p2;
+       uint8_t p1;
+       uint8_t p2;
+       uint16_t p3;
 };
 
 /* A bucket inside the TDMA scheduler */
@@ -35,10 +36,10 @@ struct tdma_scheduler {
 };
 
 /* Schedule an item at 'frame_offset' TDMA frames in the future */
-int tdma_schedule(uint8_t frame_offset, tdma_sched_cb *cb, uint16_t p1, uint16_t p2);
+int tdma_schedule(uint8_t frame_offset, tdma_sched_cb *cb, uint8_t p1, uint8_t p2, uint16_t p3);
 
 /* Schedule a set of items starting from 'frame_offset' TDMA frames in the future */
-int tdma_schedule_set(uint8_t frame_offset, const struct tdma_sched_item *item_set);
+int tdma_schedule_set(uint8_t frame_offset, const struct tdma_sched_item *item_set, uint16_t p3);
 
 /* Execute pre-scheduled events for current frame */
 int tdma_sched_execute(void);
@@ -53,7 +54,7 @@ void tdma_sched_reset(void);
 void tdma_sched_dump(void);
 
 
-extern void tdma_end_set(uint16_t p1, uint16_t p2);
+extern void tdma_end_set(uint8_t p1, uint8_t p2, uint16_t p3);
 #define SCHED_ITEM(x, y, z)            { .cb = x, .p1 = y, .p2 = z }
 #define SCHED_END_FRAME()              { .cb = NULL, .p1 = 0, .p2 = 0 }
 #define SCHED_END_SET()                        { .cb = &tdma_end_set, .p1 = 0, .p2 = 0 }
index c1a457e..d351709 100644 (file)
@@ -64,7 +64,7 @@ void l1a_rach_req(uint8_t fn51, uint8_t ra)
        /* TODO: can we wrap here? I don't think so */
        fn_sched = l1s.current_time.fn - l1s.current_time.t3;
        fn_sched += fn51;
-       sched_gsmtime(rach_sched_set_ul, fn_sched);
+       sched_gsmtime(rach_sched_set_ul, fn_sched, 0);
        l1a_unlock_sync();
 }
 
index 7bae6ca..502d102 100644 (file)
@@ -45,7 +45,7 @@ struct mframe_sched_item {
        /* At which number inside the modulo shall we be scheduled */
        uint16_t frame_nr;
        /* bit-mask of flags */
-       uint32_t flags;
+       uint16_t flags;
 };
 
 /* FIXME: properly clean this up */
@@ -246,7 +246,8 @@ static void mframe_schedule_set(const struct mframe_sched_item *set)
                unsigned int current = (l1s.current_time.fn + SCHEDULE_AHEAD) % si->modulo;
                if (current == trigger) {
                        /* FIXME: what to do with SACCH Flag etc? */
-                       tdma_schedule_set(SCHEDULE_AHEAD-SCHEDULE_LATENCY, si->sched_set);
+                       tdma_schedule_set(SCHEDULE_AHEAD-SCHEDULE_LATENCY,
+                                         si->sched_set, si->flags);
                }
        }
 }
index 86b5103..dabe15f 100644 (file)
@@ -34,7 +34,7 @@ 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)
+int sched_gsmtime(struct tdma_sched_item *si, uint32_t fn, uint16_t p3)
 {
        struct llist_head *lh;
        struct sched_gsmtime_event *evt, *cur;
@@ -50,6 +50,7 @@ int sched_gsmtime(struct tdma_sched_item *si, uint32_t fn)
 
        evt->fn = fn;
        evt->si = si;
+       evt->p3 = p3;
 
        /* do a sorted insert into the list, i.e. insert the new
         * event _before_ the first entry that has a higher fn */
@@ -82,7 +83,8 @@ int sched_gsmtime_execute(uint32_t fn)
        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);
+                       tdma_schedule_set(SCHEDULE_AHEAD-SCHEDULE_LATENCY,
+                                         evt->si, evt->p3);
                        llist_del(&evt->list);
                        /* put event back in list of inactive (free) events */
                        llist_add(&evt->list, &inactive_evts);
index 8ad6d96..1f01158 100644 (file)
@@ -400,7 +400,7 @@ static void l1_sync(void)
 
 /* ABORT command ********************************************************/
 
-static int l1s_abort_cmd(uint16_t p1, uint16_t p2)
+static int l1s_abort_cmd(uint8_t p1, uint8_t p2, uint16_t p3)
 {
        putchart('A');
 
@@ -427,13 +427,13 @@ static int l1s_abort_cmd(uint16_t p1, uint16_t p2)
 void l1s_dsp_abort(void)
 {
        /* abort right now */
-       tdma_schedule(0, &l1s_abort_cmd, 0, 0);
+       tdma_schedule(0, &l1s_abort_cmd, 0, 0, 0);
 }
 
 /* FCCH Burst *****************************************************************/
 
 /* scheduler callback to issue a FB detection task to the DSP */
-static int l1s_fbdet_cmd(uint16_t p1, uint16_t fb_mode)
+static int l1s_fbdet_cmd(uint8_t p1, uint8_t fb_mode, uint16_t p3)
 {
        if (fb_mode == 0) {
                putchart('F');
@@ -456,7 +456,7 @@ static int l1s_fbdet_cmd(uint16_t p1, uint16_t fb_mode)
 
 
 /* scheduler callback to check for a FB detection response */
-static int l1s_fbdet_resp(uint16_t p1, uint16_t attempt)
+static int l1s_fbdet_resp(uint8_t p1, uint8_t attempt, uint16_t p3)
 {
        int ntdma, qbits, fn_offset;
 
@@ -575,17 +575,17 @@ void l1s_fb_test(uint8_t base_fn, uint8_t fb_mode)
 #if 1
        int i;
        /* schedule the FB detection command */
-       tdma_schedule(base_fn, &l1s_fbdet_cmd, 0, fb_mode);
+       tdma_schedule(base_fn, &l1s_fbdet_cmd, 0, fb_mode, 0);
 
        /* schedule 12 attempts to read the result */
        for (i = 1; i <= 12; i++) {
                uint8_t fn = base_fn + 1 + i;
-               tdma_schedule(fn, &l1s_fbdet_resp, 0, i);
+               tdma_schedule(fn, &l1s_fbdet_resp, 0, i, 0);
        }
 #else
        /* use the new scheduler 'set' and simply schedule the whole set */
        /* WARNING: we cannot set FB_MODE_1 this way !!! */
-       tdma_schedule_set(base_fn, fb_sched_set);
+       tdma_schedule_set(base_fn, fb_sched_set, 0);
 #endif
 }
 
@@ -601,7 +601,7 @@ static uint8_t sb_cnt;
 
 extern const struct tdma_sched_item rach_sched_set_ul[];
 
-static int l1s_sbdet_resp(uint16_t p1, uint16_t attempt)
+static int l1s_sbdet_resp(uint8_t p1, uint8_t attempt, uint16_t p3)
 {
        uint32_t sb;
        uint8_t bsic;
@@ -713,7 +713,7 @@ static int l1s_sbdet_resp(uint16_t p1, uint16_t attempt)
        return 0;
 }
 
-static int l1s_sbdet_cmd(uint16_t p1, uint16_t p2)
+static int l1s_sbdet_cmd(uint8_t p1, uint8_t p2, uint16_t p3)
 {
        putchart('S');
 
@@ -734,21 +734,21 @@ void l1s_sb_test(uint8_t base_fn)
 {
 #if 1
        /* This is how it is done by the TSM30 */
-       tdma_schedule(base_fn, &l1s_sbdet_cmd, 0, 1);
-       tdma_schedule(base_fn + 1, &l1s_sbdet_cmd, 0, 2);
-       tdma_schedule(base_fn + 3, &l1s_sbdet_resp, 0, 1);
-       tdma_schedule(base_fn + 4, &l1s_sbdet_resp, 0, 2);
+       tdma_schedule(base_fn, &l1s_sbdet_cmd, 0, 1, 0);
+       tdma_schedule(base_fn + 1, &l1s_sbdet_cmd, 0, 2, 0);
+       tdma_schedule(base_fn + 3, &l1s_sbdet_resp, 0, 1, 0);
+       tdma_schedule(base_fn + 4, &l1s_sbdet_resp, 0, 2, 0);
 #else
-       tdma_schedule(base_fn, &l1s_sbdet_cmd, 0, 1);
-       tdma_schedule(base_fn + 1, &l1s_sbdet_resp, 0, 1);
-       tdma_schedule(base_fn + 2, &l1s_sbdet_resp, 0, 2);
+       tdma_schedule(base_fn, &l1s_sbdet_cmd, 0, 1, 0);
+       tdma_schedule(base_fn + 1, &l1s_sbdet_resp, 0, 1, 0);
+       tdma_schedule(base_fn + 2, &l1s_sbdet_resp, 0, 2, 0);
 #endif
 }
 
 /* Power Measurement **********************************************************/
 
 /* scheduler callback to issue a power measurement task to the DSP */
-static int l1s_pm_cmd(uint16_t p1, uint16_t arfcn)
+static int l1s_pm_cmd(uint8_t p1, uint8_t p2, uint16_t arfcn)
 {
        putchart('P');
 
@@ -766,7 +766,7 @@ static int l1s_pm_cmd(uint16_t p1, uint16_t arfcn)
 }
 
 /* scheduler callback to read power measurement resposnse from the DSP */
-static int l1s_pm_resp(uint16_t p1, uint16_t p2)
+static int l1s_pm_resp(uint8_t p1, uint8_t p2, uint16_t p3)
 {
        uint16_t pm_level[2];
        struct l1_signal sig;
@@ -793,13 +793,13 @@ static int l1s_pm_resp(uint16_t p1, uint16_t p2)
 
 void l1s_pm_test(uint8_t base_fn, uint16_t arfcn)
 {
-       tdma_schedule(base_fn, &l1s_pm_cmd, 0, arfcn);
-       tdma_schedule(base_fn + 2, &l1s_pm_resp, 0, 0);
+       tdma_schedule(base_fn, &l1s_pm_cmd, 0, 0, arfcn);
+       tdma_schedule(base_fn + 2, &l1s_pm_resp, 0, 0, 0);
 }
 
 /* Normal Burst ***************************************************************/
 
-static int l1s_nb_resp(uint16_t p1, uint16_t burst_id)
+static int l1s_nb_resp(uint8_t p1, uint8_t burst_id, uint16_t p3)
 {
        static struct l1_signal _nb_sig, *sig = &_nb_sig;
        struct msgb *msg;
@@ -872,7 +872,7 @@ static int l1s_nb_resp(uint16_t p1, uint16_t burst_id)
        return 0;
 }
 
-static int l1s_nb_cmd(uint16_t p1, uint16_t burst_id)
+static int l1s_nb_cmd(uint8_t p1, uint8_t burst_id, uint16_t p3)
 {
        uint8_t tsc = l1s.serving_cell.bsic & 0x7;
 
@@ -902,7 +902,7 @@ const struct tdma_sched_item nb_sched_set[] = {
 const uint8_t ubUui[23]     = { 0x01, 0x03, 0x01, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b };
 
 /* p1: type of operation (0: one NB, 1: one RACH burst, 2: four NB */
-static int l1s_tx_resp(uint16_t p1, uint16_t burst_id)
+static int l1s_tx_resp(uint8_t p1, uint8_t burst_id, uint16_t p3)
 {
        putchart('t');
 
@@ -933,7 +933,7 @@ static int l1s_tx_resp(uint16_t p1, uint16_t burst_id)
 static uint8_t loc_cnt = 0;
 
 /* p1: type of operation (0: one NB, 1: one RACH burst, 2: four NB */
-static int l1s_tx_cmd(uint16_t p1, uint16_t burst_id)
+static int l1s_tx_cmd(uint8_t p1, uint8_t burst_id, uint16_t p3)
 {
        int i;
        uint8_t tsc;
@@ -1035,20 +1035,20 @@ void l1s_tx_test(uint8_t base_fn, uint8_t type)
        printf("Starting TX %d\n", type);
 
        if (type == 0) {// one normal burst
-               tdma_schedule(base_fn, &l1s_tx_cmd, 0, 0);
-               tdma_schedule(base_fn + 2, &l1s_tx_resp, 0, 0);
+               tdma_schedule(base_fn, &l1s_tx_cmd, 0, 0, 0);
+               tdma_schedule(base_fn + 2, &l1s_tx_resp, 0, 0, 0);
        } else if (type == 1) { // one RACH burst
-               tdma_schedule(base_fn, &l1s_tx_cmd, 1, 0);
-               tdma_schedule(base_fn + 2, &l1s_tx_resp, 1, 0);
+               tdma_schedule(base_fn, &l1s_tx_cmd, 1, 0, 0);
+               tdma_schedule(base_fn + 2, &l1s_tx_resp, 1, 0, 0);
        } else if (type == 2) { // four normal burst
-               tdma_schedule(base_fn, &l1s_tx_cmd, 2, 0);
-               tdma_schedule(base_fn + 1, &l1s_tx_cmd, 2, 1);
-               tdma_schedule(base_fn + 2, &l1s_tx_resp, 2, 0);
-               tdma_schedule(base_fn + 2, &l1s_tx_cmd, 2, 2);
-               tdma_schedule(base_fn + 3, &l1s_tx_resp, 2, 1);
-               tdma_schedule(base_fn + 3, &l1s_tx_cmd, 2, 3);
-               tdma_schedule(base_fn + 4, &l1s_tx_resp, 2, 2);
-               tdma_schedule(base_fn + 5, &l1s_tx_resp, 2, 3);
+               tdma_schedule(base_fn, &l1s_tx_cmd, 2, 0, 0);
+               tdma_schedule(base_fn + 1, &l1s_tx_cmd, 2, 1, 0);
+               tdma_schedule(base_fn + 2, &l1s_tx_resp, 2, 0, 0);
+               tdma_schedule(base_fn + 2, &l1s_tx_cmd, 2, 2, 0);
+               tdma_schedule(base_fn + 3, &l1s_tx_resp, 2, 1, 0);
+               tdma_schedule(base_fn + 3, &l1s_tx_cmd, 2, 3, 0);
+               tdma_schedule(base_fn + 4, &l1s_tx_resp, 2, 2, 0);
+               tdma_schedule(base_fn + 5, &l1s_tx_resp, 2, 3, 0);
        }
 }
 
index 0ed1a75..12296d7 100644 (file)
@@ -33,7 +33,7 @@
 #include <calypso/dsp.h>
 
 /* dummy function to mark end of set */
-void tdma_end_set(uint16_t p1, uint16_t p2)
+void tdma_end_set(uint8_t p1, uint8_t p2, uint16_t p3)
 {
 
 }
@@ -49,7 +49,7 @@ static uint8_t wrap_bucket(uint8_t offset)
 }
 
 /* Schedule an item at 'frame_offset' TDMA frames in the future */
-int tdma_schedule(uint8_t frame_offset, tdma_sched_cb *cb, uint16_t p1, uint16_t p2)
+int tdma_schedule(uint8_t frame_offset, tdma_sched_cb *cb, uint8_t p1, uint8_t p2, uint16_t p3)
 {
        struct tdma_scheduler *sched = &l1s.tdma_sched;
        uint8_t bucket_nr = wrap_bucket(frame_offset);
@@ -66,12 +66,13 @@ int tdma_schedule(uint8_t frame_offset, tdma_sched_cb *cb, uint16_t p1, uint16_t
        sched_item->cb = cb;
        sched_item->p1 = p1;
        sched_item->p2 = p2;
+       sched_item->p3 = p3;
 
        return 0;
 }
 
 /* Schedule a set of items starting from 'frame_offset' TDMA frames in the future */
-int tdma_schedule_set(uint8_t frame_offset, const struct tdma_sched_item *item_set)
+int tdma_schedule_set(uint8_t frame_offset, const struct tdma_sched_item *item_set, uint16_t p3)
 {
        struct tdma_scheduler *sched = &l1s.tdma_sched;
        uint8_t bucket_nr = wrap_bucket(frame_offset);
@@ -97,7 +98,9 @@ int tdma_schedule_set(uint8_t frame_offset, const struct tdma_sched_item *item_s
                        return -1;
                }
                /* copy the item from the set into the current bucket item position */
-               memcpy(&bucket->item[bucket->num_items++], sched_item, sizeof(*sched_item));
+               memcpy(&bucket->item[bucket->num_items], sched_item, sizeof(*sched_item));
+               bucket->item[bucket->num_items].p3 = p3;
+               bucket->num_items++;
        }
 
        return i;
@@ -131,7 +134,7 @@ int tdma_sched_execute(void)
 
                num_events++;
 
-               rc = item->cb(item->p1, item->p2);
+               rc = item->cb(item->p1, item->p2, item->p3);
                if (rc < 0) {
                        printf("Error %d during processing of item %u of bucket %u\n",
                                rc, i, sched->cur_bucket);