/alps/pcitool

To get this branch, use:
bzr branch http://darksoft.org/webbzr/alps/pcitool
89 by Suren A. Chilingaryan
Few fixes for IPE Camera modification
1
#define _BSD_SOURCE
302 by Suren A. Chilingaryan
Fixes out-of-source builds and minor build issues
2
#define _DEFAULT_SOURCE
65 by Suren A. Chilingaryan
Separate NWL loopback code, provide DMA start/stop interfaces
3
#include <stdio.h>
4
#include <stdlib.h>
5
#include <string.h>
6
#include <unistd.h>
7
#include <sys/time.h>
8
9
#include "pci.h"
10
#include "pcilib.h"
11
#include "error.h"
12
#include "tools.h"
227 by Suren A. Chilingaryan
Initial implementation of IPEDMA, dummy driver for KAPTURE, start of API changes
13
#include "nwl_private.h"
65 by Suren A. Chilingaryan
Separate NWL loopback code, provide DMA start/stop interfaces
14
15
#include "nwl_defines.h"
16
109 by Suren A. Chilingaryan
Improvements of DMA engine
17
#define NWL_BUG_EXTRA_DATA
18
65 by Suren A. Chilingaryan
Separate NWL loopback code, provide DMA start/stop interfaces
19
20
int dma_nwl_start_loopback(nwl_dma_t *ctx,  pcilib_dma_direction_t direction, size_t packet_size) {
21
    uint32_t val;
22
78 by Suren A. Chilingaryan
Correctly detect the tail pointer of C2S ring
23
    ctx->loopback_started = 1;
24
    dma_nwl_stop_loopback(ctx);
65 by Suren A. Chilingaryan
Separate NWL loopback code, provide DMA start/stop interfaces
25
    
26
    val = packet_size;
27
    nwl_write_register(val, ctx, ctx->base_addr, PKT_SIZE_ADDRESS);
28
236 by Suren A. Chilingaryan
Big redign of model structures
29
    if (ctx->type == NWL_MODIFICATION_DEFAULT) {
89 by Suren A. Chilingaryan
Few fixes for IPE Camera modification
30
	switch (direction) {
31
          case PCILIB_DMA_BIDIRECTIONAL:
32
	    val = LOOPBACK;
33
	    nwl_write_register(val, ctx, ctx->base_addr, TX_CONFIG_ADDRESS);
34
	    break;
35
          case PCILIB_DMA_TO_DEVICE:
36
	    return -1;
37
	  case PCILIB_DMA_FROM_DEVICE:
38
    	    val = PKTGENR;
39
	    nwl_write_register(val, ctx, ctx->base_addr, RX_CONFIG_ADDRESS);
40
	    break;
41
	}
65 by Suren A. Chilingaryan
Separate NWL loopback code, provide DMA start/stop interfaces
42
    }
43
44
    ctx->loopback_started = 1;
45
        
46
    return 0;
47
}
48
49
int dma_nwl_stop_loopback(nwl_dma_t *ctx) {
50
    uint32_t val = 0;
78 by Suren A. Chilingaryan
Correctly detect the tail pointer of C2S ring
51
    
52
    if (!ctx->loopback_started) return 0;
65 by Suren A. Chilingaryan
Separate NWL loopback code, provide DMA start/stop interfaces
53
70 by Suren A. Chilingaryan
Support modifications of DMA engine and allow DMA customizations by Event engine
54
	/* Stop in any case, otherwise we can have problems in benchmark due to
55
	engine initialized in previous run, and benchmark is only actual usage.
56
	Otherwise, we should detect current loopback status during initialization */
89 by Suren A. Chilingaryan
Few fixes for IPE Camera modification
57
236 by Suren A. Chilingaryan
Big redign of model structures
58
    if (ctx->type == NWL_MODIFICATION_DEFAULT) {
89 by Suren A. Chilingaryan
Few fixes for IPE Camera modification
59
	nwl_write_register(val, ctx, ctx->base_addr, TX_CONFIG_ADDRESS);
60
	nwl_write_register(val, ctx, ctx->base_addr, RX_CONFIG_ADDRESS);
61
    }
62
    
70 by Suren A. Chilingaryan
Support modifications of DMA engine and allow DMA customizations by Event engine
63
    ctx->loopback_started = 0;
65 by Suren A. Chilingaryan
Separate NWL loopback code, provide DMA start/stop interfaces
64
    
65
    return 0;
66
}
71 by Suren A. Chilingaryan
First iteration of work to preserve DMA state between executions
67
68
double dma_nwl_benchmark(pcilib_dma_context_t *vctx, pcilib_dma_engine_addr_t dma, uintptr_t addr, size_t size, size_t iterations, pcilib_dma_direction_t direction) {
89 by Suren A. Chilingaryan
Few fixes for IPE Camera modification
69
    int iter, i;
71 by Suren A. Chilingaryan
First iteration of work to preserve DMA state between executions
70
    int err;
109 by Suren A. Chilingaryan
Improvements of DMA engine
71
    size_t bytes, rbytes;
71 by Suren A. Chilingaryan
First iteration of work to preserve DMA state between executions
72
    uint32_t *buf, *cmp;
73
    const char *error = NULL;
109 by Suren A. Chilingaryan
Improvements of DMA engine
74
    size_t packet_size, blocks;    
71 by Suren A. Chilingaryan
First iteration of work to preserve DMA state between executions
75
76
    size_t us = 0;
77
    struct timeval start, cur;
78
79
    nwl_dma_t *ctx = (nwl_dma_t*)vctx;
80
236 by Suren A. Chilingaryan
Big redign of model structures
81
    pcilib_dma_engine_t readid = pcilib_find_dma_by_addr(ctx->dmactx.pcilib, PCILIB_DMA_FROM_DEVICE, dma);
82
    pcilib_dma_engine_t writeid = pcilib_find_dma_by_addr(ctx->dmactx.pcilib, PCILIB_DMA_TO_DEVICE, dma);
71 by Suren A. Chilingaryan
First iteration of work to preserve DMA state between executions
83
84
    if (size%sizeof(uint32_t)) size = 1 + size / sizeof(uint32_t);
85
    else size /= sizeof(uint32_t);
86
87
	// Not supported
236 by Suren A. Chilingaryan
Big redign of model structures
88
    if (ctx->type == NWL_MODIFICATION_DEFAULT) {
109 by Suren A. Chilingaryan
Improvements of DMA engine
89
	if (direction == PCILIB_DMA_TO_DEVICE) return -1.;
90
    }
236 by Suren A. Chilingaryan
Big redign of model structures
91
//    else if ((direction == PCILIB_DMA_FROM_DEVICE)&&(ctx->type != NWL_MODIFICATION_DEFAULT)) return -1.;
71 by Suren A. Chilingaryan
First iteration of work to preserve DMA state between executions
92
93
	// Stop Generators and drain old data
236 by Suren A. Chilingaryan
Big redign of model structures
94
    if (ctx->type == NWL_MODIFICATION_DEFAULT) dma_nwl_stop_loopback(ctx);
71 by Suren A. Chilingaryan
First iteration of work to preserve DMA state between executions
95
//    dma_nwl_stop_engine(ctx, readid); // DS: replace with something better
96
97
    __sync_synchronize();
98
236 by Suren A. Chilingaryan
Big redign of model structures
99
    err = pcilib_skip_dma(ctx->dmactx.pcilib, readid);
71 by Suren A. Chilingaryan
First iteration of work to preserve DMA state between executions
100
    if (err) {
101
	pcilib_error("Can't start benchmark, devices continuously writes unexpected data using DMA engine");
230 by Suren A. Chilingaryan
Properly return error code in NWLDMA benchmarking code
102
	return -1;
71 by Suren A. Chilingaryan
First iteration of work to preserve DMA state between executions
103
    }
104
105
#ifdef NWL_GENERATE_DMA_IRQ
106
    dma_nwl_enable_engine_irq(ctx, readid);
107
    dma_nwl_enable_engine_irq(ctx, writeid);
108
#endif /* NWL_GENERATE_DMA_IRQ */
109
109 by Suren A. Chilingaryan
Improvements of DMA engine
110
    if (size * sizeof(uint32_t) > NWL_MAX_PACKET_SIZE) {
111
	packet_size = NWL_MAX_PACKET_SIZE;
112
	blocks = (size * sizeof(uint32_t)) / packet_size + (((size*sizeof(uint32_t))%packet_size)?1:0);
113
    } else {
114
	packet_size = size * sizeof(uint32_t);
115
	blocks = 1;
116
    }
117
118
    dma_nwl_start_loopback(ctx, direction, packet_size);
71 by Suren A. Chilingaryan
First iteration of work to preserve DMA state between executions
119
120
	// Allocate memory and prepare data
109 by Suren A. Chilingaryan
Improvements of DMA engine
121
    buf = malloc(blocks * packet_size * sizeof(uint32_t));
122
    cmp = malloc(blocks * packet_size * sizeof(uint32_t));
71 by Suren A. Chilingaryan
First iteration of work to preserve DMA state between executions
123
    if ((!buf)||(!cmp)) {
124
	if (buf) free(buf);
125
	if (cmp) free(cmp);
126
	return -1;
127
    }
128
236 by Suren A. Chilingaryan
Big redign of model structures
129
    if (ctx->type == NWL_MODIFICATION_IPECAMERA) {
130
	pcilib_write_register(ctx->dmactx.pcilib, NULL, "control", 0x1e5);
71 by Suren A. Chilingaryan
First iteration of work to preserve DMA state between executions
131
	usleep(100000);
236 by Suren A. Chilingaryan
Big redign of model structures
132
	pcilib_write_register(ctx->dmactx.pcilib, NULL, "control", 0x1e1);
109 by Suren A. Chilingaryan
Improvements of DMA engine
133
134
	    // This way causes more problems with garbage
236 by Suren A. Chilingaryan
Big redign of model structures
135
	//pcilib_write_register(ctx->dmactx.pcilib, NULL, "control", 0x3e1);
71 by Suren A. Chilingaryan
First iteration of work to preserve DMA state between executions
136
    }
137
138
	// Benchmark
89 by Suren A. Chilingaryan
Few fixes for IPE Camera modification
139
    for (iter = 0; iter < iterations; iter++) {
140
        memset(cmp, 0x13 + iter, size * sizeof(uint32_t));
79 by Suren A. Chilingaryan
Few more fixes
141
236 by Suren A. Chilingaryan
Big redign of model structures
142
	if (ctx->type == NWL_MODIFICATION_IPECAMERA) {
143
	    pcilib_write_register(ctx->dmactx.pcilib, NULL, "control", 0x1e1);
71 by Suren A. Chilingaryan
First iteration of work to preserve DMA state between executions
144
	}
145
236 by Suren A. Chilingaryan
Big redign of model structures
146
	if ((direction&PCILIB_DMA_TO_DEVICE)||(ctx->type != NWL_MODIFICATION_DEFAULT)) {
71 by Suren A. Chilingaryan
First iteration of work to preserve DMA state between executions
147
	    memcpy(buf, cmp, size * sizeof(uint32_t));
148
109 by Suren A. Chilingaryan
Improvements of DMA engine
149
    	    if (direction&PCILIB_DMA_TO_DEVICE) {
150
		gettimeofday(&start, NULL);
151
	    }
152
	    
236 by Suren A. Chilingaryan
Big redign of model structures
153
	    err = pcilib_write_dma(ctx->dmactx.pcilib, writeid, addr, size * sizeof(uint32_t), buf, &bytes);
71 by Suren A. Chilingaryan
First iteration of work to preserve DMA state between executions
154
	    if ((err)||(bytes != size * sizeof(uint32_t))) {
155
		error = "Write failed";
109 by Suren A. Chilingaryan
Improvements of DMA engine
156
	    	break;
157
	    }
158
	    
159
    	    if (direction&PCILIB_DMA_TO_DEVICE) {
160
		// wait written
161
		if (direction == PCILIB_DMA_TO_DEVICE) {
162
		    dma_nwl_wait_completion(ctx, writeid, PCILIB_DMA_TIMEOUT);
163
		}
164
		gettimeofday(&cur, NULL);
165
	        us += ((cur.tv_sec - start.tv_sec)*1000000 + (cur.tv_usec - start.tv_usec));    
71 by Suren A. Chilingaryan
First iteration of work to preserve DMA state between executions
166
	    }
167
	}
168
236 by Suren A. Chilingaryan
Big redign of model structures
169
	if (ctx->type == NWL_MODIFICATION_IPECAMERA) {
170
	    pcilib_write_register(ctx->dmactx.pcilib, NULL, "control", 0x3e1);
71 by Suren A. Chilingaryan
First iteration of work to preserve DMA state between executions
171
	}
172
173
	memset(buf, 0, size * sizeof(uint32_t));
109 by Suren A. Chilingaryan
Improvements of DMA engine
174
175
        if (direction&PCILIB_DMA_FROM_DEVICE) {
176
	    gettimeofday(&start, NULL);
177
	}
178
179
	for (i = 0, bytes = 0; i < blocks; i++) {
180
#ifdef NWL_BUG_EXTRA_DATA
181
	    retry:
182
#endif
183
    
236 by Suren A. Chilingaryan
Big redign of model structures
184
	    err = pcilib_read_dma(ctx->dmactx.pcilib, readid, addr, packet_size * sizeof(uint32_t), buf + (bytes>>2), &rbytes);
109 by Suren A. Chilingaryan
Improvements of DMA engine
185
	    if ((err)||(rbytes%sizeof(uint32_t))) {
186
		break;
187
	    } 
188
#ifdef NWL_BUG_EXTRA_DATA
189
	    else if (rbytes == 8) {
190
		goto retry;	
191
	    }
192
#endif
193
	    bytes += rbytes;
194
	}
195
196
        if (direction&PCILIB_DMA_FROM_DEVICE) {
197
	    gettimeofday(&cur, NULL);
198
	    us += ((cur.tv_sec - start.tv_sec)*1000000 + (cur.tv_usec - start.tv_usec));
199
	}
200
#ifdef NWL_BUG_EXTRA_DATA
201
	if ((err)||((bytes != size * sizeof(uint32_t))&&((bytes - 8) != size * sizeof(uint32_t)))) {
202
#else
71 by Suren A. Chilingaryan
First iteration of work to preserve DMA state between executions
203
	if ((err)||(bytes != size * sizeof(uint32_t))) {
109 by Suren A. Chilingaryan
Improvements of DMA engine
204
#endif
205
	    printf("Expected: %zu bytes, but %zu read, error: %i\n", size * sizeof(uint32_t), bytes, err);
206
	    error = "Read failed";
207
	    break;
71 by Suren A. Chilingaryan
First iteration of work to preserve DMA state between executions
208
	}
209
	
109 by Suren A. Chilingaryan
Improvements of DMA engine
210
#ifndef NWL_BUG_EXTRA_DATA
71 by Suren A. Chilingaryan
First iteration of work to preserve DMA state between executions
211
	if (direction == PCILIB_DMA_BIDIRECTIONAL) {
126 by Suren A. Chilingaryan
multithread preprocessing of ipecamera frames and code reorganization
212
	    if (memcmp(buf, cmp, size * sizeof(uint32_t))) {
79 by Suren A. Chilingaryan
Few more fixes
213
		for (i = 0; i < size; i++)
214
		    if (buf[i] != cmp[i]) break;
215
		
216
		bytes = i;
109 by Suren A. Chilingaryan
Improvements of DMA engine
217
		printf("Expected: *0x%lx, Written at dword %lu:", 0x13 + iter, bytes);
79 by Suren A. Chilingaryan
Few more fixes
218
		for (; (i < size)&&(i < (bytes + 16)); i++) {
219
		    if (((i - bytes)%8)==0) printf("\n");
220
		    printf("% 10lx", buf[i]);
221
		}
89 by Suren A. Chilingaryan
Few fixes for IPE Camera modification
222
		printf("\n");
79 by Suren A. Chilingaryan
Few more fixes
223
		
71 by Suren A. Chilingaryan
First iteration of work to preserve DMA state between executions
224
		error = "Written and read values does not match";
225
		break;
226
	    }
227
	}
109 by Suren A. Chilingaryan
Improvements of DMA engine
228
#endif
229
    }
230
236 by Suren A. Chilingaryan
Big redign of model structures
231
    if (ctx->type == NWL_MODIFICATION_IPECAMERA) {
232
	pcilib_write_register(ctx->dmactx.pcilib, NULL, "control", 0x1e1);
109 by Suren A. Chilingaryan
Improvements of DMA engine
233
    }
71 by Suren A. Chilingaryan
First iteration of work to preserve DMA state between executions
234
235
    if (error) {
89 by Suren A. Chilingaryan
Few fixes for IPE Camera modification
236
	pcilib_warning("%s at iteration %i, error: %i, bytes: %zu", error, iter, err, bytes);
71 by Suren A. Chilingaryan
First iteration of work to preserve DMA state between executions
237
    }
238
    
239
#ifdef NWL_GENERATE_DMA_IRQ
240
    dma_nwl_disable_engine_irq(ctx, writeid);
241
    dma_nwl_disable_engine_irq(ctx, readid);
242
#endif /* NWL_GENERATE_DMA_IRQ */
243
89 by Suren A. Chilingaryan
Few fixes for IPE Camera modification
244
    dma_nwl_stop_loopback(ctx);
71 by Suren A. Chilingaryan
First iteration of work to preserve DMA state between executions
245
246
    __sync_synchronize();
247
    
248
    if (direction == PCILIB_DMA_FROM_DEVICE) {
236 by Suren A. Chilingaryan
Big redign of model structures
249
	pcilib_skip_dma(ctx->dmactx.pcilib, readid);
71 by Suren A. Chilingaryan
First iteration of work to preserve DMA state between executions
250
    }
251
    
252
    free(cmp);
253
    free(buf);
254
109 by Suren A. Chilingaryan
Improvements of DMA engine
255
    return /*error?-1:*/(1. * size * sizeof(uint32_t) * iterations * 1000000) / (1024. * 1024. * us);
71 by Suren A. Chilingaryan
First iteration of work to preserve DMA state between executions
256
}