OpenCores
URL https://opencores.org/ocsvn/pcie_ds_dma/pcie_ds_dma/trunk

Subversion Repositories pcie_ds_dma

[/] [pcie_ds_dma/] [trunk/] [soft/] [linux/] [driver/] [pexdrv/] [dmachan.c] - Blame information for rev 2

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 dsmv
 
2
#include <linux/kernel.h>
3
#define __NO_VERSION__
4
#include <linux/module.h>
5
#include <linux/types.h>
6
#include <linux/ioport.h>
7
#include <linux/pci.h>
8
#include <linux/interrupt.h>
9
#include <linux/pagemap.h>
10
#include <linux/interrupt.h>
11
#include <linux/proc_fs.h>
12
#include <asm/io.h>
13
 
14
#ifndef _EVENT_H_
15
#include "event.h"
16
#endif
17
#ifndef  _DMA_CHAN_H_
18
#include "dmachan.h"
19
#endif
20
#ifndef  _HARDWARE_H_
21
#include "hardware.h"
22
#endif
23
 
24
//-----------------------------------------------------------------------------
25
 
26
struct CDmaChannel* CDmaChannelCreate(  u32 NumberOfChannel,
27
        void *brd,
28
        struct device   *dev,
29
        u32 cbMaxTransferLength,
30
        u16 idBlockFifo,
31
        int bScatterGather )
32
{
33
    struct CDmaChannel *dma = NULL;
34
 
35
    dma = kzalloc(sizeof(struct CDmaChannel), GFP_KERNEL);
36
    if(!dma) {
37
        printk("<0>%s(): Error allocate memory for CDmaChannel object\n", __FUNCTION__);
38
        return NULL;
39
    }
40
 
41
    dma->m_NumberOfChannel = NumberOfChannel;
42
    dma->m_Board = brd;
43
    dma->m_dev = dev;
44
    dma->m_UseCount = 0;
45
    dma->m_DpcForIsr = DmaDpcForIsr;
46
    dma->m_idBlockFifo = idBlockFifo;
47
 
48
    spin_lock_init( &dma->m_DmaLock );
49
    init_waitqueue_head( &dma->m_DmaWq );
50
    tasklet_init( &dma->m_Dpc, dma->m_DpcForIsr, (unsigned long)dma );
51
    InitKevent( &dma->m_BlockEndEvent );
52
    InitKevent( &dma->m_BufferEndEvent );
53
 
54
    //printk("<0>%s(%d): COMPLETE.\n", __FUNCTION__, dma->m_NumberOfChannel);
55
 
56
    return dma;
57
}
58
 
59
//-----------------------------------------------------------------------------
60
 
61
void CDmaChannelDelete(struct CDmaChannel *dma)
62
{
63
    //printk("<0>%s()\n", __FUNCTION__);
64
    if (dma) {
65
        tasklet_kill( &dma->m_Dpc );
66
        kfree(dma);
67
    }
68
}
69
 
70
//-----------------------------------------------------------------------------
71
 
72
int RequestMemory(struct CDmaChannel *dma, void** ppVirtAddr, u32 size, u32 *pCount, void** pStub, u32 bMemType)
73
{
74
    int Status = -ENOMEM;
75
 
76
    //printk("<0>%s(): Channel = %d\n", __FUNCTION__, dma->m_NumberOfChannel);
77
 
78
    // при первом обращении действительно выделяем память,
79
    // а при повторных только отображаем выделенную память на пользовательское пространство
80
    if(!dma->m_UseCount)
81
    {
82
        dma->m_MemType = bMemType;
83
        dma->m_BlockCount = *pCount;
84
        dma->m_BlockSize = size;
85
 
86
        // выделяем память под описатели блоков (системный, и логический адрес для каждого блока)
87
        dma->m_pBufDscr.SystemAddress = (void*)dma_alloc_coherent( dma->m_dev,
88
                                                                   dma->m_BlockCount * sizeof(SHARED_MEMORY_DESCRIPTION),
89
                                                                   &dma->m_pBufDscr.LogicalAddress, GFP_KERNEL);
90
        if(!dma->m_pBufDscr.SystemAddress)
91
        {
92
            printk("<0>%s(): Not memory for buffer descriptions\n", __FUNCTION__);
93
            return -ENOMEM;
94
        }
95
 
96
        dma->m_ScatterGatherTableEntryCnt = 0;
97
    }
98
 
99
    Status = RequestStub(dma, pStub);
100
    if(Status == 0)
101
    {
102
        if(dma->m_MemType == SYSTEM_MEMORY_TYPE) {
103
            Status = RequestSysBuf(dma, ppVirtAddr);
104
        } else {
105
            ReleaseStub(dma);
106
            dma_free_coherent(dma->m_dev,
107
                              dma->m_BlockCount * sizeof(SHARED_MEMORY_DESCRIPTION),
108
                              dma->m_pBufDscr.SystemAddress,
109
                              dma->m_pBufDscr.LogicalAddress);
110
            dma->m_pBufDscr.SystemAddress = NULL;
111
            dma->m_pBufDscr.LogicalAddress = 0;
112
            printk("<0>%s(): Invalid memory type for DMA data blocks\n", __FUNCTION__);
113
            return -EINVAL;
114
        }
115
 
116
        if(Status == 0)
117
        {
118
            if(!dma->m_UseCount)
119
            {
120
                //printk("<0>%s(): Scatter/Gather Table Entry is %d\n", __FUNCTION__, dma->m_ScatterGatherTableEntryCnt);
121
                if(dma->m_idBlockFifo == PE_EXT_FIFO_ID)
122
                    SetScatterGatherListExt(dma);
123
                else {
124
                    printk("<0>%s(): Scatter/Gather Table Entry not created\n", __FUNCTION__);
125
                    //SetScatterGatherList(dma);
126
                }
127
                *pCount = dma->m_BlockCount;
128
                dma->m_pStub = (PAMB_STUB)dma->m_StubDscr.SystemAddress;
129
                dma->m_pStub->lastBlock = -1;
130
                dma->m_pStub->totalCounter = 0;
131
                dma->m_pStub->offset = 0;
132
                dma->m_pStub->state = STATE_STOP;
133
            }
134
            dma->m_UseCount++;
135
        }
136
        else
137
        {
138
            ReleaseStub(dma);
139
            dma_free_coherent(dma->m_dev, dma->m_BlockCount * sizeof(SHARED_MEMORY_DESCRIPTION),
140
                              dma->m_pBufDscr.SystemAddress, dma->m_pBufDscr.LogicalAddress);
141
            dma->m_pBufDscr.SystemAddress = NULL;
142
            dma->m_pBufDscr.LogicalAddress = 0;
143
            printk("<0>%s(): Error allocate memory\n", __FUNCTION__);
144
            return -EINVAL;
145
        }
146
    }
147
    else
148
{
149
    if(!dma->m_UseCount)        {
150
        dma_free_coherent(dma->m_dev,
151
                          dma->m_BlockCount * sizeof(SHARED_MEMORY_DESCRIPTION),
152
                          dma->m_pBufDscr.SystemAddress, dma->m_pBufDscr.LogicalAddress);
153
        dma->m_pBufDscr.SystemAddress = NULL;
154
        dma->m_pBufDscr.LogicalAddress = 0;
155
    }
156
}
157
return Status;
158
}
159
 
