aboutsummaryrefslogtreecommitdiffstats
path: root/firmware/src_simtrace/req_ctx.c
blob: a4ecee299edd704d86bafd6387354ec53c620845 (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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/* USB Request Context for OpenPCD / OpenPICC / SIMtrace
 * (C) 2006-2016 by Harald Welte <hwelte@hmw-consulting.de>
 *
 *  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 <unistd.h>
#include <stdlib.h>
#include <stdint.h>

#include "utils.h"
#include "trace.h"
#include "req_ctx.h"

#define NUM_RCTX_SMALL 10
#define NUM_RCTX_LARGE 0

#define NUM_REQ_CTX	(NUM_RCTX_SMALL+NUM_RCTX_LARGE)

static uint8_t rctx_data[NUM_RCTX_SMALL][RCTX_SIZE_SMALL];
static uint8_t rctx_data_large[NUM_RCTX_LARGE][RCTX_SIZE_LARGE];

static struct req_ctx req_ctx[NUM_REQ_CTX];

struct req_ctx __ramfunc *
req_ctx_find_get(int large, uint32_t old_state, uint32_t new_state)
{
	struct req_ctx *toReturn = NULL;
	unsigned long flags;
	unsigned int i;

	if (old_state >= RCTX_STATE_COUNT || new_state >= RCTX_STATE_COUNT) {
		TRACE_DEBUG("Invalid parameters for req_ctx_find_get\r\n");
		return NULL;
	}

	local_irq_save(flags);
	for (i = 0; i < ARRAY_SIZE(req_ctx); i++) {
		if (req_ctx[i].state == old_state) {
			toReturn = &req_ctx[i];
			toReturn->state = new_state;
			break;
		}
	}
	local_irq_restore(flags);

	TRACE_DEBUG("%s(%u, %u, %u)=%p\r\n", __func__, large, old_state,
			new_state, toReturn);

	return toReturn;
}

uint8_t req_ctx_num(struct req_ctx *ctx)
{
	return ctx - req_ctx;
}

void req_ctx_set_state(struct req_ctx *ctx, uint32_t new_state)
{
	unsigned long flags;

	TRACE_DEBUG("%s(ctx=%p, new_state=%u)\r\n", __func__, ctx, new_state);

	if (new_state >= RCTX_STATE_COUNT) {
		TRACE_DEBUG("Invalid new_state for req_ctx_set_state\r\n");
		return;
	}
	local_irq_save(flags);
	ctx->state = new_state;
	local_irq_restore(flags);
}

#ifdef DEBUG_REQCTX
void req_print(int state) {
	int count = 0;
	struct req_ctx *ctx, *last = NULL;
	DEBUGP("State [%02i] start <==> ", state);
	ctx = req_ctx_queues[state];
	while (ctx) {
		if (last != ctx->prev)
			DEBUGP("*INV_PREV* ");
		DEBUGP("%08X => ", ctx);
		last = ctx;
		ctx = ctx->next;
		count++;
		if (count > NUM_REQ_CTX) {
		  DEBUGP("*WILD POINTER* => ");
		  break;
		}
	}
	TRACE_DEBUG("NULL");
	if (!req_ctx_queues[state] && req_ctx_tails[state]) {
		TRACE_DEBUG("NULL head, NON-NULL tail\r\n");
	}
	if (last != req_ctx_tails[state]) {
		TRACE_DEBUG("Tail does not match last element\r\n");
	}
}
#endif

void req_ctx_put(struct req_ctx *ctx)
{
	return req_ctx_set_state(ctx, RCTX_S_FREE);
}

void req_ctx_init(void)
{
	int i;
	for (i = 0; i < NUM_RCTX_SMALL; i++) {
		req_ctx[i].size = RCTX_SIZE_SMALL;
		req_ctx[i].tot_len = 0;
		req_ctx[i].data = rctx_data[i];
		req_ctx[i].state = RCTX_S_FREE;
		TRACE_DEBUG("SMALL req_ctx[%02i] initialized at %p, Data: %p => %p\r\n",
			i, req_ctx + i, req_ctx[i].data, req_ctx[i].data + RCTX_SIZE_SMALL);
	}

	for (; i < NUM_REQ_CTX; i++) {
		req_ctx[i].size = RCTX_SIZE_LARGE;
		req_ctx[i].tot_len = 0;
		req_ctx[i].data = rctx_data_large[i];
		req_ctx[i].state = RCTX_S_FREE;
		TRACE_DEBUG("LARGE req_ctx[%02i] initialized at %p, Data: %p => %p\r\n",
			i, req_ctx + i, req_ctx[i].data, req_ctx[i].data + RCTX_SIZE_LARGE);
	}
}