/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/nwl_engine_buffers.h

  • 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:
2
2
#define NWL_RING_SET(data, offset, val)  *(uint32_t*)(((char*)(data)) + (offset)) = (val)
3
3
#define NWL_RING_UPDATE(data, offset, mask, val) *(uint32_t*)(((char*)(data)) + (offset)) = ((*(uint32_t*)(((char*)(data)) + (offset)))&(mask))|(val)
4
4
 
5
 
static int dma_nwl_compute_read_s2c_pointers(nwl_dma_t *ctx, pcilib_nwl_engine_description_t *info, unsigned char *ring, uint32_t ring_pa) {
 
5
static int dma_nwl_compute_read_s2c_pointers(nwl_dma_t *ctx, pcilib_nwl_engine_context_t *ectx, unsigned char *ring, uint32_t ring_pa) {
6
6
    uint32_t val;
7
7
 
8
 
    char *base = info->base_addr;
 
8
    const char *base = ectx->base_addr;
9
9
    
10
10
    nwl_read_register(val, ctx, base, REG_SW_NEXT_BD);
11
11
    if ((val < ring_pa)||((val - ring_pa) % PCILIB_NWL_DMA_DESCRIPTOR_SIZE)) {
14
14
        return PCILIB_ERROR_INVALID_STATE;
15
15
    }
16
16
 
17
 
    info->head = (val - ring_pa) / PCILIB_NWL_DMA_DESCRIPTOR_SIZE;
18
 
    if (info->head >= PCILIB_NWL_DMA_PAGES) {
19
 
        pcilib_warning("Inconsistent S2C DMA Ring buffer is found (REG_SW_NEXT_BD register value (%zu) out of range)", info->head);
 
17
    ectx->head = (val - ring_pa) / PCILIB_NWL_DMA_DESCRIPTOR_SIZE;
 
18
    if (ectx->head >= PCILIB_NWL_DMA_PAGES) {
 
19
        pcilib_warning("Inconsistent S2C DMA Ring buffer is found (REG_SW_NEXT_BD register value (%zu) out of range)", ectx->head);
20
20
        return PCILIB_ERROR_INVALID_STATE;
21
21
    }
22
22
 
27
27
        return PCILIB_ERROR_INVALID_STATE;
28
28
    }
29
29
 
30
 
    info->tail = (val - ring_pa) / PCILIB_NWL_DMA_DESCRIPTOR_SIZE;
31
 
    if (info->tail >= PCILIB_NWL_DMA_PAGES) {
32
 
        pcilib_warning("Inconsistent S2C DMA Ring buffer is found (REG_DMA_ENG_NEXT_BD register value (%zu) out of range)", info->tail);
 
30
    ectx->tail = (val - ring_pa) / PCILIB_NWL_DMA_DESCRIPTOR_SIZE;
 
31
    if (ectx->tail >= PCILIB_NWL_DMA_PAGES) {
 
32
        pcilib_warning("Inconsistent S2C DMA Ring buffer is found (REG_DMA_ENG_NEXT_BD register value (%zu) out of range)", ectx->tail);
33
33
        return PCILIB_ERROR_INVALID_STATE;
34
34
    }
35
35
 
36
36
#ifdef DEBUG_NWL    
37
 
    printf("S2C: %lu %lu\n", info->tail, info->head);
 
37
    printf("S2C: %lu %lu\n", ectx->tail, ectx->head);
38
38
#endif /* DEBUG_NWL */
39
39
 
40
40
    return 0;
41
41
}
42
42
 
43
 
static int dma_nwl_compute_read_c2s_pointers(nwl_dma_t *ctx, pcilib_nwl_engine_description_t *info, unsigned char *ring, uint32_t ring_pa) {
 
43
static int dma_nwl_compute_read_c2s_pointers(nwl_dma_t *ctx, pcilib_nwl_engine_context_t *ectx, unsigned char *ring, uint32_t ring_pa) {
44
44
    uint32_t val;
45
45
 
46
 
    char *base = info->base_addr;
 
46
    const char *base = ectx->base_addr;
47
47
 
48
48
    nwl_read_register(val, ctx, base, REG_SW_NEXT_BD);
49
49
    if ((val < ring_pa)||((val - ring_pa) % PCILIB_NWL_DMA_DESCRIPTOR_SIZE)) {
52
52
        return PCILIB_ERROR_INVALID_STATE;
53
53
    }
54
54
 
55
 
    info->head = (val - ring_pa) / PCILIB_NWL_DMA_DESCRIPTOR_SIZE;
56
 
    if (info->head >= PCILIB_NWL_DMA_PAGES) {
57
 
        pcilib_warning("Inconsistent C2S DMA Ring buffer is found (REG_SW_NEXT_BD register value (%zu) out of range)", info->head);
 
55
    ectx->head = (val - ring_pa) / PCILIB_NWL_DMA_DESCRIPTOR_SIZE;
 
56
    if (ectx->head >= PCILIB_NWL_DMA_PAGES) {
 
57
        pcilib_warning("Inconsistent C2S DMA Ring buffer is found (REG_SW_NEXT_BD register value (%zu) out of range)", ectx->head);
58
58
        return PCILIB_ERROR_INVALID_STATE;
59
59
    }
60
60
    
61
 
    info->tail = info->head + 1;
62
 
    if (info->tail == PCILIB_NWL_DMA_PAGES) info->tail = 0;
 
61
    ectx->tail = ectx->head + 1;
 
62
    if (ectx->tail == PCILIB_NWL_DMA_PAGES) ectx->tail = 0;
63
63
 
64
64
#ifdef DEBUG_NWL    
65
 
    printf("C2S: %lu %lu\n", info->tail, info->head);
 
65
    printf("C2S: %lu %lu\n", ectx->tail, ectx->head);
66
66
#endif /* DEBUG_NWL */
67
67
 
68
68
    return 0;
69
69
}
70
70
 
71
71
 
72
 
static int dma_nwl_allocate_engine_buffers(nwl_dma_t *ctx, pcilib_nwl_engine_description_t *info) {
 
72
static int dma_nwl_allocate_engine_buffers(nwl_dma_t *ctx, pcilib_nwl_engine_context_t *ectx) {
73
73
    int err = 0;
74
74
 
75
75
    int i;
82
82
    pcilib_kmem_flags_t flags;
83
83
    pcilib_kmem_type_t type;
84
84
 
85
 
    char *base = info->base_addr;
 
85
    char *base = ectx->base_addr;
86
86
    
87
 
    if (info->pages) return 0;
 
87
    if (ectx->pages) return 0;
88
88
    
89
89
        // Or bidirectional specified by 0x0|addr, or read 0x0|addr and write 0x80|addr
90
 
    type = (info->desc.direction == PCILIB_DMA_TO_DEVICE)?PCILIB_KMEM_TYPE_DMA_S2C_PAGE:PCILIB_KMEM_TYPE_DMA_C2S_PAGE;
91
 
    sub_use = info->desc.addr|((info->desc.direction == PCILIB_DMA_TO_DEVICE)?0x80:0x00);
92
 
    flags = PCILIB_KMEM_FLAG_REUSE|PCILIB_KMEM_FLAG_EXCLUSIVE|PCILIB_KMEM_FLAG_HARDWARE|(info->preserve?PCILIB_KMEM_FLAG_PERSISTENT:0);
 
90
    type = (ectx->desc->direction == PCILIB_DMA_TO_DEVICE)?PCILIB_KMEM_TYPE_DMA_S2C_PAGE:PCILIB_KMEM_TYPE_DMA_C2S_PAGE;
 
91
    sub_use = ectx->desc->addr|((ectx->desc->direction == PCILIB_DMA_TO_DEVICE)?0x80:0x00);
 
92
    flags = PCILIB_KMEM_FLAG_REUSE|PCILIB_KMEM_FLAG_EXCLUSIVE|PCILIB_KMEM_FLAG_HARDWARE|(ectx->preserve?PCILIB_KMEM_FLAG_PERSISTENT:0);
93
93
    
94
 
    pcilib_kmem_handle_t *ring = pcilib_alloc_kernel_memory(ctx->pcilib, PCILIB_KMEM_TYPE_CONSISTENT, 1, PCILIB_NWL_DMA_PAGES * PCILIB_NWL_DMA_DESCRIPTOR_SIZE, PCILIB_NWL_ALIGNMENT, PCILIB_KMEM_USE(PCILIB_KMEM_USE_DMA_RING, sub_use), flags);
95
 
    pcilib_kmem_handle_t *pages = pcilib_alloc_kernel_memory(ctx->pcilib, type, PCILIB_NWL_DMA_PAGES, 0, 0, PCILIB_KMEM_USE(PCILIB_KMEM_USE_DMA_PAGES, sub_use), flags);
 
94
    pcilib_kmem_handle_t *ring = pcilib_alloc_kernel_memory(ctx->dmactx.pcilib, PCILIB_KMEM_TYPE_CONSISTENT, 1, PCILIB_NWL_DMA_PAGES * PCILIB_NWL_DMA_DESCRIPTOR_SIZE, PCILIB_NWL_ALIGNMENT, PCILIB_KMEM_USE(PCILIB_KMEM_USE_DMA_RING, sub_use), flags);
 
95
    pcilib_kmem_handle_t *pages = pcilib_alloc_kernel_memory(ctx->dmactx.pcilib, type, PCILIB_NWL_DMA_PAGES, 0, 0, PCILIB_KMEM_USE(PCILIB_KMEM_USE_DMA_PAGES, sub_use), flags);
96
96
 
97
97
    if (!ring||!pages) {
98
 
        if (pages) pcilib_free_kernel_memory(ctx->pcilib, pages, 0);
99
 
        if (ring) pcilib_free_kernel_memory(ctx->pcilib, ring, 0);
 
98
        if (pages) pcilib_free_kernel_memory(ctx->dmactx.pcilib, pages, 0);
 
99
        if (ring) pcilib_free_kernel_memory(ctx->dmactx.pcilib, ring, 0);
100
100
        return PCILIB_ERROR_MEMORY;
101
101
    }
102
102
 
103
 
    reuse_ring = pcilib_kmem_is_reused(ctx->pcilib, ring);
104
 
    reuse_pages = pcilib_kmem_is_reused(ctx->pcilib, pages);
 
103
    reuse_ring = pcilib_kmem_is_reused(ctx->dmactx.pcilib, ring);
 
104
    reuse_pages = pcilib_kmem_is_reused(ctx->dmactx.pcilib, pages);
105
105
 
106
106
//      I guess idea here was that we not need to check all that stuff during the second iteration
107
107
//      which is basicaly true (shall we expect any driver-triggered changes or parallel accesses?)
108
108
//      but still we need to set preserve flag (and that if we enforcing preservation --start-dma). 
109
109
//      Probably having checks anyway is not harming...
110
 
//    if (!info->preserve) {
 
110
//    if (!ectx->preserve) {
111
111
        if (reuse_ring == reuse_pages) {
112
112
            if (reuse_ring & PCILIB_KMEM_REUSE_PARTIAL) pcilib_warning("Inconsistent DMA buffers are found (only part of required buffers is available), reinitializing...");
113
113
            else if (reuse_ring & PCILIB_KMEM_REUSE_REUSED) {
114
114
                if ((reuse_ring & PCILIB_KMEM_REUSE_PERSISTENT) == 0) pcilib_warning("Lost DMA buffers are found (non-persistent mode), reinitializing...");
115
115
                else if ((reuse_ring & PCILIB_KMEM_REUSE_HARDWARE) == 0) pcilib_warning("Lost DMA buffers are found (missing HW reference), reinitializing...");
116
116
                else {
117
 
                    nwl_read_register(val, ctx, info->base_addr, REG_DMA_ENG_CTRL_STATUS);
 
117
                    nwl_read_register(val, ctx, ectx->base_addr, REG_DMA_ENG_CTRL_STATUS);
118
118
 
119
119
                    if ((val&DMA_ENG_RUNNING) == 0) pcilib_warning("Lost DMA buffers are found (DMA engine is stopped), reinitializing...");
120
120
                    else preserve = 1;
124
124
//    }
125
125
 
126
126
    
127
 
    unsigned char *data = (unsigned char*)pcilib_kmem_get_ua(ctx->pcilib, ring);
128
 
    uint32_t ring_pa = pcilib_kmem_get_pa(ctx->pcilib, ring);
 
127
    unsigned char *data = (unsigned char*)pcilib_kmem_get_ua(ctx->dmactx.pcilib, ring);
 
128
    uint32_t ring_pa = pcilib_kmem_get_pa(ctx->dmactx.pcilib, ring);
129
129
 
130
130
    if (preserve) {
131
 
        if (info->desc.direction == PCILIB_DMA_FROM_DEVICE) err = dma_nwl_compute_read_c2s_pointers(ctx, info, data, ring_pa);
132
 
        else err = dma_nwl_compute_read_s2c_pointers(ctx, info, data, ring_pa);
 
131
        if (ectx->desc->direction == PCILIB_DMA_FROM_DEVICE) err = dma_nwl_compute_read_c2s_pointers(ctx, ectx, data, ring_pa);
 
132
        else err = dma_nwl_compute_read_s2c_pointers(ctx, ectx, data, ring_pa);
133
133
 
134
134
        if (err) preserve = 0;
135
135
    }
136
136
    
137
137
    if (preserve) {
138
 
        info->reused = 1;
139
 
        buf_sz = pcilib_kmem_get_block_size(ctx->pcilib, pages, 0);
 
138
        ectx->reused = 1;
 
139
        buf_sz = pcilib_kmem_get_block_size(ctx->dmactx.pcilib, pages, 0);
140
140
    } else {
141
 
        info->reused = 0;
 
141
        ectx->reused = 0;
142
142
        
143
143
        memset(data, 0, PCILIB_NWL_DMA_PAGES * PCILIB_NWL_DMA_DESCRIPTOR_SIZE);
144
144
 
145
145
        for (i = 0; i < PCILIB_NWL_DMA_PAGES; i++, data += PCILIB_NWL_DMA_DESCRIPTOR_SIZE) {
146
 
            buf_pa = pcilib_kmem_get_block_pa(ctx->pcilib, pages, i);
147
 
            buf_sz = pcilib_kmem_get_block_size(ctx->pcilib, pages, i);
 
146
            buf_pa = pcilib_kmem_get_block_pa(ctx->dmactx.pcilib, pages, i);
 
147
            buf_sz = pcilib_kmem_get_block_size(ctx->dmactx.pcilib, pages, i);
148
148
 
149
149
            NWL_RING_SET(data, DMA_BD_NDESC_OFFSET, ring_pa + ((i + 1) % PCILIB_NWL_DMA_PAGES) * PCILIB_NWL_DMA_DESCRIPTOR_SIZE);
150
150
            NWL_RING_SET(data, DMA_BD_BUFAL_OFFSET, buf_pa&0xFFFFFFFF);
160
160
        nwl_write_register(val, ctx, base, REG_DMA_ENG_NEXT_BD);
161
161
        nwl_write_register(val, ctx, base, REG_SW_NEXT_BD);
162
162
 
163
 
        info->head = 0;
164
 
        info->tail = 0;
 
163
        ectx->head = 0;
 
164
        ectx->tail = 0;
165
165
    }
166
166
    
167
 
    info->ring = ring;
168
 
    info->pages = pages;
169
 
    info->page_size = buf_sz;
170
 
    info->ring_size = PCILIB_NWL_DMA_PAGES;
 
167
    ectx->ring = ring;
 
168
    ectx->pages = pages;
 
169
    ectx->page_size = buf_sz;
 
170
    ectx->ring_size = PCILIB_NWL_DMA_PAGES;
171
171
    
172
172
    return 0;
173
173
}
174
174
 
175
175
 
176
 
static size_t dma_nwl_clean_buffers(nwl_dma_t * ctx, pcilib_nwl_engine_description_t *info) {
 
176
static size_t dma_nwl_clean_buffers(nwl_dma_t * ctx, pcilib_nwl_engine_context_t *ectx) {
177
177
    size_t res = 0;
178
178
    uint32_t status;
179
179
 
180
 
    unsigned char *ring = pcilib_kmem_get_ua(ctx->pcilib, info->ring);
181
 
    ring += info->tail * PCILIB_NWL_DMA_DESCRIPTOR_SIZE;
 
180
    unsigned char *ring = pcilib_kmem_get_ua(ctx->dmactx.pcilib, ectx->ring);
 
181
    ring += ectx->tail * PCILIB_NWL_DMA_DESCRIPTOR_SIZE;
182
182
 
183
183
next_buffer:
184
184
    status = NWL_RING_GET(ring, DMA_BD_BUFL_STATUS_OFFSET)&DMA_BD_STATUS_MASK;
195
195
    }
196
196
        
197
197
    if (status & DMA_BD_COMP_MASK) {
198
 
        info->tail++;
199
 
        if (info->tail == info->ring_size) {
200
 
            ring -= (info->tail - 1) * PCILIB_NWL_DMA_DESCRIPTOR_SIZE;
201
 
            info->tail = 0;
 
198
        ectx->tail++;
 
199
        if (ectx->tail == ectx->ring_size) {
 
200
            ring -= (ectx->tail - 1) * PCILIB_NWL_DMA_DESCRIPTOR_SIZE;
 
201
            ectx->tail = 0;
202
202
        } else {
203
203
            ring += PCILIB_NWL_DMA_DESCRIPTOR_SIZE;
204
204
        }
205
205
        
206
206
        res++;
207
207
 
208
 
        if (info->tail != info->head) goto next_buffer;
 
208
        if (ectx->tail != ectx->head) goto next_buffer;
209
209
    }
210
210
    
211
211
//    printf("====> Cleaned: %i\n", res);
213
213
}
214
214
 
215
215
 
216
 
static size_t dma_nwl_get_next_buffer(nwl_dma_t * ctx, pcilib_nwl_engine_description_t *info, size_t n_buffers, pcilib_timeout_t timeout) {
 
216
static size_t dma_nwl_get_next_buffer(nwl_dma_t * ctx, pcilib_nwl_engine_context_t *ectx, size_t n_buffers, pcilib_timeout_t timeout) {
217
217
    struct timeval start, cur;
218
218
 
219
219
    size_t res, n = 0;
220
220
    size_t head;
221
221
 
222
 
    for (head = info->head; (((head + 1)%info->ring_size) != info->tail)&&(n < n_buffers); head++, n++);
223
 
    if (n == n_buffers) return info->head;
 
222
    for (head = ectx->head; (((head + 1)%ectx->ring_size) != ectx->tail)&&(n < n_buffers); head++, n++);
 
223
    if (n == n_buffers) return ectx->head;
224
224
 
225
225
    gettimeofday(&start, NULL);
226
226
 
227
 
    res = dma_nwl_clean_buffers(ctx, info);
 
227
    res = dma_nwl_clean_buffers(ctx, ectx);
228
228
    if (res == (size_t)-1) return PCILIB_DMA_BUFFER_INVALID;
229
229
    else n += res;
230
230
 
237
237
        
238
238
        usleep (10);    
239
239
 
240
 
        res = dma_nwl_clean_buffers(ctx, info);
 
240
        res = dma_nwl_clean_buffers(ctx, ectx);
241
241
        if (res == (size_t)-1) return PCILIB_DMA_BUFFER_INVALID;
242
242
        else if (res > 0) {
243
243
            gettimeofday(&start, NULL);
247
247
 
248
248
    if (n < n_buffers) return PCILIB_DMA_BUFFER_INVALID;
249
249
    
250
 
    return info->head;
 
250
    return ectx->head;
251
251
}
252
252
 
253
 
static int dma_nwl_push_buffer(nwl_dma_t *ctx, pcilib_nwl_engine_description_t *info, size_t size, int eop, pcilib_timeout_t timeout) {
 
253
static int dma_nwl_push_buffer(nwl_dma_t *ctx, pcilib_nwl_engine_context_t *ectx, size_t size, int eop, pcilib_timeout_t timeout) {
254
254
    int flags = 0;
255
255
    
256
256
    uint32_t val;
257
 
    unsigned char *ring = pcilib_kmem_get_ua(ctx->pcilib, info->ring);
258
 
    uint32_t ring_pa = pcilib_kmem_get_pa(ctx->pcilib, info->ring);
 
257
    unsigned char *ring = pcilib_kmem_get_ua(ctx->dmactx.pcilib, ectx->ring);
 
258
    uint32_t ring_pa = pcilib_kmem_get_pa(ctx->dmactx.pcilib, ectx->ring);
259
259
 
260
 
    ring += info->head * PCILIB_NWL_DMA_DESCRIPTOR_SIZE;
 
260
    ring += ectx->head * PCILIB_NWL_DMA_DESCRIPTOR_SIZE;
261
261
 
262
262
    
263
 
    if (!info->writting) {
 
263
    if (!ectx->writting) {
264
264
        flags |= DMA_BD_SOP_MASK;
265
 
        info->writting = 1;
 
265
        ectx->writting = 1;
266
266
    }
267
267
    if (eop) {
268
268
        flags |= DMA_BD_EOP_MASK;
269
 
        info->writting = 0;
 
269
        ectx->writting = 0;
270
270
    }
271
271
    
272
272
    NWL_RING_SET(ring, DMA_BD_BUFL_CTRL_OFFSET, size|flags);
273
273
    NWL_RING_SET(ring, DMA_BD_BUFL_STATUS_OFFSET, size);
274
274
 
275
 
    info->head++;
276
 
    if (info->head == info->ring_size) info->head = 0;
 
275
    ectx->head++;
 
276
    if (ectx->head == ectx->ring_size) ectx->head = 0;
277
277
    
278
 
    val = ring_pa + info->head * PCILIB_NWL_DMA_DESCRIPTOR_SIZE;
279
 
    nwl_write_register(val, ctx, info->base_addr, REG_SW_NEXT_BD);
 
278
    val = ring_pa + ectx->head * PCILIB_NWL_DMA_DESCRIPTOR_SIZE;
 
279
    nwl_write_register(val, ctx, ectx->base_addr, REG_SW_NEXT_BD);
280
280
    
281
281
    return 0;
282
282
}
283
283
 
284
284
 
285
 
static size_t dma_nwl_wait_buffer(nwl_dma_t *ctx, pcilib_nwl_engine_description_t *info, size_t *size, int *eop, pcilib_timeout_t timeout) {
 
285
static size_t dma_nwl_wait_buffer(nwl_dma_t *ctx, pcilib_nwl_engine_context_t *ectx, size_t *size, int *eop, pcilib_timeout_t timeout) {
286
286
    struct timeval start, cur;
287
287
    uint32_t status_size, status;
288
288
 
289
 
    unsigned char *ring = pcilib_kmem_get_ua(ctx->pcilib, info->ring);
 
289
    unsigned char *ring = pcilib_kmem_get_ua(ctx->dmactx.pcilib, ectx->ring);
290
290
    
291
 
    ring += info->tail * PCILIB_NWL_DMA_DESCRIPTOR_SIZE;
 
291
    ring += ectx->tail * PCILIB_NWL_DMA_DESCRIPTOR_SIZE;
292
292
 
293
293
    gettimeofday(&start, NULL);
294
294
    
309
309
 
310
310
/*          
311
311
            if (mrd) {
312
 
                if ((info->tail + 1) == info->ring_size) ring -= info->tail * PCILIB_NWL_DMA_DESCRIPTOR_SIZE;
 
312
                if ((ectx->tail + 1) == ectx->ring_size) ring -= ectx->tail * PCILIB_NWL_DMA_DESCRIPTOR_SIZE;
313
313
                else ring += PCILIB_NWL_DMA_DESCRIPTOR_SIZE;
314
314
                *mrd = NWL_RING_GET(ring, DMA_BD_BUFL_STATUS_OFFSET)&DMA_BD_COMP_MASK;
315
315
            }
316
316
*/
317
317
        
318
 
            return info->tail;
 
318
            return ectx->tail;
319
319
        }
320
320
        
321
321
        usleep(10);
327
327
 
328
328
/*
329
329
    // This function is not used now, but we may need it in the future
330
 
static int dma_nwl_is_overflown(nwl_dma_t *ctx, pcilib_nwl_engine_description_t *info) {
 
330
static int dma_nwl_is_overflown(nwl_dma_t *ctx, pcilib_nwl_engine_context_t *ectx) {
331
331
    uint32_t status;
332
 
    unsigned char *ring = pcilib_kmem_get_ua(ctx->pcilib, info->ring);
333
 
    if (info->tail > 0) ring += (info->tail - 1) * PCILIB_NWL_DMA_DESCRIPTOR_SIZE;
334
 
    else ring += (info->ring_size - 1) * PCILIB_NWL_DMA_DESCRIPTOR_SIZE;
 
332
    unsigned char *ring = pcilib_kmem_get_ua(ctx->dmactx.pcilib, ectx->ring);
 
333
    if (ectx->tail > 0) ring += (ectx->tail - 1) * PCILIB_NWL_DMA_DESCRIPTOR_SIZE;
 
334
    else ring += (ectx->ring_size - 1) * PCILIB_NWL_DMA_DESCRIPTOR_SIZE;
335
335
 
336
336
    status = NWL_RING_GET(ring, DMA_BD_BUFL_STATUS_OFFSET);
337
337
    return status&DMA_BD_COMP_MASK?1:0;
338
338
}
339
339
*/
340
340
 
341
 
static int dma_nwl_return_buffer(nwl_dma_t *ctx, pcilib_nwl_engine_description_t *info) {
 
341
static int dma_nwl_return_buffer(nwl_dma_t *ctx, pcilib_nwl_engine_context_t *ectx) {
342
342
    uint32_t val;
343
343
 
344
 
    unsigned char *ring = pcilib_kmem_get_ua(ctx->pcilib, info->ring);
345
 
    uint32_t ring_pa = pcilib_kmem_get_pa(ctx->pcilib, info->ring);
346
 
    size_t bufsz = pcilib_kmem_get_block_size(ctx->pcilib, info->pages, info->tail);
 
344
    unsigned char *ring = pcilib_kmem_get_ua(ctx->dmactx.pcilib, ectx->ring);
 
345
    uint32_t ring_pa = pcilib_kmem_get_pa(ctx->dmactx.pcilib, ectx->ring);
 
346
    size_t bufsz = pcilib_kmem_get_block_size(ctx->dmactx.pcilib, ectx->pages, ectx->tail);
347
347
 
348
 
    ring += info->tail * PCILIB_NWL_DMA_DESCRIPTOR_SIZE;
 
348
    ring += ectx->tail * PCILIB_NWL_DMA_DESCRIPTOR_SIZE;
349
349
 
350
350
#ifdef NWL_GENERATE_DMA_IRQ    
351
351
    NWL_RING_SET(ring, DMA_BD_BUFL_CTRL_OFFSET, bufsz | DMA_BD_INT_ERROR_MASK | DMA_BD_INT_COMP_MASK);
355
355
 
356
356
    NWL_RING_SET(ring, DMA_BD_BUFL_STATUS_OFFSET, 0);
357
357
 
358
 
    val = ring_pa + info->tail * PCILIB_NWL_DMA_DESCRIPTOR_SIZE;
359
 
    nwl_write_register(val, ctx, info->base_addr, REG_SW_NEXT_BD);
 
358
    val = ring_pa + ectx->tail * PCILIB_NWL_DMA_DESCRIPTOR_SIZE;
 
359
    nwl_write_register(val, ctx, ectx->base_addr, REG_SW_NEXT_BD);
360
360
    
361
 
    info->tail++;
362
 
    if (info->tail == info->ring_size) info->tail = 0;
 
361
    ectx->tail++;
 
362
    if (ectx->tail == ectx->ring_size) ectx->tail = 0;
363
363
    
364
364
    return 0;
365
365
}
368
368
    size_t i;
369
369
    uint32_t bstatus;
370
370
    nwl_dma_t *ctx = (nwl_dma_t*)vctx;
371
 
    pcilib_nwl_engine_description_t *info = ctx->engines + dma;
372
 
    unsigned char *ring = (unsigned char*)pcilib_kmem_get_ua(ctx->pcilib, info->ring);
 
371
    pcilib_nwl_engine_context_t *ectx = ctx->engines + dma;
 
372
    unsigned char *ring = (unsigned char*)pcilib_kmem_get_ua(ctx->dmactx.pcilib, ectx->ring);
373
373
 
374
374
 
375
375
    if (!status) return -1;
376
376
    
377
 
    status->started = info->started;
378
 
    status->ring_size = info->ring_size;
379
 
    status->buffer_size = info->page_size;
380
 
    status->ring_tail = info->tail;
 
377
    status->started = ectx->started;
 
378
    status->ring_size = ectx->ring_size;
 
379
    status->buffer_size = ectx->page_size;
 
380
    status->ring_tail = ectx->tail;
381
381
    
382
 
    if (info->desc.direction == PCILIB_DMA_FROM_DEVICE) {
 
382
    if (ectx->desc->direction == PCILIB_DMA_FROM_DEVICE) {
383
383
        size_t pos = 0;
384
 
        for (i = 0; i < info->ring_size; i++) {
 
384
        for (i = 0; i < ectx->ring_size; i++) {
385
385
            pos = status->ring_tail + i;
386
 
            if (pos >= info->ring_size) pos -= info->ring_size;
 
386
            if (pos >= ectx->ring_size) pos -= ectx->ring_size;
387
387
 
388
388
            bstatus = NWL_RING_GET(ring + pos * PCILIB_NWL_DMA_DESCRIPTOR_SIZE, DMA_BD_BUFL_STATUS_OFFSET);
389
389
            if ((bstatus&(DMA_BD_ERROR_MASK|DMA_BD_COMP_MASK)) == 0) break;
390
390
        }
391
391
        status->ring_head = pos;
392
392
    } else {
393
 
        status->ring_head = info->head;
 
393
        status->ring_head = ectx->head;
394
394
    }
395
395
 
396
396
 
397
397
    if (buffers) {      
398
 
        for (i = 0; (i < info->ring_size)&&(i < n_buffers); i++) {
 
398
        for (i = 0; (i < ectx->ring_size)&&(i < n_buffers); i++) {
399
399
            bstatus = NWL_RING_GET(ring, DMA_BD_BUFL_STATUS_OFFSET);
400
400
 
401
401
            buffers[i].error = bstatus & (DMA_BD_ERROR_MASK/*|DMA_BD_SHORT_MASK*/);