160
//-----------------------------------------------------------------------------
161
 
162
void ReleaseMemory(struct CDmaChannel *dma)
163
{
164
    //printk("<0>%s(): Entered. Channel = %d\n", __FUNCTION__, dma->m_NumberOfChannel);
165
 
166
    if(!dma->m_UseCount) {
167
        printk("<0> %s: Memory not allocated.\n", __FUNCTION__);
168
        return;
169
    }
170
 
171
    ReleaseStub( dma );
172
    ReleaseSGList( dma );
173
    ReleaseSysBuf( dma );
174
 
175
    dma_free_coherent(dma->m_dev,
176
                      dma->m_BlockCount * sizeof(SHARED_MEMORY_DESCRIPTION),
177
                      dma->m_pBufDscr.SystemAddress, dma->m_pBufDscr.LogicalAddress);
178
 
179
    dma->m_pBufDscr.SystemAddress = NULL;
180
    dma->m_pBufDscr.LogicalAddress = 0;
181
    dma->m_UseCount--;
182
}
183
 
184
//-----------------------------------------------------------------------------
185
 
186
int SetScatterGatherListExt(struct CDmaChannel *dma)
187
{
188
    int Status = 0;
189
    u32 iBlock = 0;
190
    //u32 ii = 0;
191
    u32 iEntry = 0;
192
    u32 iBlkEntry = 0;
193
    u64 *pDscrBuf = NULL;
194
    u16* pNextDscr = NULL;
195
    u32 DscrSize = 0;
196
    SHARED_MEMORY_DESCRIPTION *pMemDscr = (SHARED_MEMORY_DESCRIPTION*)dma->m_pBufDscr.SystemAddress;
197
    DMA_CHAINING_DESCR_EXT      *pSGTEx = NULL;
198
 
199
    //printk("<0>%s()\n", __FUNCTION__);
200
 
201
    Status = RequestSGList(dma);
202
    if(Status < 0)
203
        return Status;
204
 
205
    //получим адрес таблицы для хранения цепочек DMA
206
    dma->m_pScatterGatherTableExt = (DMA_CHAINING_DESCR_EXT*)dma->m_SGTableDscr.SystemAddress;
207
    pSGTEx = dma->m_pScatterGatherTableExt;
208
 
209
    DscrSize = DSCR_BLOCK_SIZE*sizeof(DMA_CHAINING_DESCR_EXT);
210
 
211
    //обнулим таблицу дескрипторов DMA
212
    memset(pSGTEx, 0, dma->m_ScatterGatherBlockCnt*DscrSize);
213
 
214
    //printk("<0>%s(): m_SGTableDscr.SystemAddress = %p\n", __FUNCTION__, dma->m_SGTableDscr.SystemAddress );
215
    //printk("<0>%s(): m_SGTableDscr.LogicalAddress = %zx\n", __FUNCTION__, dma->m_SGTableDscr.LogicalAddress );
216
 
217
    //заполним значениями таблицу цепочек DMA
218
    for(iBlock=0, iEntry=0; iBlock < dma->m_BlockCount; iBlock++) {
219
 
220
        //адрес и размер DMA блока
221
        u64     address = pMemDscr[iBlock].LogicalAddress;
222
        u64     DmaSize = dma->m_BlockSize - 0x1000;
223
 
224
 
225
        //заполним поля элментов таблицы дескрипторов
226
        pSGTEx[iEntry].AddrByte1  = (u8)((address >> 8) & 0xFF);
227
        pSGTEx[iEntry].AddrByte2  = (u8)((address >> 16) & 0xFF);
228
        pSGTEx[iEntry].AddrByte3  = (u8)((address >> 24) & 0xFF);
229
        pSGTEx[iEntry].AddrByte4  = (u8)((address >> 32) & 0xFF);
230
        pSGTEx[iEntry].SizeByte1  = (u8)((DmaSize >> 8) & 0xFF);
231
        pSGTEx[iEntry].SizeByte2  = (u8)((DmaSize >> 16) & 0xFF);
232
        pSGTEx[iEntry].SizeByte3  = (u8)((DmaSize >> 24) & 0xFF);
233
        pSGTEx[iEntry].Cmd.JumpNextDescr = 1; //перейти к следующему дескриптору
234
        pSGTEx[iEntry].Cmd.JumpNextBlock = 0; //перейти к следующему блоку дескрипторов
235
        pSGTEx[iEntry].Cmd.JumpDescr0 = 0;
236
        pSGTEx[iEntry].Cmd.Res0 = 0;
237
        pSGTEx[iEntry].Cmd.EndOfTrans = 1;
238
        pSGTEx[iEntry].Cmd.Res = 0;
239
        pSGTEx[iEntry].SizeByte1 |= dma->m_DmaDirection;
240
 
241
        {
242
            //u32 *ptr=(u32*)&pSGTEx[iEntry];
243
            //printk("<0>%s(): %d: Entry Addr: %p, Data Addr: %llx  %.8X %.8X\n",
244
            //       __FUNCTION__, iEntry, &pSGTEx[iEntry], address, ptr[1], ptr[0]);
245
        }
246
 
247
        if(((iEntry+2)%DSCR_BLOCK_SIZE) == 0)
248
        {
249
            size_t NextDscrBlockAddr = 0;
250
            DMA_NEXT_BLOCK *pNextBlock = NULL;
251
 
252
            pSGTEx[iEntry].Cmd.JumpNextBlock = 1;
253
            pSGTEx[iEntry].Cmd.JumpNextDescr = 0;
254
 
255
            //NextDscrBlockAddr = virt_to_bus((void*)&pSGTEx[iEntry+2]);
256
            NextDscrBlockAddr = (size_t)((u8*)dma->m_SGTableDscr.LogicalAddress + sizeof(DMA_CHAINING_DESCR_EXT)*(iEntry +2));
257
 
258
            //printk("<0>%s(): NextDscrBlock [PA]: %x\n", __FUNCTION__, NextDscrBlockAddr);
259
            //printk("<0>%s(): NextDscrBlock [VA]: %p\n", __FUNCTION__, &pSGTEx[iEntry+2]);
260
 
261
            pNextBlock = (DMA_NEXT_BLOCK*)&pSGTEx[iEntry+1];
262
 
263
            //printk("<0>%s(): pNextBlock: %p\n", __FUNCTION__, pNextBlock);
264
 
265
            pNextBlock->NextBlkAddr = (NextDscrBlockAddr >> 8) & 0xFFFFFF;
266
            pNextBlock->Signature = 0x4953;
267
            pNextBlock->Crc = 0;
268
            iEntry++;
269
        }
270
        iEntry++;
271
    }
272
 
273
    //printk("<0>%s(): iEntry = %d\n", __FUNCTION__, iEntry);
274
 
275
    if(((iEntry % DSCR_BLOCK_SIZE)) != 0)
276
    {
277
        DMA_NEXT_BLOCK *pNextBlock = NULL;
278
        u32 i = 0;
279
 
280
        pSGTEx[iEntry-1].Cmd.JumpNextDescr = 0;
281
 
282
        pNextBlock = (DMA_NEXT_BLOCK*)(&pSGTEx[iEntry]);
283
        pNextBlock->NextBlkAddr = (dma->m_SGTableDscr.LogicalAddress >> 8);
284
 
285
        i = (DSCR_BLOCK_SIZE * dma->m_ScatterGatherBlockCnt) - 1;
286
        pNextBlock = (DMA_NEXT_BLOCK*)(&pSGTEx[i]);
287
 
288
        //printk("<0>%s(): %d: pNextBlock: %p\n", __FUNCTION__, i, pNextBlock );
289
 
290
        pNextBlock->NextBlkAddr = 0;
291
        pNextBlock->Signature = 0x4953;
292
        pNextBlock->Crc = 0;
293
    }
294
 
295
    //printk("<0>%s(): DmaDirection = %d, DmaLocalAddress = 0x%X\n", __FUNCTION__, dma->m_DmaDirection, dma->m_DmaLocalAddress);
296
 
297
    //for( ii=0; ii<dma->m_ScatterGatherBlockCnt*DSCR_BLOCK_SIZE; ii++ )
298
    //{
299
    //u32 *ptr=(u32*)&pSGTEx[ii];
300
    //printk("<0>%s(): %d: %.8X %.8X\n", __FUNCTION__, ii, ptr[1], ptr[0]);
301
 
302
    //}
303
 
304
    pDscrBuf = (u64*)dma->m_pScatterGatherTableExt;
305
 
306
    for(iBlkEntry = 0; iBlkEntry < dma->m_ScatterGatherBlockCnt; iBlkEntry++)
307
    {
308
        u32 ctrl_code = 0xFFFFFFFF;
309
 
310
        for(iBlock = 0; iBlock < DSCR_BLOCK_SIZE; iBlock++)
311
        {
312
            u16 data0 = (u16)(pDscrBuf[iBlock] & 0xFFFF);
313
            u16 data1 = (u16)((pDscrBuf[iBlock] >> 16) & 0xFFFF);
314
            u16 data2 = (u16)((pDscrBuf[iBlock] >> 32) & 0xFFFF);
315
            u16 data3 = (u16)((pDscrBuf[iBlock] >> 48) & 0xFFFF);
316
            if(iBlock == DSCR_BLOCK_SIZE-1)
317
            {
318
                ctrl_code = ctrl_code ^ data0 ^ data1 ^ data2 ^ data3;
319
                /*
320
                printk("<0>%s(): DSCR_BLCK[%d] - NextBlkAddr = 0x%8X, Signature = 0x%4X, Crc = 0x%4X\n", __FUNCTION__,
321
                       iBlkEntry,
322
                       (u32)(pDscrBuf[iBlock] << 8),
323
                       (u16)((pDscrBuf[iBlock] >> 32) & 0xFFFF),
324
                       (u16)ctrl_code);
325
*/
326
            }
327
            else
328
            {
329
                u32 ctrl_tmp = 0;
330
                ctrl_code = ctrl_code ^ data0 ^ data1 ^ data2 ^ data3;
331
                ctrl_tmp = ctrl_code << 1;
332
                ctrl_tmp |= (ctrl_code & 0x8000) ? 0: 1;
333
                ctrl_code = ctrl_tmp;
334
 
335
                //printk("<0>%s(): %d(%d) - PciAddr = 0x%8X, Cmd = 0x%2X, DmaLength = %d(%2X %2X %2X)\n",  __FUNCTION__,
336
                //                                                                      iBlock, iBlkEntry,
337
                //                                                                      (u32)(pDscrBuf[iBlock] << 8),
338
                //                                                                      (u8)(pDscrBuf[iBlock] >> 32),
339
                //                                                                      (u32)((pDscrBuf[iBlock] >> 41) << 9),
340
                //                                                                      (u8)(pDscrBuf[iBlock] >> 56),
341
                //                                                                      (u8)(pDscrBuf[iBlock] >> 48),
342
                //                                                                      (u8)(pDscrBuf[iBlock] >> 40));
343
                //printk("<0>%s(): JumpNextDescr = %d, JumpNextBlock = %d, JumpDescr0 = %d, EndOfTrans = %d, Signature = 0x%08X, Crc = 0x%08X\n",
344
                //                                                                      __FUNCTION__, m_pScatterGatherTable[iEntry].Cmd.EndOfChain,
345
                //                                                                      m_pScatterGatherTable[iEntry].Cmd.EndOfTrans,
346
                //                                                                      m_pScatterGatherTable[iEntry].Signature,
347
                //                                                                      m_pScatterGatherTable[iEntry].Crc
348
                //                                                                      );
349
            }
350
        }
351
        pNextDscr = (u16*)pDscrBuf;
352
        pNextDscr[255] |= (u16)ctrl_code;
353
        pDscrBuf += DSCR_BLOCK_SIZE;
354
    }
355
    return 0;
356
}
357
 
