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 6

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

powered by: WebSVN 2.1.0

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