/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>
12
#include <errno.h>
13
#include <assert.h>
14
15
#include "error.h"
16
#include "pcilib.h"
17
#include "pci.h"
18
#include "dma.h"
19
20
const pcilib_dma_info_t *pcilib_get_dma_info(pcilib_t *ctx) {
21
    if (!ctx->dma_ctx) {
22
	pcilib_model_t model = pcilib_get_model(ctx);
23
	pcilib_dma_api_description_t *api = pcilib_model[model].dma_api;
24
	
25
	if ((api)&&(api->init)) {
26
	    pcilib_map_register_space(ctx);
27
	    ctx->dma_ctx = api->init(ctx);
28
	}
29
	
30
	if (!ctx->dma_ctx) return NULL;
31
    }
32
    
33
    return &ctx->dma_info;
34
}
35
49 by Suren A. Chilingaryan
A bit of renaming
36
pcilib_dma_engine_t pcilib_find_dma_by_addr(pcilib_t *ctx, pcilib_dma_direction_t direction, pcilib_dma_engine_addr_t dma) {
37
    pcilib_dma_engine_t i;
45 by root
North West Logick DMA implementation
38
39
    const pcilib_dma_info_t *info =  pcilib_get_dma_info(ctx);
40
    if (!info) {
41
	pcilib_error("DMA Engine is not configured in the current model");
42
	return PCILIB_ERROR_NOTSUPPORTED;
43
    }
44
    
45
    for (i = 0; info->engines[i]; i++) {
46
	if ((info->engines[i]->addr == dma)&&((info->engines[i]->direction&direction)==direction)) break;
47
    }
48
    
49
    if (info->engines[i]) return i;
50
    return PCILIB_DMA_INVALID;
51
}
52
49 by Suren A. Chilingaryan
A bit of renaming
53
int pcilib_set_dma_engine_description(pcilib_t *ctx, pcilib_dma_engine_t engine, pcilib_dma_engine_description_t *desc) {
45 by root
North West Logick DMA implementation
54
    ctx->dma_info.engines[engine] = desc;
55
}
56
57
typedef struct {
58
    size_t size;
59
    void *data;
60
    size_t pos;
61
} pcilib_dma_read_callback_context_t;
62
63
static int pcilib_dma_read_callback(void *arg, pcilib_dma_flags_t flags, size_t bufsize, void *buf) {
64
    pcilib_dma_read_callback_context_t *ctx = (pcilib_dma_read_callback_context_t*)arg;
65
    
66
    if (ctx->pos + bufsize > ctx->size) {
67
	pcilib_error("Buffer size (%li) is not large enough for DMA packet, at least %li bytes is required", ctx->size, ctx->pos + bufsize); 
68
	return PCILIB_ERROR_INVALID_DATA;
69
    }
70
    
71
    memcpy(ctx->data + ctx->pos, buf, bufsize);
72
    ctx->pos += bufsize;
73
74
    if (flags & PCILIB_DMA_FLAG_EOP) return 0;
75
    return 1;
76
}
77
78
static int pcilib_dma_skip_callback(void *arg, pcilib_dma_flags_t flags, size_t bufsize, void *buf) {
79
    return 1;
80
}
81
49 by Suren A. Chilingaryan
A bit of renaming
82
size_t pcilib_stream_dma(pcilib_t *ctx, pcilib_dma_engine_t dma, uintptr_t addr, size_t size, pcilib_dma_flags_t flags, size_t timeout, pcilib_dma_callback_t cb, void *cbattr) {
45 by root
North West Logick DMA implementation
83
    int err; 
84
85
    const pcilib_dma_info_t *info =  pcilib_get_dma_info(ctx);
86
    if (!info) {
87
	pcilib_error("DMA is not supported by the device");
88
	return 0;
89
    }
90
54 by Suren A. Chilingaryan
Support dynamic registers, support register offsets and multiregisters (bitmasks), list NWL DMA registers
91
    if (!ctx->model_info.dma_api) {
45 by root
North West Logick DMA implementation
92
	pcilib_error("DMA Engine is not configured in the current model");
93
	return 0;
94
    }
95
    
54 by Suren A. Chilingaryan
Support dynamic registers, support register offsets and multiregisters (bitmasks), list NWL DMA registers
96
    if (!ctx->model_info.dma_api->stream) {
45 by root
North West Logick DMA implementation
97
	pcilib_error("The DMA read is not supported by configured DMA engine");
98
	return 0;
99
    }
100
    
101
    if (!info->engines[dma]) {
102
	pcilib_error("The DMA engine (%i) is not supported by device", dma);
103
	return 0;
104
    }
105
106
    if (info->engines[dma]->direction&PCILIB_DMA_FROM_DEVICE == 0) {
107
	pcilib_error("The selected engine (%i) is S2C-only and does not support reading", dma);
108
	return 0;
109
    }
110
54 by Suren A. Chilingaryan
Support dynamic registers, support register offsets and multiregisters (bitmasks), list NWL DMA registers
111
    return ctx->model_info.dma_api->stream(ctx->dma_ctx, dma, addr, size, flags, timeout, cb, cbattr);
45 by root
North West Logick DMA implementation
112
}
113
49 by Suren A. Chilingaryan
A bit of renaming
114
size_t pcilib_read_dma(pcilib_t *ctx, pcilib_dma_engine_t dma, uintptr_t addr, size_t size, void *buf) {
45 by root
North West Logick DMA implementation
115
    int err; 
116
117
    pcilib_dma_read_callback_context_t opts = {
118
	size, buf, 0
119
    };
120
121
    return pcilib_stream_dma(ctx, dma, addr, size, PCILIB_DMA_FLAGS_DEFAULT, PCILIB_DMA_TIMEOUT, pcilib_dma_read_callback, &opts);
122
}
123
49 by Suren A. Chilingaryan
A bit of renaming
124
int pcilib_skip_dma(pcilib_t *ctx, pcilib_dma_engine_t dma) {
45 by root
North West Logick DMA implementation
125
    size_t skipped;
126
    do {
127
	    // IMMEDIATE timeout is not working properly, so default is set
128
	skipped = pcilib_stream_dma(ctx, dma, 0, 0, PCILIB_DMA_FLAGS_DEFAULT, PCILIB_DMA_TIMEOUT, pcilib_dma_skip_callback, NULL);
129
    } while (skipped > 0);
130
    
131
    return 0;
132
}
133
134
49 by Suren A. Chilingaryan
A bit of renaming
135
size_t pcilib_push_dma(pcilib_t *ctx, pcilib_dma_engine_t dma, uintptr_t addr, size_t size, pcilib_dma_flags_t flags, size_t timeout, void *buf) {
45 by root
North West Logick DMA implementation
136
    int err; 
137
138
    const pcilib_dma_info_t *info =  pcilib_get_dma_info(ctx);
139
    if (!info) {
140
	pcilib_error("DMA is not supported by the device");
141
	return 0;
142
    }
143
54 by Suren A. Chilingaryan
Support dynamic registers, support register offsets and multiregisters (bitmasks), list NWL DMA registers
144
    if (!ctx->model_info.dma_api) {
45 by root
North West Logick DMA implementation
145
	pcilib_error("DMA Engine is not configured in the current model");
146
	return 0;
147
    }
148
    
54 by Suren A. Chilingaryan
Support dynamic registers, support register offsets and multiregisters (bitmasks), list NWL DMA registers
149
    if (!ctx->model_info.dma_api->push) {
45 by root
North West Logick DMA implementation
150
	pcilib_error("The DMA write is not supported by configured DMA engine");
151
	return 0;
152
    }
153
    
154
    if (!info->engines[dma]) {
155
	pcilib_error("The DMA engine (%i) is not supported by device", dma);
156
	return 0;
157
    }
158
159
    if (info->engines[dma]->direction&PCILIB_DMA_TO_DEVICE == 0) {
160
	pcilib_error("The selected engine (%i) is C2S-only and does not support writes", dma);
161
	return 0;
162
    }
163
    
54 by Suren A. Chilingaryan
Support dynamic registers, support register offsets and multiregisters (bitmasks), list NWL DMA registers
164
    return ctx->model_info.dma_api->push(ctx->dma_ctx, dma, addr, size, flags, timeout, buf);
45 by root
North West Logick DMA implementation
165
}
166
167
49 by Suren A. Chilingaryan
A bit of renaming
168
size_t pcilib_write_dma(pcilib_t *ctx, pcilib_dma_engine_t dma, uintptr_t addr, size_t size, void *buf) {
45 by root
North West Logick DMA implementation
169
    return pcilib_push_dma(ctx, dma, addr, size, PCILIB_DMA_FLAG_EOP, PCILIB_DMA_TIMEOUT, buf);
170
}
171
49 by Suren A. Chilingaryan
A bit of renaming
172
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) {
45 by root
North West Logick DMA implementation
173
    int err; 
174
175
    const pcilib_dma_info_t *info =  pcilib_get_dma_info(ctx);
176
    if (!info) {
177
	pcilib_error("DMA is not supported by the device");
178
	return 0;
179
    }
180
54 by Suren A. Chilingaryan
Support dynamic registers, support register offsets and multiregisters (bitmasks), list NWL DMA registers
181
    if (!ctx->model_info.dma_api) {
45 by root
North West Logick DMA implementation
182
	pcilib_error("DMA Engine is not configured in the current model");
183
	return -1;
184
    }
185
    
54 by Suren A. Chilingaryan
Support dynamic registers, support register offsets and multiregisters (bitmasks), list NWL DMA registers
186
    if (!ctx->model_info.dma_api->benchmark) {
45 by root
North West Logick DMA implementation
187
	pcilib_error("The DMA benchmark is not supported by configured DMA engine");
188
	return -1;
189
   }
190
    
191
    if (!info->engines[dma]) {
192
	pcilib_error("The DMA engine (%i) is not supported by device", dma);
193
	return -1;
194
    }
195
54 by Suren A. Chilingaryan
Support dynamic registers, support register offsets and multiregisters (bitmasks), list NWL DMA registers
196
    return ctx->model_info.dma_api->benchmark(ctx->dma_ctx, dma, addr, size, iterations, direction);
45 by root
North West Logick DMA implementation
197
}