358
//-----------------------------------------------------------------------------
359
/*
360
u32 NexDscrAddress(void *pVirtualAddress)
361
{
362
    return (u32)(virt_to_bus(pVirtualAddress)>>4);
363
}
364
*/
365
//-----------------------------------------------------------------------------
366
// размещение в системном адресном пространстве памяти,
367
// доступной для операций ПДП и отображаемой в пользовательское пространство
368
//-----------------------------------------------------------------------------
369
 
370
int RequestSysBuf(struct CDmaChannel *dma, void **pMemPhysAddr)
371
{
372
    u32 iBlock = 0;
373
    u32 order = 0;
374
    SHARED_MEMORY_DESCRIPTION *pMemDscr = (SHARED_MEMORY_DESCRIPTION*)dma->m_pBufDscr.SystemAddress;
375
 
376
    //printk("<0>%s()\n", __FUNCTION__);
377
 
378
    order = get_order(dma->m_BlockSize);
379
 
380
    for(iBlock = 0; iBlock < dma->m_BlockCount; iBlock++)
381
    {
382
        dma_addr_t       LogicalAddress;
383
        void            *pSystemAddress = NULL;
384
        u32 *buffer = NULL;
385
        int iii=0;
386
 
387
        pSystemAddress = dma_alloc_coherent(  dma->m_dev, dma->m_BlockSize, &LogicalAddress, GFP_KERNEL );
388
        //pSystemAddress = (void*)__get_free_pages(GFP_KERNEL, order);
389
        if(!pSystemAddress) {
390
            printk("<0>%s(): Not enought memory for %i block location. m_BlockSize = %X, BlockOrder = %d\n",
391
                   __FUNCTION__, (int)iBlock, (int)dma->m_BlockSize, (int)order );
392
            return -ENOMEM;
393
        }
394
 
395
        pMemDscr[iBlock].SystemAddress = pSystemAddress;
396
        pMemDscr[iBlock].LogicalAddress = LogicalAddress;
397
        //pMemDscr[iBlock].LogicalAddress = virt_to_bus(pSystemAddress);
398
 
399
        lock_pages( pMemDscr[iBlock].SystemAddress, dma->m_BlockSize );
400
 
401
        pMemPhysAddr[iBlock] = (void*)pMemDscr[iBlock].LogicalAddress;
402
 
403
        buffer = (u32*)pMemDscr[iBlock].SystemAddress;
404
        for(iii=0; iii<dma->m_BlockSize/4; iii++) {
405
            buffer[iii] = 0x12345678;
406
        }
407
 
408
        //printk("<0>%s(): %i: %p\n", __FUNCTION__, iBlock, pMemPhysAddr[iBlock]);
409
    }
410
 
411
    dma->m_BlockCount = iBlock;
412
    dma->m_ScatterGatherTableEntryCnt = iBlock;
413
 
414
    return 0;
415
}
416
 
