/alps/pcitool

To get this branch, use:
bzr branch http://suren.me/webbzr/alps/pcitool

« back to all changes in this revision

Viewing changes to dma.c

  • Committer: Suren A. Chilingaryan
  • Date: 2015-04-20 20:01:04 UTC
  • Revision ID: csa@suren.me-20150420200104-b5xny65io8lvoz3w
Big redign of model structures

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
#include "pci.h"
19
19
#include "dma.h"
20
20
 
21
 
const pcilib_dma_info_t *pcilib_get_dma_info(pcilib_t *ctx) {
22
 
    if (!ctx->dma_ctx) {
23
 
        pcilib_model_description_t *model_info = pcilib_get_model_description(ctx);
 
21
const pcilib_dma_description_t *pcilib_get_dma_info(pcilib_t *ctx) {
 
22
    int err;
24
23
 
25
 
        if ((ctx->event_ctx)&&(model_info->event_api->init_dma)) {
26
 
            pcilib_map_register_space(ctx);
27
 
            ctx->dma_ctx = model_info->event_api->init_dma(ctx->event_ctx);
28
 
        } else if ((model_info->dma_api)&&(model_info->dma_api->init)) {
29
 
            pcilib_map_register_space(ctx);
30
 
            ctx->dma_ctx = model_info->dma_api->init(ctx, PCILIB_DMA_MODIFICATION_DEFAULT, NULL);
31
 
        }
32
 
        
33
 
        if (!ctx->dma_ctx) return NULL;
 
24
    err = pcilib_init_dma(ctx);
 
25
    if (err) {
 
26
        pcilib_error("Error (%i) while initializing DMA", err);
 
27
        return NULL;
34
28
    }
35
 
    
36
 
    return &ctx->dma_info;
 
29
 
 
30
    if (!ctx->dma_ctx) return NULL;
 
31
 
 
32
    return ctx->model_info.dma;
37
33
}
38
34
 
 
35
 
39
36
pcilib_dma_engine_t pcilib_find_dma_by_addr(pcilib_t *ctx, pcilib_dma_direction_t direction, pcilib_dma_engine_addr_t dma) {
40
37
    pcilib_dma_engine_t i;
41
38
 
42
 
    const pcilib_dma_info_t *info =  pcilib_get_dma_info(ctx);
 
39
    const pcilib_dma_description_t *info =  pcilib_get_dma_info(ctx);
43
40
    if (!info) {
44
41
        pcilib_error("DMA Engine is not configured in the current model");
45
42
        return PCILIB_ERROR_NOTSUPPORTED;
46
43
    }
47
 
    
48
 
    for (i = 0; info->engines[i]; i++) {
49
 
        if ((info->engines[i]->addr == dma)&&((info->engines[i]->direction&direction)==direction)) break;
 
44
 
 
45
    for (i = 0; info->engines[i].addr_bits; i++) {
 
46
        if ((info->engines[i].addr == dma)&&((info->engines[i].direction&direction)==direction)) break;
50
47
    }
51
 
    
52
 
    if (info->engines[i]) return i;
 
48
 
 
49
    if (info->engines[i].addr_bits) return i;
53
50
    return PCILIB_DMA_ENGINE_INVALID;
54
51
}
55
52
 
56
 
int pcilib_set_dma_engine_description(pcilib_t *ctx, pcilib_dma_engine_t engine, pcilib_dma_engine_description_t *desc) {
57
 
    ctx->dma_info.engines[engine] = desc;
 
53
 
 
54
pcilib_dma_engine_t pcilib_add_dma_engine(pcilib_t *ctx, pcilib_dma_engine_description_t *desc) {
 
55
    pcilib_dma_engine_t engine = ctx->num_engines++;
 
56
    memcpy (&ctx->engines[engine], desc, sizeof(pcilib_dma_engine_description_t));
 
57
    return engine;
 
58
}
 
59
 
 
60
 
 
61
int pcilib_init_dma(pcilib_t *ctx) {
 
62
    int err;
 
63
    pcilib_dma_context_t *dma_ctx = NULL;
 
64
    const pcilib_model_description_t *model_info = pcilib_get_model_description(ctx);
 
65
 
 
66
    if (ctx->dma_ctx)
 
67
        return 0;
 
68
        
 
69
 
 
70
    if ((ctx->event_ctx)&&(model_info->api)&&(model_info->api->init_dma)) {
 
71
        err = pcilib_init_register_banks(ctx);
 
72
        if (err) {
 
73
            pcilib_error("Error (%i) while initializing register banks", err);
 
74
            return err;
 
75
        }
 
76
 
 
77
        dma_ctx = model_info->api->init_dma(ctx->event_ctx);
 
78
    } else if ((model_info->dma)&&(model_info->dma->api)&&(model_info->dma->api->init)) {
 
79
        const pcilib_dma_description_t *dma = model_info->dma;
 
80
        
 
81
        err = pcilib_init_register_banks(ctx);
 
82
        if (err) {
 
83
            pcilib_error("Error (%i) while initializing register banks", err);
 
84
            return err;
 
85
        }
 
86
 
 
87
        dma_ctx = dma->api->init(ctx, (dma->model?dma->model:ctx->model), dma->args);
 
88
    }
 
89
 
 
90
    if (dma_ctx) {
 
91
        dma_ctx->pcilib = ctx;
 
92
            // DS: parameters?
 
93
        ctx->dma_ctx = dma_ctx;
 
94
    }
58
95
 
59
96
    return 0;
60
97
}
61
98
 
62
99
int pcilib_start_dma(pcilib_t *ctx, pcilib_dma_engine_t dma, pcilib_dma_flags_t flags) {
63
 
    const pcilib_dma_info_t *info =  pcilib_get_dma_info(ctx);
 
100
    const pcilib_dma_description_t *info =  pcilib_get_dma_info(ctx);
64
101
    if (!info) {
65
102
        pcilib_error("DMA is not supported by the device");
66
103
        return PCILIB_ERROR_NOTSUPPORTED;
67
104
    }
68
105
 
69
 
    if (!ctx->model_info.dma_api) {
 
106
    if (!ctx->model_info.dma->api) {
70
107
        pcilib_error("DMA Engine is not configured in the current model");
71
108
        return PCILIB_ERROR_NOTAVAILABLE;
72
109
    }
73
110
    
74
 
    if (!ctx->model_info.dma_api->start_dma) {
 
111
    if (!ctx->model_info.dma->api->start_dma) {
75
112
        return 0;
76
113
    }
77
114
    
78
 
    return ctx->model_info.dma_api->start_dma(ctx->dma_ctx, dma, flags);
 
115
    return ctx->model_info.dma->api->start_dma(ctx->dma_ctx, dma, flags);
79
116
}
80
117
 
81
118
int pcilib_stop_dma(pcilib_t *ctx, pcilib_dma_engine_t dma, pcilib_dma_flags_t flags) {
82
 
    const pcilib_dma_info_t *info =  pcilib_get_dma_info(ctx);
 
119
    const pcilib_dma_description_t *info =  pcilib_get_dma_info(ctx);
83
120
 
84
121
    if (!info) {
85
122
        pcilib_error("DMA is not supported by the device");
86
123
        return PCILIB_ERROR_NOTSUPPORTED;
87
124
    }
88
125
 
89
 
    if (!ctx->model_info.dma_api) {
 
126
    if (!ctx->model_info.dma->api) {
90
127
        pcilib_error("DMA Engine is not configured in the current model");
91
128
        return PCILIB_ERROR_NOTAVAILABLE;
92
129
    }
93
130
    
94
 
    if (!ctx->model_info.dma_api->stop_dma) {
 
131
    if (!ctx->model_info.dma->api->stop_dma) {
95
132
        return 0;
96
133
    }
97
134
 
98
 
    return ctx->model_info.dma_api->stop_dma(ctx->dma_ctx, dma, flags);
 
135
    return ctx->model_info.dma->api->stop_dma(ctx->dma_ctx, dma, flags);
99
136
}
100
137
 
101
138
int pcilib_enable_irq(pcilib_t *ctx, pcilib_irq_type_t irq_type, pcilib_dma_flags_t flags) {
102
 
    const pcilib_dma_info_t *info =  pcilib_get_dma_info(ctx);
103
 
 
104
 
    if ((!info)||(!ctx->model_info.dma_api)||(!ctx->model_info.dma_api->enable_irq)) return 0;
105
 
 
106
 
    return ctx->model_info.dma_api->enable_irq(ctx->dma_ctx, irq_type, flags);
 
139
    const pcilib_dma_description_t *info =  pcilib_get_dma_info(ctx);
 
140
 
 
141
    if ((!info)||(!ctx->model_info.dma->api)||(!ctx->model_info.dma->api->enable_irq)) return 0;
 
142
 
 
143
    return ctx->model_info.dma->api->enable_irq(ctx->dma_ctx, irq_type, flags);
107
144
}
108
145
 
109
146
int pcilib_disable_irq(pcilib_t *ctx, pcilib_dma_flags_t flags) {
110
 
    const pcilib_dma_info_t *info =  pcilib_get_dma_info(ctx);
111
 
 
112
 
    if ((!info)||(!ctx->model_info.dma_api)||(!ctx->model_info.dma_api->disable_irq)) return 0;
113
 
 
114
 
    return ctx->model_info.dma_api->disable_irq(ctx->dma_ctx, flags);
 
147
    const pcilib_dma_description_t *info =  pcilib_get_dma_info(ctx);
 
148
 
 
149
    if ((!info)||(!ctx->model_info.dma->api)||(!ctx->model_info.dma->api->disable_irq)) return 0;
 
150
 
 
151
    return ctx->model_info.dma->api->disable_irq(ctx->dma_ctx, flags);
115
152
}
116
153
 
117
154
int pcilib_acknowledge_irq(pcilib_t *ctx, pcilib_irq_type_t irq_type, pcilib_irq_source_t irq_source) {
118
 
    const pcilib_dma_info_t *info =  pcilib_get_dma_info(ctx);
119
 
 
120
 
    if ((!info)||(!ctx->model_info.dma_api)||(!ctx->model_info.dma_api->acknowledge_irq)) return 0;
121
 
 
122
 
    return ctx->model_info.dma_api->acknowledge_irq(ctx->dma_ctx, irq_type, irq_source);
 
155
    const pcilib_dma_description_t *info =  pcilib_get_dma_info(ctx);
 
156
 
 
157
    if ((!info)||(!ctx->model_info.dma->api)||(!ctx->model_info.dma->api->acknowledge_irq)) return 0;
 
158
 
 
159
    return ctx->model_info.dma->api->acknowledge_irq(ctx->dma_ctx, irq_type, irq_source);
123
160
}
124
161
 
125
162
typedef struct {
126
163
    size_t size;
127
164
    void *data;
128
165
    size_t pos;
129
 
    
 
166
 
130
167
    pcilib_dma_flags_t flags;
131
168
} pcilib_dma_read_callback_context_t;
132
169
 
166
203
}
167
204
 
168
205
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) {
169
 
    const pcilib_dma_info_t *info =  pcilib_get_dma_info(ctx);
 
206
    const pcilib_dma_description_t *info =  pcilib_get_dma_info(ctx);
170
207
    if (!info) {
171
208
        pcilib_error("DMA is not supported by the device");
172
209
        return PCILIB_ERROR_NOTSUPPORTED;
173
210
    }
174
211
 
175
 
    if (!ctx->model_info.dma_api) {
 
212
    if (!ctx->model_info.dma->api) {
176
213
        pcilib_error("DMA Engine is not configured in the current model");
177
214
        return PCILIB_ERROR_NOTAVAILABLE;
178
215
    }
179
216
    
180
 
    if (!ctx->model_info.dma_api->stream) {
 
217
    if (!ctx->model_info.dma->api->stream) {
181
218
        pcilib_error("The DMA read is not supported by configured DMA engine");
182
219
        return PCILIB_ERROR_NOTSUPPORTED;
183
220
    }
184
 
    
185
 
    if (!info->engines[dma]) {
 
221
 
 
222
        // DS: We should check we are not going outside of allocated engine space
 
223
    if (!info->engines[dma].addr_bits) {
186
224
        pcilib_error("The DMA engine (%i) is not supported by device", dma);
187
225
        return PCILIB_ERROR_NOTAVAILABLE;
188
226
    }
189
227
 
190
 
    if ((info->engines[dma]->direction&PCILIB_DMA_FROM_DEVICE) == 0) {
 
228
    if ((info->engines[dma].direction&PCILIB_DMA_FROM_DEVICE) == 0) {
191
229
        pcilib_error("The selected engine (%i) is S2C-only and does not support reading", dma);
192
230
        return PCILIB_ERROR_NOTSUPPORTED;
193
231
    }
194
232
 
195
 
    return ctx->model_info.dma_api->stream(ctx->dma_ctx, dma, addr, size, flags, timeout, cb, cbattr);
 
233
    return ctx->model_info.dma->api->stream(ctx->dma_ctx, dma, addr, size, flags, timeout, cb, cbattr);
196
234
}
197
235
 
198
236
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) {
242
280
 
243
281
 
244
282
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) {
245
 
    const pcilib_dma_info_t *info =  pcilib_get_dma_info(ctx);
 
283
    const pcilib_dma_description_t *info =  pcilib_get_dma_info(ctx);
246
284
    if (!info) {
247
285
        pcilib_error("DMA is not supported by the device");
248
286
        return PCILIB_ERROR_NOTSUPPORTED;
249
287
    }
250
288
 
251
 
    if (!ctx->model_info.dma_api) {
 
289
    if (!ctx->model_info.dma->api) {
252
290
        pcilib_error("DMA Engine is not configured in the current model");
253
291
        return PCILIB_ERROR_NOTAVAILABLE;
254
292
    }
255
293
    
256
 
    if (!ctx->model_info.dma_api->push) {
 
294
    if (!ctx->model_info.dma->api->push) {
257
295
        pcilib_error("The DMA write is not supported by configured DMA engine");
258
296
        return PCILIB_ERROR_NOTSUPPORTED;
259
297
    }
260
298
    
261
 
    if (!info->engines[dma]) {
 
299
            // DS: We should check we don't exceed allocated engine range
 
300
    if (!info->engines[dma].addr_bits) {
262
301
        pcilib_error("The DMA engine (%i) is not supported by device", dma);
263
302
        return PCILIB_ERROR_NOTAVAILABLE;
264
303
    }
265
304
 
266
 
    if ((info->engines[dma]->direction&PCILIB_DMA_TO_DEVICE) == 0) {
 
305
    if ((info->engines[dma].direction&PCILIB_DMA_TO_DEVICE) == 0) {
267
306
        pcilib_error("The selected engine (%i) is C2S-only and does not support writes", dma);
268
307
        return PCILIB_ERROR_NOTSUPPORTED;
269
308
    }
270
309
    
271
 
    return ctx->model_info.dma_api->push(ctx->dma_ctx, dma, addr, size, flags, timeout, buf, written);
 
310
    return ctx->model_info.dma->api->push(ctx->dma_ctx, dma, addr, size, flags, timeout, buf, written);
272
311
}
273
312
 
274
313
 
277
316
}
278
317
 
279
318
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) {
280
 
    const pcilib_dma_info_t *info =  pcilib_get_dma_info(ctx);
 
319
    const pcilib_dma_description_t *info =  pcilib_get_dma_info(ctx);
281
320
    if (!info) {
282
321
        pcilib_error("DMA is not supported by the device");
283
322
        return 0;
284
323
    }
285
324
 
286
 
    if (!ctx->model_info.dma_api) {
 
325
    if (!ctx->model_info.dma->api) {
287
326
        pcilib_error("DMA Engine is not configured in the current model");
288
327
        return -1;
289
328
    }
290
329
    
291
 
    if (!ctx->model_info.dma_api->benchmark) {
 
330
    if (!ctx->model_info.dma->api->benchmark) {
292
331
        pcilib_error("The DMA benchmark is not supported by configured DMA engine");
293
332
        return -1;
294
 
   }
295
 
    
296
 
    if (!info->engines[dma]) {
297
 
        pcilib_error("The DMA engine (%i) is not supported by device", dma);
298
 
        return -1;
299
333
    }
300
334
 
301
 
    return ctx->model_info.dma_api->benchmark(ctx->dma_ctx, dma, addr, size, iterations, direction);
 
335
    return ctx->model_info.dma->api->benchmark(ctx->dma_ctx, dma, addr, size, iterations, direction);
302
336
}
303
337
 
304
338
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) {
305
 
    const pcilib_dma_info_t *info =  pcilib_get_dma_info(ctx);
 
339
    const pcilib_dma_description_t *info =  pcilib_get_dma_info(ctx);
306
340
    if (!info) {
307
341
        pcilib_error("DMA is not supported by the device");
308
342
        return 0;
309
343
    }
310
344
 
311
 
    if (!ctx->model_info.dma_api) {
 
345
    if (!ctx->model_info.dma->api) {
312
346
        pcilib_error("DMA Engine is not configured in the current model");
313
347
        return -1;
314
348
    }
315
349
    
316
 
    if (!ctx->model_info.dma_api->status) {
 
350
    if (!ctx->model_info.dma->api->status) {
317
351
        memset(status, 0, sizeof(pcilib_dma_engine_status_t));
318
352
        return -1;
319
353
   }
320
354
    
321
 
    if (!info->engines[dma]) {
 
355
        // DS: We should check we don't exceed allocated engine range
 
356
    if (!info->engines[dma].addr_bits) {
322
357
        pcilib_error("The DMA engine (%i) is not supported by device", dma);
323
358
        return -1;
324
359
    }
325
360
 
326
 
    return ctx->model_info.dma_api->status(ctx->dma_ctx, dma, status, n_buffers, buffers);
 
361
    return ctx->model_info.dma->api->status(ctx->dma_ctx, dma, status, n_buffers, buffers);
327
362
}