/alps/pcitool

To get this branch, use:
bzr branch http://suren.me/webbzr/alps/pcitool
45 by root
North West Logick DMA implementation
1
#include <stdio.h>
2
#include <string.h>
3
#include <strings.h>
4
#include <stdlib.h>
5
#include <stdint.h>
6
#include <stdarg.h>
7
#include <fcntl.h>
8
#include <unistd.h>
9
#include <sys/ioctl.h>
10
#include <sys/mman.h>
11
#include <arpa/inet.h>
69 by Suren A. Chilingaryan
Add timeout to pcilib_skip_dma
12
#include <sys/time.h>
45 by root
North West Logick DMA implementation
13
#include <errno.h>
14
#include <assert.h>
15
16
#include "error.h"
17
#include "pcilib.h"
18
#include "pci.h"
19
#include "dma.h"
330 by Suren A. Chilingaryan
Support for 64-bit registes
20
#include "tools.h"
21
#include "pagecpy.h"
45 by root
North West Logick DMA implementation
22
240 by Suren A. Chilingaryan
More structural changes to get ready for stand-alone event engines
23
const pcilib_dma_description_t *pcilib_get_dma_description(pcilib_t *ctx) {
236 by Suren A. Chilingaryan
Big redign of model structures
24
    int err;
70 by Suren A. Chilingaryan
Support modifications of DMA engine and allow DMA customizations by Event engine
25
236 by Suren A. Chilingaryan
Big redign of model structures
26
    err = pcilib_init_dma(ctx);
27
    if (err) {
28
	pcilib_error("Error (%i) while initializing DMA", err);
29
	return NULL;
45 by root
North West Logick DMA implementation
30
    }
236 by Suren A. Chilingaryan
Big redign of model structures
31
32
    if (!ctx->dma_ctx) return NULL;
33
240 by Suren A. Chilingaryan
More structural changes to get ready for stand-alone event engines
34
    return &ctx->dma;
45 by root
North West Logick DMA implementation
35
}
36
236 by Suren A. Chilingaryan
Big redign of model structures
37
49 by Suren A. Chilingaryan
A bit of renaming
38
pcilib_dma_engine_t pcilib_find_dma_by_addr(pcilib_t *ctx, pcilib_dma_direction_t direction, pcilib_dma_engine_addr_t dma) {
39
    pcilib_dma_engine_t i;
45 by root
North West Logick DMA implementation
40
240 by Suren A. Chilingaryan
More structural changes to get ready for stand-alone event engines
41
    const pcilib_dma_description_t *dma_info =  pcilib_get_dma_description(ctx);
42
    if (!dma_info) {
45 by root
North West Logick DMA implementation
43
	pcilib_error("DMA Engine is not configured in the current model");
44
	return PCILIB_ERROR_NOTSUPPORTED;
45
    }
236 by Suren A. Chilingaryan
Big redign of model structures
46
240 by Suren A. Chilingaryan
More structural changes to get ready for stand-alone event engines
47
    for (i = 0; dma_info->engines[i].addr_bits; i++) {
48
	if ((dma_info->engines[i].addr == dma)&&((dma_info->engines[i].direction&direction)==direction)) break;
45 by root
North West Logick DMA implementation
49
    }
236 by Suren A. Chilingaryan
Big redign of model structures
50
240 by Suren A. Chilingaryan
More structural changes to get ready for stand-alone event engines
51
    if (dma_info->engines[i].addr_bits) return i;
62 by Suren A. Chilingaryan
Suppport DMA modes in console application (not functional yet)
52
    return PCILIB_DMA_ENGINE_INVALID;
45 by root
North West Logick DMA implementation
53
}
54
236 by Suren A. Chilingaryan
Big redign of model structures
55
56
pcilib_dma_engine_t pcilib_add_dma_engine(pcilib_t *ctx, pcilib_dma_engine_description_t *desc) {
57
    pcilib_dma_engine_t engine = ctx->num_engines++;
58
    memcpy (&ctx->engines[engine], desc, sizeof(pcilib_dma_engine_description_t));
59
    return engine;
60
}
61
62
63
int pcilib_init_dma(pcilib_t *ctx) {
64
    int err;
65
    pcilib_dma_context_t *dma_ctx = NULL;
292 by Suren A. Chilingaryan
Protect access to the DMA engine with locks
66
    const pcilib_dma_description_t *info = &ctx->dma;
236 by Suren A. Chilingaryan
Big redign of model structures
67
    const pcilib_model_description_t *model_info = pcilib_get_model_description(ctx);
68
292 by Suren A. Chilingaryan
Protect access to the DMA engine with locks
69
    pcilib_dma_engine_t dma;
70
236 by Suren A. Chilingaryan
Big redign of model structures
71
    if (ctx->dma_ctx)
72
	return 0;
73
	
74
75
    if ((ctx->event_ctx)&&(model_info->api)&&(model_info->api->init_dma)) {
76
	err = pcilib_init_register_banks(ctx);
77
	if (err) {
78
	    pcilib_error("Error (%i) while initializing register banks", err);
79
	    return err;
80
	}
81
82
	dma_ctx = model_info->api->init_dma(ctx->event_ctx);
240 by Suren A. Chilingaryan
More structural changes to get ready for stand-alone event engines
83
    } else if ((ctx->dma.api)&&(ctx->dma.api->init)) {
236 by Suren A. Chilingaryan
Big redign of model structures
84
	err = pcilib_init_register_banks(ctx);
85
	if (err) {
86
	    pcilib_error("Error (%i) while initializing register banks", err);
87
	    return err;
88
	}
89
240 by Suren A. Chilingaryan
More structural changes to get ready for stand-alone event engines
90
	dma_ctx = ctx->dma.api->init(ctx, (ctx->dma.model?ctx->dma.model:ctx->model), ctx->dma.args);
236 by Suren A. Chilingaryan
Big redign of model structures
91
    }
92
93
    if (dma_ctx) {
292 by Suren A. Chilingaryan
Protect access to the DMA engine with locks
94
	for  (dma = 0; info->engines[dma].addr_bits; dma++) {
95
	    if (info->engines[dma].direction&PCILIB_DMA_FROM_DEVICE) {
96
		ctx->dma_rlock[dma] = pcilib_get_lock(ctx, PCILIB_LOCK_FLAGS_DEFAULT, "dma%ir/%s", info->engines[dma].addr, info->name);
97
		if (!ctx->dma_rlock[dma]) break;
98
	    }
99
	    if (info->engines[dma].direction&PCILIB_DMA_TO_DEVICE) {
100
		ctx->dma_wlock[dma] = pcilib_get_lock(ctx, PCILIB_LOCK_FLAGS_DEFAULT, "dma%iw/%s", info->engines[dma].addr, info->name);
101
		if (!ctx->dma_wlock[dma]) break;
102
	    }
103
	}
104
105
	if (info->engines[dma].addr_bits) {
106
	    if (ctx->dma.api->free)
107
		ctx->dma.api->free(dma_ctx);
108
	    pcilib_error("Failed to intialize DMA locks");
109
	    return PCILIB_ERROR_FAILED;
110
	}
111
236 by Suren A. Chilingaryan
Big redign of model structures
112
	dma_ctx->pcilib = ctx;
113
	    // DS: parameters?
114
	ctx->dma_ctx = dma_ctx;
115
    }
126 by Suren A. Chilingaryan
multithread preprocessing of ipecamera frames and code reorganization
116
117
    return 0;
45 by root
North West Logick DMA implementation
118
}
119
62 by Suren A. Chilingaryan
Suppport DMA modes in console application (not functional yet)
120
int pcilib_start_dma(pcilib_t *ctx, pcilib_dma_engine_t dma, pcilib_dma_flags_t flags) {
240 by Suren A. Chilingaryan
More structural changes to get ready for stand-alone event engines
121
    const pcilib_dma_description_t *info =  pcilib_get_dma_description(ctx);
65 by Suren A. Chilingaryan
Separate NWL loopback code, provide DMA start/stop interfaces
122
    if (!info) {
123
	pcilib_error("DMA is not supported by the device");
124
	return PCILIB_ERROR_NOTSUPPORTED;
125
    }
126
240 by Suren A. Chilingaryan
More structural changes to get ready for stand-alone event engines
127
    if (!info->api) {
65 by Suren A. Chilingaryan
Separate NWL loopback code, provide DMA start/stop interfaces
128
	pcilib_error("DMA Engine is not configured in the current model");
129
	return PCILIB_ERROR_NOTAVAILABLE;
130
    }
292 by Suren A. Chilingaryan
Protect access to the DMA engine with locks
131
240 by Suren A. Chilingaryan
More structural changes to get ready for stand-alone event engines
132
    if (!info->api->start_dma) {
65 by Suren A. Chilingaryan
Separate NWL loopback code, provide DMA start/stop interfaces
133
	return 0;
134
    }
292 by Suren A. Chilingaryan
Protect access to the DMA engine with locks
135
240 by Suren A. Chilingaryan
More structural changes to get ready for stand-alone event engines
136
    return info->api->start_dma(ctx->dma_ctx, dma, flags);
62 by Suren A. Chilingaryan
Suppport DMA modes in console application (not functional yet)
137
}
138
139
int pcilib_stop_dma(pcilib_t *ctx, pcilib_dma_engine_t dma, pcilib_dma_flags_t flags) {
240 by Suren A. Chilingaryan
More structural changes to get ready for stand-alone event engines
140
    const pcilib_dma_description_t *info =  pcilib_get_dma_description(ctx);
194 by Suren A. Chilingaryan
DMA-independent IRQ functions
141
65 by Suren A. Chilingaryan
Separate NWL loopback code, provide DMA start/stop interfaces
142
    if (!info) {
143
	pcilib_error("DMA is not supported by the device");
144
	return PCILIB_ERROR_NOTSUPPORTED;
145
    }
146
240 by Suren A. Chilingaryan
More structural changes to get ready for stand-alone event engines
147
    if (!info->api) {
65 by Suren A. Chilingaryan
Separate NWL loopback code, provide DMA start/stop interfaces
148
	pcilib_error("DMA Engine is not configured in the current model");
149
	return PCILIB_ERROR_NOTAVAILABLE;
150
    }
151
    
240 by Suren A. Chilingaryan
More structural changes to get ready for stand-alone event engines
152
    if (!info->api->stop_dma) {
65 by Suren A. Chilingaryan
Separate NWL loopback code, provide DMA start/stop interfaces
153
	return 0;
154
    }
75 by Suren A. Chilingaryan
Few fixes
155
240 by Suren A. Chilingaryan
More structural changes to get ready for stand-alone event engines
156
    return info->api->stop_dma(ctx->dma_ctx, dma, flags);
62 by Suren A. Chilingaryan
Suppport DMA modes in console application (not functional yet)
157
}
158
63 by Suren A. Chilingaryan
Provide IRQ enable/disable call
159
int pcilib_enable_irq(pcilib_t *ctx, pcilib_irq_type_t irq_type, pcilib_dma_flags_t flags) {
240 by Suren A. Chilingaryan
More structural changes to get ready for stand-alone event engines
160
    const pcilib_dma_description_t *info =  pcilib_get_dma_description(ctx);
161
162
    if ((!info)||(!info->api)||(!info->api->enable_irq)) return 0;
163
164
    return info->api->enable_irq(ctx->dma_ctx, irq_type, flags);
62 by Suren A. Chilingaryan
Suppport DMA modes in console application (not functional yet)
165
}
166
167
int pcilib_disable_irq(pcilib_t *ctx, pcilib_dma_flags_t flags) {
240 by Suren A. Chilingaryan
More structural changes to get ready for stand-alone event engines
168
    const pcilib_dma_description_t *info =  pcilib_get_dma_description(ctx);
169
170
    if ((!info)||(!info->api)||(!info->api->disable_irq)) return 0;
171
172
    return info->api->disable_irq(ctx->dma_ctx, flags);
62 by Suren A. Chilingaryan
Suppport DMA modes in console application (not functional yet)
173
}
174
88 by Suren A. Chilingaryan
IRQ acknowledgement support in the engine API
175
int pcilib_acknowledge_irq(pcilib_t *ctx, pcilib_irq_type_t irq_type, pcilib_irq_source_t irq_source) {
240 by Suren A. Chilingaryan
More structural changes to get ready for stand-alone event engines
176
    const pcilib_dma_description_t *info =  pcilib_get_dma_description(ctx);
177
178
    if ((!info)||(!info->api)||(!info->api->acknowledge_irq)) return 0;
179
180
    return info->api->acknowledge_irq(ctx->dma_ctx, irq_type, irq_source);
88 by Suren A. Chilingaryan
IRQ acknowledgement support in the engine API
181
}
182
45 by root
North West Logick DMA implementation
183
typedef struct {
184
    size_t size;
185
    void *data;
186
    size_t pos;
236 by Suren A. Chilingaryan
Big redign of model structures
187
109 by Suren A. Chilingaryan
Improvements of DMA engine
188
    pcilib_dma_flags_t flags;
45 by root
North West Logick DMA implementation
189
} pcilib_dma_read_callback_context_t;
190
191
static int pcilib_dma_read_callback(void *arg, pcilib_dma_flags_t flags, size_t bufsize, void *buf) {
192
    pcilib_dma_read_callback_context_t *ctx = (pcilib_dma_read_callback_context_t*)arg;
193
    
194
    if (ctx->pos + bufsize > ctx->size) {
109 by Suren A. Chilingaryan
Improvements of DMA engine
195
	if ((ctx->flags&PCILIB_DMA_FLAG_IGNORE_ERRORS) == 0)
196
	    pcilib_error("Buffer size (%li) is not large enough for DMA packet, at least %li bytes is required", ctx->size, ctx->pos + bufsize); 
197
	return -PCILIB_ERROR_TOOBIG;
45 by root
North West Logick DMA implementation
198
    }
330 by Suren A. Chilingaryan
Support for 64-bit registes
199
200
    pcilib_pagecpy(ctx->data + ctx->pos, buf, bufsize);
45 by root
North West Logick DMA implementation
201
    ctx->pos += bufsize;
202
109 by Suren A. Chilingaryan
Improvements of DMA engine
203
    if (flags & PCILIB_DMA_FLAG_EOP) {
204
	if ((ctx->pos < ctx->size)&&(ctx->flags&PCILIB_DMA_FLAG_MULTIPACKET)) {
117 by Suren A. Chilingaryan
new event architecture, first trial
205
	    if (ctx->flags&PCILIB_DMA_FLAG_WAIT) return PCILIB_STREAMING_WAIT;
206
	    else return PCILIB_STREAMING_CONTINUE;
109 by Suren A. Chilingaryan
Improvements of DMA engine
207
	}
117 by Suren A. Chilingaryan
new event architecture, first trial
208
	return PCILIB_STREAMING_STOP;
109 by Suren A. Chilingaryan
Improvements of DMA engine
209
    }
117 by Suren A. Chilingaryan
new event architecture, first trial
210
    
211
    return PCILIB_STREAMING_REQ_FRAGMENT;
45 by root
North West Logick DMA implementation
212
}
213
214
static int pcilib_dma_skip_callback(void *arg, pcilib_dma_flags_t flags, size_t bufsize, void *buf) {
69 by Suren A. Chilingaryan
Add timeout to pcilib_skip_dma
215
    struct timeval *tv = (struct timeval*)arg;
216
    struct timeval cur;
217
    
218
    if (tv) {
219
	gettimeofday(&cur, NULL);
117 by Suren A. Chilingaryan
new event architecture, first trial
220
	if ((cur.tv_sec > tv->tv_sec)||((cur.tv_sec == tv->tv_sec)&&(cur.tv_usec > tv->tv_usec))) return PCILIB_STREAMING_STOP;
69 by Suren A. Chilingaryan
Add timeout to pcilib_skip_dma
221
    }
222
    
117 by Suren A. Chilingaryan
new event architecture, first trial
223
    return PCILIB_STREAMING_REQ_PACKET;
45 by root
North West Logick DMA implementation
224
}
225
62 by Suren A. Chilingaryan
Suppport DMA modes in console application (not functional yet)
226
int pcilib_stream_dma(pcilib_t *ctx, pcilib_dma_engine_t dma, uintptr_t addr, size_t size, pcilib_dma_flags_t flags, pcilib_timeout_t timeout, pcilib_dma_callback_t cb, void *cbattr) {
292 by Suren A. Chilingaryan
Protect access to the DMA engine with locks
227
    int err;
240 by Suren A. Chilingaryan
More structural changes to get ready for stand-alone event engines
228
    const pcilib_dma_description_t *info =  pcilib_get_dma_description(ctx);
45 by root
North West Logick DMA implementation
229
    if (!info) {
230
	pcilib_error("DMA is not supported by the device");
58 by Suren A. Chilingaryan
Wait for the completion of DMA operations during writes
231
	return PCILIB_ERROR_NOTSUPPORTED;
45 by root
North West Logick DMA implementation
232
    }
233
240 by Suren A. Chilingaryan
More structural changes to get ready for stand-alone event engines
234
    if (!info->api) {
45 by root
North West Logick DMA implementation
235
	pcilib_error("DMA Engine is not configured in the current model");
58 by Suren A. Chilingaryan
Wait for the completion of DMA operations during writes
236
	return PCILIB_ERROR_NOTAVAILABLE;
45 by root
North West Logick DMA implementation
237
    }
238
    
240 by Suren A. Chilingaryan
More structural changes to get ready for stand-alone event engines
239
    if (!info->api->stream) {
45 by root
North West Logick DMA implementation
240
	pcilib_error("The DMA read is not supported by configured DMA engine");
58 by Suren A. Chilingaryan
Wait for the completion of DMA operations during writes
241
	return PCILIB_ERROR_NOTSUPPORTED;
45 by root
North West Logick DMA implementation
242
    }
236 by Suren A. Chilingaryan
Big redign of model structures
243
244
	// DS: We should check we are not going outside of allocated engine space
245
    if (!info->engines[dma].addr_bits) {
45 by root
North West Logick DMA implementation
246
	pcilib_error("The DMA engine (%i) is not supported by device", dma);
58 by Suren A. Chilingaryan
Wait for the completion of DMA operations during writes
247
	return PCILIB_ERROR_NOTAVAILABLE;
45 by root
North West Logick DMA implementation
248
    }
249
236 by Suren A. Chilingaryan
Big redign of model structures
250
    if ((info->engines[dma].direction&PCILIB_DMA_FROM_DEVICE) == 0) {
45 by root
North West Logick DMA implementation
251
	pcilib_error("The selected engine (%i) is S2C-only and does not support reading", dma);
58 by Suren A. Chilingaryan
Wait for the completion of DMA operations during writes
252
	return PCILIB_ERROR_NOTSUPPORTED;
45 by root
North West Logick DMA implementation
253
    }
254
292 by Suren A. Chilingaryan
Protect access to the DMA engine with locks
255
    err = pcilib_try_lock(ctx->dma_rlock[dma]);
256
    if (err) {
257
	if ((err == PCILIB_ERROR_BUSY)||(err == PCILIB_ERROR_TIMEOUT))
258
	    pcilib_error("DMA engine (%i) is busy", dma);
259
	else
260
	    pcilib_error("Error (%i) locking DMA engine (%i)", err, dma);
261
262
	return err;
263
    }
264
265
    err = info->api->stream(ctx->dma_ctx, dma, addr, size, flags, timeout, cb, cbattr);
266
267
    pcilib_unlock(ctx->dma_rlock[dma]);
268
269
    return err;
45 by root
North West Logick DMA implementation
270
}
271
109 by Suren A. Chilingaryan
Improvements of DMA engine
272
int pcilib_read_dma_custom(pcilib_t *ctx, pcilib_dma_engine_t dma, uintptr_t addr, size_t size, pcilib_dma_flags_t flags, pcilib_timeout_t timeout, void *buf, size_t *read_bytes) {
273
    int err; 
274
275
    pcilib_dma_read_callback_context_t opts = {
276
	size, buf, 0, flags
277
    };
278
    
279
    err = pcilib_stream_dma(ctx, dma, addr, size, flags, timeout, pcilib_dma_read_callback, &opts);
280
    if (read_bytes) *read_bytes = opts.pos;
281
    return err;
282
}
283
58 by Suren A. Chilingaryan
Wait for the completion of DMA operations during writes
284
int pcilib_read_dma(pcilib_t *ctx, pcilib_dma_engine_t dma, uintptr_t addr, size_t size, void *buf, size_t *read_bytes) {
45 by root
North West Logick DMA implementation
285
    int err; 
286
287
    pcilib_dma_read_callback_context_t opts = {
109 by Suren A. Chilingaryan
Improvements of DMA engine
288
	size, buf, 0, 0
45 by root
North West Logick DMA implementation
289
    };
103 by Suren A. Chilingaryan
Provide information about active DMA engines & buffers
290
    
58 by Suren A. Chilingaryan
Wait for the completion of DMA operations during writes
291
    err = pcilib_stream_dma(ctx, dma, addr, size, PCILIB_DMA_FLAGS_DEFAULT, PCILIB_DMA_TIMEOUT, pcilib_dma_read_callback, &opts);
292
    if (read_bytes) *read_bytes = opts.pos;
293
    return err;
45 by root
North West Logick DMA implementation
294
}
295
109 by Suren A. Chilingaryan
Improvements of DMA engine
296
49 by Suren A. Chilingaryan
A bit of renaming
297
int pcilib_skip_dma(pcilib_t *ctx, pcilib_dma_engine_t dma) {
61 by Suren A. Chilingaryan
Few fixes
298
    int err;
69 by Suren A. Chilingaryan
Add timeout to pcilib_skip_dma
299
    struct timeval tv, cur;
300
301
    gettimeofday(&tv, NULL);
302
    tv.tv_usec += PCILIB_DMA_SKIP_TIMEOUT;
303
    tv.tv_sec += tv.tv_usec / 1000000;
304
    tv.tv_usec += tv.tv_usec % 1000000;
305
    
45 by root
North West Logick DMA implementation
306
    do {
307
	    // IMMEDIATE timeout is not working properly, so default is set
69 by Suren A. Chilingaryan
Add timeout to pcilib_skip_dma
308
	err = pcilib_stream_dma(ctx, dma, 0, 0, PCILIB_DMA_FLAGS_DEFAULT, PCILIB_DMA_TIMEOUT, pcilib_dma_skip_callback, &tv);
309
	gettimeofday(&cur, NULL);
310
    } while ((!err)&&((cur.tv_sec < tv.tv_sec)||((cur.tv_sec == tv.tv_sec)&&(cur.tv_usec < tv.tv_usec))));
311
312
    if ((cur.tv_sec > tv.tv_sec)||((cur.tv_sec == tv.tv_sec)&&(cur.tv_usec > tv.tv_usec))) return PCILIB_ERROR_TIMEOUT;
45 by root
North West Logick DMA implementation
313
    
314
    return 0;
315
}
316
317
62 by Suren A. Chilingaryan
Suppport DMA modes in console application (not functional yet)
318
int pcilib_push_dma(pcilib_t *ctx, pcilib_dma_engine_t dma, uintptr_t addr, size_t size, pcilib_dma_flags_t flags, pcilib_timeout_t timeout, void *buf, size_t *written) {
292 by Suren A. Chilingaryan
Protect access to the DMA engine with locks
319
    int err;
320
240 by Suren A. Chilingaryan
More structural changes to get ready for stand-alone event engines
321
    const pcilib_dma_description_t *info =  pcilib_get_dma_description(ctx);
45 by root
North West Logick DMA implementation
322
    if (!info) {
323
	pcilib_error("DMA is not supported by the device");
58 by Suren A. Chilingaryan
Wait for the completion of DMA operations during writes
324
	return PCILIB_ERROR_NOTSUPPORTED;
45 by root
North West Logick DMA implementation
325
    }
326
240 by Suren A. Chilingaryan
More structural changes to get ready for stand-alone event engines
327
    if (!info->api) {
45 by root
North West Logick DMA implementation
328
	pcilib_error("DMA Engine is not configured in the current model");
58 by Suren A. Chilingaryan
Wait for the completion of DMA operations during writes
329
	return PCILIB_ERROR_NOTAVAILABLE;
45 by root
North West Logick DMA implementation
330
    }
331
    
240 by Suren A. Chilingaryan
More structural changes to get ready for stand-alone event engines
332
    if (!info->api->push) {
45 by root
North West Logick DMA implementation
333
	pcilib_error("The DMA write is not supported by configured DMA engine");
58 by Suren A. Chilingaryan
Wait for the completion of DMA operations during writes
334
	return PCILIB_ERROR_NOTSUPPORTED;
45 by root
North West Logick DMA implementation
335
    }
336
    
236 by Suren A. Chilingaryan
Big redign of model structures
337
	    // DS: We should check we don't exceed allocated engine range
338
    if (!info->engines[dma].addr_bits) {
45 by root
North West Logick DMA implementation
339
	pcilib_error("The DMA engine (%i) is not supported by device", dma);
58 by Suren A. Chilingaryan
Wait for the completion of DMA operations during writes
340
	return PCILIB_ERROR_NOTAVAILABLE;
45 by root
North West Logick DMA implementation
341
    }
342
236 by Suren A. Chilingaryan
Big redign of model structures
343
    if ((info->engines[dma].direction&PCILIB_DMA_TO_DEVICE) == 0) {
45 by root
North West Logick DMA implementation
344
	pcilib_error("The selected engine (%i) is C2S-only and does not support writes", dma);
58 by Suren A. Chilingaryan
Wait for the completion of DMA operations during writes
345
	return PCILIB_ERROR_NOTSUPPORTED;
45 by root
North West Logick DMA implementation
346
    }
292 by Suren A. Chilingaryan
Protect access to the DMA engine with locks
347
348
    err = pcilib_try_lock(ctx->dma_wlock[dma]);
349
    if (err) {
350
	if (err == PCILIB_ERROR_BUSY) 
351
	    pcilib_error("DMA engine (%i) is busy", dma);
352
	else
353
	    pcilib_error("Error (%i) locking DMA engine (%i)", err, dma);
354
355
	return err;
356
    }
357
358
    err = info->api->push(ctx->dma_ctx, dma, addr, size, flags, timeout, buf, written);
359
360
    pcilib_unlock(ctx->dma_wlock[dma]);
361
362
    return err;
45 by root
North West Logick DMA implementation
363
}
364
365
58 by Suren A. Chilingaryan
Wait for the completion of DMA operations during writes
366
int pcilib_write_dma(pcilib_t *ctx, pcilib_dma_engine_t dma, uintptr_t addr, size_t size, void *buf, size_t *written_bytes) {
61 by Suren A. Chilingaryan
Few fixes
367
    return pcilib_push_dma(ctx, dma, addr, size, PCILIB_DMA_FLAG_EOP|PCILIB_DMA_FLAG_WAIT, PCILIB_DMA_TIMEOUT, buf, written_bytes);
45 by root
North West Logick DMA implementation
368
}
369
49 by Suren A. Chilingaryan
A bit of renaming
370
double pcilib_benchmark_dma(pcilib_t *ctx, pcilib_dma_engine_addr_t dma, uintptr_t addr, size_t size, size_t iterations, pcilib_dma_direction_t direction) {
240 by Suren A. Chilingaryan
More structural changes to get ready for stand-alone event engines
371
    const pcilib_dma_description_t *info =  pcilib_get_dma_description(ctx);
45 by root
North West Logick DMA implementation
372
    if (!info) {
373
	pcilib_error("DMA is not supported by the device");
374
	return 0;
375
    }
376
240 by Suren A. Chilingaryan
More structural changes to get ready for stand-alone event engines
377
    if (!info->api) {
45 by root
North West Logick DMA implementation
378
	pcilib_error("DMA Engine is not configured in the current model");
379
	return -1;
380
    }
381
    
240 by Suren A. Chilingaryan
More structural changes to get ready for stand-alone event engines
382
    if (!info->api->benchmark) {
45 by root
North West Logick DMA implementation
383
	pcilib_error("The DMA benchmark is not supported by configured DMA engine");
384
	return -1;
385
    }
386
240 by Suren A. Chilingaryan
More structural changes to get ready for stand-alone event engines
387
    return info->api->benchmark(ctx->dma_ctx, dma, addr, size, iterations, direction);
45 by root
North West Logick DMA implementation
388
}
103 by Suren A. Chilingaryan
Provide information about active DMA engines & buffers
389
390
int pcilib_get_dma_status(pcilib_t *ctx, pcilib_dma_engine_t dma, pcilib_dma_engine_status_t *status, size_t n_buffers, pcilib_dma_buffer_status_t *buffers) {
240 by Suren A. Chilingaryan
More structural changes to get ready for stand-alone event engines
391
    const pcilib_dma_description_t *info =  pcilib_get_dma_description(ctx);
103 by Suren A. Chilingaryan
Provide information about active DMA engines & buffers
392
    if (!info) {
393
	pcilib_error("DMA is not supported by the device");
394
	return 0;
395
    }
396
240 by Suren A. Chilingaryan
More structural changes to get ready for stand-alone event engines
397
    if (!info->api) {
103 by Suren A. Chilingaryan
Provide information about active DMA engines & buffers
398
	pcilib_error("DMA Engine is not configured in the current model");
399
	return -1;
400
    }
401
    
240 by Suren A. Chilingaryan
More structural changes to get ready for stand-alone event engines
402
    if (!info->api->status) {
103 by Suren A. Chilingaryan
Provide information about active DMA engines & buffers
403
	memset(status, 0, sizeof(pcilib_dma_engine_status_t));
404
	return -1;
405
   }
406
    
236 by Suren A. Chilingaryan
Big redign of model structures
407
        // DS: We should check we don't exceed allocated engine range
408
    if (!info->engines[dma].addr_bits) {
103 by Suren A. Chilingaryan
Provide information about active DMA engines & buffers
409
	pcilib_error("The DMA engine (%i) is not supported by device", dma);
410
	return -1;
411
    }
412
240 by Suren A. Chilingaryan
More structural changes to get ready for stand-alone event engines
413
    return info->api->status(ctx->dma_ctx, dma, status, n_buffers, buffers);
103 by Suren A. Chilingaryan
Provide information about active DMA engines & buffers
414
}