417
//-----------------------------------------------------------------------------
418
 
419
void ReleaseSysBuf(struct CDmaChannel *dma)
420
{
421
    u32 iBlock = 0;
422
    //u32 order = 0;
423
    SHARED_MEMORY_DESCRIPTION *pMemDscr = (SHARED_MEMORY_DESCRIPTION*)dma->m_pBufDscr.SystemAddress;
424
 
425
    //printk("<0>%s()\n", __FUNCTION__);
426
 
427
    //order = get_order(dma->m_BlockSize);
428
 
429
    if(!dma->m_UseCount) {
430
        printk("<0> ReleaseSysBuf(): Memory not allocated.\n");
431
        return;
432
    }
433
 
434
    for(iBlock = 0; iBlock < dma->m_BlockCount; iBlock++)
435
    {
436
        unlock_pages( pMemDscr[iBlock].SystemAddress, dma->m_BlockSize );
437
 
438
        dma_free_coherent( dma->m_dev, dma->m_BlockSize, pMemDscr[iBlock].SystemAddress, pMemDscr[iBlock].LogicalAddress );
439
        //free_pages((size_t)pMemDscr[iBlock].SystemAddress, order);
440
 
441
        pMemDscr[iBlock].SystemAddress = NULL;
442
        pMemDscr[iBlock].LogicalAddress = 0;
443
    }
444
}
445
 
446
//-----------------------------------------------------------------------------
447
 
448
int RequestStub(struct CDmaChannel *dma, void **pStubPhysAddr)
449
{
450
    dma_addr_t LogicalAddress = 0;
451
    u32 StubSize = 0;
452
 
453
    //printk("<0>%s()\n", __FUNCTION__ );
454
 
455
    if(!dma)
456
        return -EINVAL;
457
 
458
    StubSize = sizeof(AMB_STUB) > PAGE_SIZE ? sizeof(AMB_STUB) : PAGE_SIZE;
459
 
460
    //printk("<0>%s() 0\n", __FUNCTION__ );
461
 
462
    if(!dma->m_UseCount)
463
    {
464
        void *pStub = dma_alloc_coherent( dma->m_dev, StubSize, &LogicalAddress, GFP_KERNEL );
465
        if(!pStub)
466
        {
467
            printk("<0>%s(): Not enought memory for stub\n", __FUNCTION__);
468
            return -ENOMEM;
469
        }
470
 
471
        lock_pages( pStub, StubSize );
472
 
473
        //printk("<0>%s() 1\n", __FUNCTION__ );
474
 
475
        dma->m_StubDscr.SystemAddress = pStub;
476
        dma->m_StubDscr.LogicalAddress = LogicalAddress;
477
        dma->m_pStub = (AMB_STUB*)pStub;          //может быть в этом нет необходимости,
478
        //но в дальнейшем в модуле используется dma->m_pStub
479
    }
480
 
481
    //printk("<0>%s() 2\n", __FUNCTION__ );
482
 
483
    pStubPhysAddr[0] = (void*)dma->m_StubDscr.LogicalAddress;
484
 
485
    //printk("<0>%s(): Stub physical address: %zx\n", __FUNCTION__, dma->m_StubDscr.LogicalAddress);
486
    //printk("<0>%s(): Stub virtual address: %p\n", __FUNCTION__, dma->m_StubDscr.SystemAddress);
487
 
488
    return 0;
489
}
490
 
491
//-----------------------------------------------------------------------------
492
 
493
void ReleaseStub(struct CDmaChannel *dma)
494
{
495
    u32 StubSize = sizeof(AMB_STUB) > PAGE_SIZE ? sizeof(AMB_STUB) : PAGE_SIZE;
496
 
497
    //printk("<0>%s()\n", __FUNCTION__);
498
 
499
    if(!dma->m_UseCount)
500
    {
501
        unlock_pages(dma->m_StubDscr.SystemAddress, StubSize);
502
 
503
        dma_free_coherent(dma->m_dev, StubSize,
504
                          dma->m_StubDscr.SystemAddress,
505
                          dma->m_StubDscr.LogicalAddress);
506
        dma->m_pStub = NULL;
507
        dma->m_StubDscr.SystemAddress = NULL;
508
        dma->m_StubDscr.LogicalAddress = 0;
509
    }
510
}
511
 
512
//-----------------------------------------------------------------------------
513
// вызываем только при первичном размещении буфера
514
//-----------------------------------------------------------------------------
515
 
516
int RequestSGList(struct CDmaChannel *dma)
517
{
518
    u32 SGListMemSize = 0;
519
    u32 SGListSize = 0;
520
    dma_addr_t PhysicalAddress;
521
 
522
    //printk("<0>%s()\n", __FUNCTION__);
523
 
524
    if(dma->m_idBlockFifo == PE_EXT_FIFO_ID)
525
    {
526
        dma->m_ScatterGatherBlockCnt = dma->m_ScatterGatherTableEntryCnt / (DSCR_BLOCK_SIZE-1);
527
        dma->m_ScatterGatherBlockCnt = (dma->m_ScatterGatherTableEntryCnt % (DSCR_BLOCK_SIZE-1)) ? (dma->m_ScatterGatherBlockCnt+1) : dma->m_ScatterGatherBlockCnt;
528
        SGListSize = sizeof(DMA_CHAINING_DESCR_EXT) * DSCR_BLOCK_SIZE * dma->m_ScatterGatherBlockCnt;
529
        //printk("<0>%s(): SGBlockCnt = %d, SGListSize = %d.\n", __FUNCTION__, dma->m_ScatterGatherBlockCnt, SGListSize);
530
    }
531
 
532
    SGListMemSize = (SGListSize >= PAGE_SIZE) ? SGListSize : PAGE_SIZE;
533
 
534
    //  выделяем память под список
535
    dma->m_SGTableDscr.SystemAddress = dma_alloc_coherent( dma->m_dev, SGListMemSize, &PhysicalAddress, GFP_KERNEL);
536
    if(!dma->m_SGTableDscr.SystemAddress)
537
    {
538
        printk("<0>%s(): Not enought memory for scatter/gather list\n", __FUNCTION__);
539
        return -ENOMEM;
540
    }
541
 
542
    dma->m_SGTableDscr.LogicalAddress = PhysicalAddress;
543
 
544
    // закрепляем список в физической памяти
545
    lock_pages(dma->m_SGTableDscr.SystemAddress, SGListMemSize);
546
 
547
    return 0;
548
}
549
 
550
//-----------------------------------------------------------------------------
551
 
552
void ReleaseSGList(struct CDmaChannel *dma)
553
{
554
    u32 SGListMemSize = 0;
555
    u32 SGListSize = 0;
556
 
557
    //printk("<0>%s()\n", __FUNCTION__);
558
 
559
    if(dma->m_idBlockFifo == PE_EXT_FIFO_ID)
560
    {
561
        SGListSize = sizeof(DMA_CHAINING_DESCR_EXT) * DSCR_BLOCK_SIZE * dma->m_ScatterGatherBlockCnt;
562
    }
563
 
564
    SGListMemSize = (SGListSize >= PAGE_SIZE) ? SGListSize : PAGE_SIZE;
565
 
566
    // закрепляем список в физической памяти
567
    unlock_pages(dma->m_SGTableDscr.SystemAddress, SGListMemSize);
568
 
569
    dma_free_coherent( dma->m_dev, SGListMemSize,
570
                       dma->m_SGTableDscr.SystemAddress,
571
                       dma->m_SGTableDscr.LogicalAddress );
572
 
573
    dma->m_SGTableDscr.SystemAddress = NULL;
574
    dma->m_SGTableDscr.LogicalAddress = 0;
575
}
576
 
577
//-----------------------------------------------------------------------------
578
 
579
int StartDmaTransfer(struct CDmaChannel *dma, u32 IsCycling)
580
{
581
    //printk("<0>%s()\n", __FUNCTION__);
582
 
583
    dma->m_DmaCycling = IsCycling;
584
    dma->m_DoneBlock = -1;
585
    dma->m_DoneFlag = 1;
586
    dma->m_CycleNum     = 0;
587
    dma->m_BlocksRemaining      = dma->m_BlockCount;
588
    dma->m_CurBlockNum = 0;
589
    dma->m_preBlockCount1 = 1;
590
    dma->m_preBlockCount2 = 2;
591
    dma->m_preBlockCount3 = 3;
592
 
593
    if(dma->m_idBlockFifo == PE_EXT_FIFO_ID)
594
    {
595
        u64 *pDscrBuf = NULL;
596
        u32 ctrl_code = ~0;
597
        u16* pDscr = NULL;
598
        int iEntry = 0;
599
        u32 iLastEntry = dma->m_ScatterGatherTableEntryCnt + dma->m_ScatterGatherBlockCnt - 1;
600
        if(dma->m_ScatterGatherBlockCnt == 1)
601
            dma->m_pScatterGatherTableExt[iLastEntry - 1].Cmd.JumpDescr0 = dma->m_DmaCycling;
602
        else
603
            dma->m_pScatterGatherTableExt[iLastEntry - 1].Cmd.JumpNextBlock = dma->m_DmaCycling;
604
 
605
        //printk("<0>%s(): m_DmaCycling = %d\n", __FUNCTION__, dma->m_DmaCycling);
606
 
607
        pDscrBuf = (u64*)dma->m_pScatterGatherTableExt + DSCR_BLOCK_SIZE * (dma->m_ScatterGatherBlockCnt - 1);
608
        ctrl_code = 0xFFFFFFFF;
609
        pDscr = (u16*)pDscrBuf;
610
        pDscr[255] = 0;
611
        for(iEntry = 0; iEntry < DSCR_BLOCK_SIZE; iEntry++)
612
        {
613
            u16 data0 = (u16)(pDscrBuf[iEntry] & 0xFFFF);
614
            u16 data1 = (u16)((pDscrBuf[iEntry] >> 16) & 0xFFFF);
615
            u16 data2 = (u16)((pDscrBuf[iEntry] >> 32) & 0xFFFF);
616
            u16 data3 = (u16)((pDscrBuf[iEntry] >> 48) & 0xFFFF);
617
            if(iEntry == DSCR_BLOCK_SIZE-1)
618
            {
619
                ctrl_code = ctrl_code ^ data0 ^ data1 ^ data2 ^ data3;
620
                /*
621
                printk("<0>%s(): DSCR_BLK[%d] - NextBlkAddr = 0x%08X, Signature = 0x%04X, Crc = 0x%04X\n",
622
                       __FUNCTION__,
623
                       dma->m_ScatterGatherBlockCnt-1,
624
                       (u32)(pDscrBuf[iEntry] << 8),
625
                       (u16)((pDscrBuf[iEntry] >> 32) & 0xFFFF),
626
                       (u16)ctrl_code);
627
*/
628
            }
629
            else
630
            {
631
                u32 ctrl_tmp = 0;
632
                ctrl_code = ctrl_code ^ data0 ^ data1 ^ data2 ^ data3;
633
                ctrl_tmp = ctrl_code << 1;
634
                ctrl_tmp |= (ctrl_code & 0x8000) ? 0: 1;
635
                ctrl_code = ctrl_tmp;
636
 
637
                // 3 способа циклического сдвига влево 32-разрядного значения
638
                // (у нас оказалось не совсем то: значение берется 16-разрядное и старший бит при переносе в младший инвертируется)
639
                //_rotl(ctrl_code, 1);
640
                //ctrl_code = (ctrl_code << 1) | (ctrl_code >> 31);
641
                //__asm {
642
                //      rol ctrl_code,1
643
                //}
644
 
645
                //printk("<0>%s(): %d(%d) - PciAddr = 0x%08X, Cmd = 0x%02X, DmaLength = %d(%02X %02X %02X)\n",
646
                //                                                                      __FUNCTION__,
647
                //                                                                      iEntry, dma->m_ScatterGatherBlockCnt-1,
648
                //                                                                      (u32)(pDscrBuf[iEntry] << 8),
649
                //                                                                      (u16)(pDscrBuf[iEntry] >> 32),
650
                //                                                                      (u32)((pDscrBuf[iEntry] >> 41) << 9),
651
                //                                                                      (u8)(pDscrBuf[iEntry] >> 56), (u8)(pDscrBuf[iEntry] >> 48), (u8)(pDscrBuf[iEntry] >> 40));
652
            }
653
        }
654
        pDscr[255] |= (u16)ctrl_code;
655
    }
656
 
657
    dma->m_pStub->lastBlock = -1;
658
    dma->m_pStub->totalCounter = 0;
659
    dma->m_pStub->state = STATE_RUN;
660
 
661
    return 0;
662
}
663
 
664
//-----------------------------------------------------------------------------
665
 
666
u32 NextDmaTransfer(struct CDmaChannel *dma)
667
{
668
    //printk("<0>%s(): - last block = %d, cycle counter = %d\n", __FUNCTION__, dma->m_pStub->lastBlock, dma->m_CycleNum);
669
 
670
    if(dma->m_pStub->lastBlock + 1 >= (long)dma->m_BlockCount)
671
        dma->m_pStub->lastBlock = 0;
672
    else
673
        dma->m_pStub->lastBlock++;
674
 
675
    dma->m_CurBlockNum++;
676
    dma->m_pStub->totalCounter++;
677
    dma->m_BlocksRemaining--;
678
 
679
    tasklet_hi_schedule(&dma->m_Dpc);
680
 
681
    //printk("<0>%s(): tasklet_hi_schedule()\n", __FUNCTION__);
682
/*
683
    if(dma->m_AdjustMode && dma->m_DmaCycling)
684
    {
685
        u32 next_done_blk = (dma->m_DoneBlock == dma->m_BlockCount-1) ? 0 : (dma->m_DoneBlock + 1);
686
        u32 next_cur_blk = ((dma->m_CurBlockNum + 1) >= dma->m_BlockCount) ? ((dma->m_CurBlockNum + 1) - dma->m_BlockCount) : (dma->m_CurBlockNum + 1);
687
        s32 difBlock = next_done_blk - next_cur_blk;
688
 
689
        if(!difBlock)
690
            dma->m_DoneFlag = 0;
691
 
692
        //printk("%s(): DoneBlock = %d, Nextdb = %d, CurBlock = %d, Nextcb = %d, difBlock = %d, DoneFlag = %d\n",
693
        //       __FUNCTION__, dma->m_DoneBlock, next_done_blk, dma->m_CurBlockNum, next_cur_blk, difBlock, dma->m_DoneFlag);
694
    }
695
*/
696
    if(dma->m_BlocksRemaining <= 0 && dma->m_DmaCycling)
697
    {
698
        dma->m_BlocksRemaining = dma->m_BlockCount;
699
        dma->m_CurBlockNum = 0;
700
        dma->m_CycleNum++;
701
    }
702
 
703
    if(dma->m_preBlockCount1+1 == dma->m_BlockCount)
704
    {
705
        dma->m_preBlockCount1 = 0;
706
    } else {
707
        dma->m_preBlockCount1++;
708
    }
709
 
710
    if(dma->m_preBlockCount2+1 == dma->m_BlockCount)
711
    {
712
        dma->m_preBlockCount2 = 0;
713
    } else {
714
        dma->m_preBlockCount2++;
715
    }
716
 
717
    if(dma->m_preBlockCount3+1 == dma->m_BlockCount)
718
    {
719
        dma->m_preBlockCount3 = 0;
720
    } else {
721
        dma->m_preBlockCount3++;
722
    }
723
 
724
 
725
    if(dma->m_AdjustMode && dma->m_DmaCycling)
726
    {
727
        if(((dma->m_preBlockCount3 == 0)&&(dma->m_DoneBlock == -1)) || (dma->m_preBlockCount3 == dma->m_DoneBlock)) {
728
            dma->m_DoneFlag = 0;
729
            //printk("<0>%s(): m_preBlockCount = %d, m_DoneBlock = %d\n", __FUNCTION__, dma->m_preBlockCount3, dma->m_DoneBlock);
730
        }
731
    }
732
 
733
    return dma->m_DoneFlag;
734
}
735
 
736
//-----------------------------------------------------------------------------
737
 
738
u32 SetDoneBlock(struct CDmaChannel *dma, long numBlk)
739
{
740
    if(numBlk != dma->m_DoneBlock)
741
    {
742
        dma->m_DoneBlock = numBlk;
743
 
744
        if((dma->m_preBlockCount1 != dma->m_DoneBlock) && (dma->m_preBlockCount2 != dma->m_DoneBlock) && (dma->m_preBlockCount3 != dma->m_DoneBlock)) {
745
 
746
            if(dma->m_AdjustMode && dma->m_DmaCycling && !dma->m_DoneFlag)
747
            {
748
                dma->m_DoneFlag = 1;
749
            }
750
        }
751
    }
752
 
753
    //printk("<0>%s(): DoneBlock = %d, DoneFlag = %d\n", __FUNCTION__, dma->m_DoneBlock, dma->m_DoneFlag);
754
 
755
    return dma->m_DoneFlag;
756
}
757
 
758
//-----------------------------------------------------------------------------
759
 
760
void GetState(struct CDmaChannel *dma, u32 *BlockNum, u32 *BlockNumTotal, u32 *OffsetInBlock, u32 *DmaChanState)
761
{
762
    //printk("<0>%s(): - last block = %d, cycle counter = %d\n", __FUNCTION__, dma->m_pStub->lastBlock, dma->m_CycleNum);
763
 
764
    *BlockNum = dma->m_State.lastBlock;
765
    *BlockNumTotal = dma->m_State.totalCounter;
766
    *OffsetInBlock = dma->m_State.offset;// регистр подсчета переданных байт в текущем буфере будет реализован позже
767
    *DmaChanState = dma->m_State.state;
768
}
769
 
770
//-----------------------------------------------------------------------------
771
 
772
void FreezeState(struct CDmaChannel *dma)
773
{
774
    //printk("<0>%s()\n", __FUNCTION__);
775
}
776
 
777
//-----------------------------------------------------------------------------
778
 
779
int WaitBlockEndEvent(struct CDmaChannel *dma, u32 msTimeout)
780
{
781
    int status = -ETIMEDOUT;
782
 
783
    //printk("<0>%s(): DMA%d\n", __FUNCTION__, dma->m_NumberOfChannel);
784
 
785
    if( msTimeout < 0 ) {
786
        status = GrabEvent( &dma->m_BlockEndEvent, -1 );
787
    } else {
788
        status = GrabEvent( &dma->m_BlockEndEvent, msTimeout );
789
    }
790
    return status;
791
}
792
 
793
//-----------------------------------------------------------------------------
794
 
795
int WaitBufferEndEvent(struct CDmaChannel *dma, u32 msTimeout)
796
{
797
    int status = -ETIMEDOUT;
798
 
799
    //printk("<0>%s(): DMA%d\n", __FUNCTION__, dma->m_NumberOfChannel);
800
 
801
    if( msTimeout < 0 ) {
802
        status = GrabEvent( &dma->m_BufferEndEvent, -1 );
803
    } else {
804
        status = GrabEvent( &dma->m_BufferEndEvent, msTimeout );
805
    }
806
 
807
    return status;
808
}
809
 
810
//-----------------------------------------------------------------------------
811
 
812
int CompleteDmaTransfer(struct CDmaChannel *dma)
813
{
814
    //printk("<0> %s(): DMA%d\n", __FUNCTION__, dma->m_NumberOfChannel);
815
    dma->m_pStub->state = STATE_STOP;
816
    return 0;
817
}
818
 
819
//-----------------------------------------------------------------------------
820
 
821
void GetSGStartParams(struct CDmaChannel *dma, u64 *SGTableAddress, u32 *LocalAddress, u32 *DmaDirection)
822
{
823
    if(dma->m_idBlockFifo == PE_EXT_FIFO_ID)
824
    {
825
        *SGTableAddress = dma->m_SGTableDscr.LogicalAddress;
826
    }
827
 
828
    *LocalAddress = dma->m_DmaLocalAddress;
829
    *DmaDirection = dma->m_DmaDirection;
830
}
831
 
832
//-----------------------------------------------------------------------------
833
 
834
void GetStartParams(struct CDmaChannel *dma, u32 *PciAddress, u32 *LocalAddress, u32 *DmaLength)
835
{
836
    // возвращает адрес и размер DMA из первого элемента таблицы
837
    if(dma->m_idBlockFifo == PE_EXT_FIFO_ID)
838
    {
839
        u64 *pDscrBuf = (u64*)dma->m_pScatterGatherTableExt;
840
        *PciAddress = (u32)(pDscrBuf[0] << 16);
841
        *DmaLength = (u32)((pDscrBuf[0] >> 40) << 8);
842
    }
843
    *LocalAddress = dma->m_DmaLocalAddress;
844
}
845
 
846
//-----------------------------------------------------------------------------
847
 
848
void Adjust(struct CDmaChannel *dma, u32 mode)
849
{
850
    //printk("<0>%s()\n", __FUNCTION__);
851
    dma->m_AdjustMode = mode;
852
}
853
 
854
//-----------------------------------------------------------------------------
855
 
856
void SetAdmTetr(struct CDmaChannel *dma, u32 AdmNum, u32 TetrNum)
857
{
858
    //printk("<0>%s()\n", __FUNCTION__);
859
    dma->m_AdmNum = AdmNum;
860
    dma->m_TetrNum = TetrNum;
861
}
862
 
863
//-----------------------------------------------------------------------------
864
 
865
void SetDmaLocalAddress(struct CDmaChannel *dma, u32 Address)
866
{
867
    //printk("<0>%s()\n", __FUNCTION__);
868
    dma->m_DmaLocalAddress = Address;
869
}
870
 
871
//-----------------------------------------------------------------------------
872
 
873
int SetDmaDirection(struct CDmaChannel *dma, u32 DmaDirection)
874
{
875
    //printk("<0>%s()\n", __FUNCTION__);
876
    switch(DmaDirection)
877
    {
878
    case 1:
879
        dma->m_DmaDirection = TRANSFER_DIR_FROM_DEVICE;
880
        break;
881
    case 2:
882
        dma->m_DmaDirection = TRANSFER_DIR_TO_DEVICE;
883
        break;
884
    default:
885
        return -EINVAL;
886
    }
887
 
888
    return 0;
889
}
890
 
891
//-----------------------------------------------------------------------------
892
 
893
u32 GetAdmNum(struct CDmaChannel *dma)
894
{
895
    return dma->m_AdmNum;
896
}
897
 
898
//-----------------------------------------------------------------------------
899
 
900
u32 GetTetrNum(struct CDmaChannel *dma)
901
{
902
    return dma->m_TetrNum;
903
}
904
 
905
//-----------------------------------------------------------------------------
906
 
907
void DmaDpcForIsr( unsigned long Context )
908
{
909
    struct CDmaChannel *DmaChannel = (struct CDmaChannel *)Context;
910
    unsigned long flags = 0;
911
 
912
    spin_lock_irqsave(&DmaChannel->m_DmaLock, flags);
913
 
914
    //printk("<0>%s(): [DMA%d] m_CurBlockNum = %d, m_BlockCount = %d\n",
915
    //       __FUNCTION__, DmaChannel->m_NumberOfChannel, DmaChannel->m_CurBlockNum, DmaChannel->m_BlockCount );
916
 
917
    SetEvent( &DmaChannel->m_BlockEndEvent );
918
 
919
    if(DmaChannel->m_CurBlockNum >= DmaChannel->m_BlockCount)
920
    {
921
        HwCompleteDmaTransfer(DmaChannel->m_Board,DmaChannel->m_NumberOfChannel);
922
        SetEvent( &DmaChannel->m_BufferEndEvent );
923
    }
924
 
925
    spin_unlock_irqrestore(&DmaChannel->m_DmaLock, flags);
926
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.