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/] [pexmodule.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
#include <linux/module.h>
4
#include <linux/version.h>
5
#include <linux/init.h>
6
#include <linux/fs.h>
7
#include <linux/ioport.h>
8
#include <linux/list.h>
9
#include <linux/pci.h>
10
#include <linux/proc_fs.h>
11
#include <linux/interrupt.h>
12
#include <asm/system.h>
13
#include <asm/io.h>
14
#include <asm/io.h>
15
 
16
#include <asm/uaccess.h>
17
#include <linux/types.h>
18
#include <linux/ioport.h>
19
#include <linux/poll.h>
20
#include <linux/pci.h>
21
#include <linux/interrupt.h>
22
 
23
#include "pexmodule.h"
24
#include "hardware.h"
25
#include "pexioctl.h"
26
#include "ioctlrw.h"
27
#include "ambpexregs.h"
28
#include "pexproc.h"
29
 
30
//-----------------------------------------------------------------------------
31
 
32
MODULE_AUTHOR("Vladimir Karakozov. karakozov@gmail.com");
33
MODULE_LICENSE("GPL");
34
 
35
//-----------------------------------------------------------------------------
36
 
37
static dev_t devno = MKDEV(0, 0);
38
static struct class *pex_class = NULL;
39
static LIST_HEAD(device_list);
40
static int boards_count = 0;
41
static struct mutex pex_mutex;
42
int dbg_trace = 0;
43
int err_trace = 1;
44
 
45
//-----------------------------------------------------------------------------
46
 
47
static int free_memory(struct pex_device *brd)
48
{
49
    struct list_head *pos, *n;
50
    struct mem_t *m = NULL;
51
    int unlocked = 0;
52
 
53
    spin_lock(&brd->m_MemListLock);
54
 
55
    list_for_each_safe(pos, n, &brd->m_MemList) {
56
 
57
        m = list_entry(pos, struct mem_t, list);
58
 
59
        unlocked = unlock_pages(m->cpu_addr, m->size);
60
 
61
        dma_free_coherent(&brd->m_pci->dev, m->size, m->cpu_addr, m->dma_handle);
62
 
63
        dbg_msg(dbg_trace, "%s(): %d: PA = 0x%zx, VA = %p, SZ = 0x%zx, PAGES = %d\n",
64
                __FUNCTION__, atomic_read(&brd->m_MemListCount), (size_t)m->dma_handle, m->cpu_addr, m->size, unlocked );
65
 
66
        list_del(pos);
67
 
68
        atomic_dec(&brd->m_MemListCount);
69
 
70
        kfree(m);
71
    }
72
 
73
    spin_unlock(&brd->m_MemListLock);
74
 
75
    return 0;
76
}
77
 
78
//-----------------------------------------------------------------------------
79
 
80
static struct pex_device *file_to_device( struct file *file )
81
{
82
    return (struct pex_device*)file->private_data;
83
}
84
 
85
//-----------------------------------------------------------------------------
86
 
87
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37)
88
static struct pex_device *inode_to_device( struct list_head *head, struct inode *inode )
89
{
90
    struct list_head *p;
91
    struct pex_device *entry;
92
    unsigned int minor = MINOR(inode->i_rdev);
93
 
94
    list_for_each(p, head) {
95
        entry = list_entry(p, struct pex_device, m_list);
96
        if(entry->m_BoardIndex == minor)
97
            return entry;
98
    }
99
 
100
    return NULL;
101
}
102
#endif
103
 
104
//-----------------------------------------------------------------------------
105
 
106
static int pex_device_fasync(int fd, struct file *file, int mode)
107
{
108
    struct pex_device *pDevice = file->private_data;
109
    if(!pDevice)
110
        return -ENODEV;
111
 
112
    return 0;
113
}
114
 
115
//-----------------------------------------------------------------------------
116
 
117
static unsigned int pex_device_poll(struct file *filp, poll_table *wait)
118
{
119
    unsigned int mask = 0;
120
 
121
    struct pex_device *pDevice = file_to_device(filp);
122
    if(!pDevice)
123
        return -ENODEV;
124
 
125
    return mask;
126
}
127
 
128
//-----------------------------------------------------------------------------
129
 
130
static int pex_device_open( struct inode *inode, struct file *file )
131
{
132
    struct pex_device *pDevice = container_of(inode->i_cdev, struct pex_device, m_cdev);
133
    if(!pDevice) {
134
        err_msg(err_trace, "%s(): Open device failed\n", __FUNCTION__);
135
        return -ENODEV;
136
    }
137
 
138
    file->private_data = (void*)pDevice;
139
 
140
    dbg_msg(dbg_trace, "%s(): Open device %s\n", __FUNCTION__, pDevice->m_name);
141
 
142
    return 0;
143
}
144
 
145
//-----------------------------------------------------------------------------
146
 
147
static int pex_device_close( struct inode *inode, struct file *file )
148
{
149
    struct pex_device *pDevice = container_of(inode->i_cdev, struct pex_device, m_cdev);
150
    if(!pDevice) {
151
        err_msg(err_trace, "%s(): Close device failed\n", __FUNCTION__);
152
        return -ENODEV;
153
    }
154
 
155
    file->private_data = NULL;
156
 
157
    dbg_msg(dbg_trace, "%s(): Close device %s\n", __FUNCTION__, pDevice->m_name);
158
 
159
    return 0;
160
}
161
 
162
//-----------------------------------------------------------------------------
163
 
164
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)
165
static long pex_device_ioctl( struct file *file, unsigned int cmd, unsigned long arg )
166
#else
167
static int pex_device_ioctl( struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg )
168
#endif
169
{
170
    int error = 0;
171
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)
172
    struct pex_device *pDevice = file_to_device(file);
173
#else
174
    struct pex_device *pDevice = inode_to_device(&device_list, inode);
175
#endif
176
    if(!pDevice) {
177
        err_msg(err_trace, "%s(): ioctl device failed\n", __FUNCTION__);
178
        return -ENODEV;
179
    }
180
 
181
    mutex_lock(&pDevice->m_BoardMutex);
182
 
183
    switch(cmd) {
184
    case IOCTL_PEX_BOARD_INFO:
185
        error = ioctl_board_info(pDevice, arg);
186
        break;
187
    case IOCTL_PEX_MEM_ALLOC:
188
        error = ioctl_memory_alloc(pDevice, arg);
189
        break;
190
    case IOCTL_PEX_MEM_FREE:
191
        error = ioctl_memory_free(pDevice, arg);
192
        break;
193
    case IOCTL_PEX_STUB_ALLOC:
194
        error = ioctl_stub_alloc(pDevice, arg);
195
        break;
196
    case IOCTL_PEX_STUB_FREE:
197
        error = ioctl_stub_free(pDevice, arg);
198
        break;
199
    case IOCTL_AMB_SET_MEMIO:
200
        error = ioctl_set_mem(pDevice, arg);
201
        break;
202
    case IOCTL_AMB_FREE_MEMIO:
203
        error = ioctl_free_mem(pDevice, arg);
204
        break;
205
    case IOCTL_AMB_START_MEMIO:
206
        error = ioctl_start_mem(pDevice, arg);
207
        break;
208
    case IOCTL_AMB_STOP_MEMIO:
209
        error = ioctl_stop_mem(pDevice, arg);
210
        break;
211
    case IOCTL_AMB_STATE_MEMIO:
212
        error = ioctl_state_mem(pDevice, arg);
213
        break;
214
    case IOCTL_AMB_WAIT_DMA_BUFFER:
215
        error = ioctl_wait_dma_buffer(pDevice, arg);
216
        break;
217
    case IOCTL_AMB_WAIT_DMA_BLOCK:
218
        error = ioctl_wait_dma_block(pDevice, arg);
219
        break;
220
    case IOCTL_AMB_SET_SRC_MEM:
221
        error = ioctl_set_src_mem(pDevice, arg);
222
        break;
223
    case IOCTL_AMB_SET_DIR_MEM:
224
        error = ioctl_set_dir_mem(pDevice, arg);
225
        break;
226
    case IOCTL_AMB_SET_DRQ_MEM:
227
        error = ioctl_set_drq_mem(pDevice, arg);
228
        break;
229
    case IOCTL_AMB_RESET_FIFO:
230
        error = ioctl_reset_fifo(pDevice, arg);
231
        break;
232
    case IOCTL_AMB_DONE:
233
        error = ioctl_done(pDevice, arg);
234
        break;
235
    case IOCTL_AMB_ADJUST:
236
        error = ioctl_adjust(pDevice, arg);
237
        break;
238
 
239
    default:
240
        dbg_msg(dbg_trace, "%s(): Unknown command\n", __FUNCTION__);
241
        error = -EINVAL;
242
        break;
243
    }
244
 
245
    mutex_unlock(&pDevice->m_BoardMutex);
246
 
247
    return error;
248
}
249
 
250
//-----------------------------------------------------------------------------
251
 
252
static inline int private_mapping_ok(struct vm_area_struct *vma)
253
{
254
    return vma->vm_flags & VM_MAYSHARE;
255
}
256
 
257
//-----------------------------------------------------------------------------
258
 
259
static int pex_device_mmap(struct file *file, struct vm_area_struct *vma)
260
{
261
    size_t size = vma->vm_end - vma->vm_start;
262
 
263
    if (!private_mapping_ok(vma))
264
        return -ENOSYS;
265
 
266
    vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
267
 
268
    if (remap_pfn_range(vma,
269
                        vma->vm_start,
270
                        vma->vm_pgoff,
271
                        size,
272
                        vma->vm_page_prot)) {
273
        err_msg(err_trace, "%s(): error in remap_page_range.\n", __FUNCTION__ );
274
        return -EAGAIN;
275
    }
276
    return 0;
277
}
278
 
279
//-----------------------------------------------------------------------------
280
 
281
static ssize_t pex_device_aio_read(struct kiocb *iocb, const struct iovec *iov, unsigned long count, loff_t off)
282
{
283
    struct pex_device *pDevice = file_to_device(iocb->ki_filp);
284
    if(!pDevice) {
285
        err_msg(err_trace, "%s(): ioctl device failed\n", __FUNCTION__);
286
        return -ENODEV;
287
    }
288
    return -ENOSYS;
289
}
290
 
291
//-----------------------------------------------------------------------------
292
 
293
static ssize_t pex_device_aio_write(struct kiocb *iocb, const struct iovec *iov, unsigned long count, loff_t off)
294
{
295
    struct pex_device *pDevice = file_to_device(iocb->ki_filp);
296
    if(!pDevice) {
297
        err_msg(err_trace, "%s(): ioctl device failed\n", __FUNCTION__);
298
        return -ENODEV;
299
    }
300
    return -ENOSYS;
301
}
302
 
303
//-----------------------------------------------------------------------------
304
 
305
static irqreturn_t pex_device_isr( int irq, void *pContext )
306
{
307
    FIFO_STATUS FifoStatus;  //
308
 
309
    struct pex_device* pDevice = (struct pex_device*)pContext;            // our device
310
 
311
    if(!pDevice->m_DmaIrqEnbl && !pDevice->m_FlgIrqEnbl)
312
        return IRQ_NONE;
313
 
314
    if(pDevice->m_FlgIrqEnbl)
315
    {  // прерывание от флагов состояния
316
        /*
317
            u32 status = ReadOperationWordReg(pDevice, PEMAINadr_BRD_STATUS);
318
            err_msg(err_trace, "%s(): BRD_STATUS = 0x%X.\n", __FUNCTION__, status);
319
            if(status & 0x4000)
320
            {
321
                    for(int i = 0; i < NUM_TETR_IRQ; i++)
322
                            if(pDevice->m_TetrIrq[i] != 0)
323
                            {
324
                                    u32 status = ReadAmbMainReg(pDevice, pDevice->m_TetrIrq[i].Address);
325
                                    KdPrint(("CWambpex::WambpexIsr: TetrIrq = %d, Address = 0x%X, IrqInv = 0x%X, IrqMask = 0x%X, Status = 0x%X.\n",
326
                                                            i, pDevice->m_TetrIrq[i].Address, pDevice->m_TetrIrq[i].IrqInv, pDevice->m_TetrIrq[i].IrqMask, status));
327
                                    status ^= pDevice->m_TetrIrq[i].IrqInv;
328
                                    status &= pDevice->m_TetrIrq[i].IrqMask;
329
                                    KdPrint(("CWambpex::WambpexIsr: TetrIrq = %d, Address = 0x%X, IrqInv = 0x%X, IrqMask = 0x%X, Status = 0x%X.\n",
330
                                                            i, pDevice->m_TetrIrq[i].Address, pDevice->m_TetrIrq[i].IrqInv, pDevice->m_TetrIrq[i].IrqMask, status));
331
                                    if(status)
332
                                    {
333
                                            KeInsertQueueDpc(&pDevice->m_TetrIrq[i].Dpc, NULL, NULL);
334
                                            KdPrint(("CWambpex::WambpexIsr - Tetrad IRQ address = %d\n", pDevice->m_TetrIrq[i].Address));
335
                                            // сброс статусного бита, вызвавшего прерывание
336
                                            //pDevice->WriteAmbMainReg(pDevice->m_TetrIrq[i].Address + 0x200);
337
                                            ULONG CmdAddress = pDevice->m_TetrIrq[i].Address + TRDadr_CMD_ADR * REG_SIZE;
338
                                            pDevice->WriteAmbMainReg(CmdAddress, 0);
339
                                            ULONG DataAddress = pDevice->m_TetrIrq[i].Address + TRDadr_CMD_DATA * REG_SIZE;
340
                                            ULONG Mode0Value = pDevice->ReadAmbMainReg(DataAddress);
341
                                            Mode0Value &= 0xFFFB;
342
                                            //pDevice->WriteAmbMainReg(CmdAddress, 0);
343
                                            pDevice->WriteAmbMainReg(DataAddress, Mode0Value);
344
                                            break;
345
                                    }
346
                            }
347
                return IRQ_HANDLED;
348
            }
349
            else // вообще не наше прерывание !!!
350
                    return IRQ_NONE;    // we did not interrupt
351
            */
352
    }
353
 
354
    if(pDevice->m_DmaIrqEnbl)
355
    {   // прерывание от каналов ПДП
356
        u32 i=0;
357
        u32 FifoAddr = 0;
358
        u32 iChan = pDevice->m_primChan;
359
        u32 NumberOfChannel = -1;
360
 
361
        for(i = 0; i < MAX_NUMBER_OF_DMACHANNELS; i++)
362
        {
363
            if(pDevice->m_DmaChanMask & (1 << iChan))
364
            {
365
                FifoAddr = pDevice->m_FifoAddr[iChan];
366
                FifoStatus.AsWhole = ReadOperationWordReg(pDevice, PEFIFOadr_FIFO_STATUS + FifoAddr);
367
                if(FifoStatus.ByBits.IntRql)
368
                {
369
                    //err_msg(err_trace, "%s(): - Channel = %d, Fifo Status = 0x%X\n", __FUNCTION__, iChan, FifoStatus.AsWhole);
370
                    NumberOfChannel = iChan;
371
                    pDevice->m_primChan = ((pDevice->m_primChan+1) >= MAX_NUMBER_OF_DMACHANNELS) ? 0 : pDevice->m_primChan+1;
372
                    break;
373
                }
374
            }
375
            iChan = ((iChan+1) >= MAX_NUMBER_OF_DMACHANNELS) ? 0 : iChan+1;
376
        }
377
 
378
        if(NumberOfChannel != -1)
379
        {
380
            u32 flag = 0;
381
 
382
            //err_msg(err_trace, "%s(%d)\n", __FUNCTION__, atomic_read(&pDevice->m_TotalIRQ));
383
 
384
            flag = NextDmaTransfer(pDevice->m_DmaChannel[NumberOfChannel]);
385
            if(!flag)
386
            {
387
                DMA_CTRL_EXT CtrlExt;
388
                CtrlExt.AsWhole = 0;
389
                CtrlExt.ByBits.Pause = 1;
390
                CtrlExt.ByBits.Start = 1;
391
                WriteOperationWordReg(pDevice, PEFIFOadr_DMA_CTRL + FifoAddr, CtrlExt.AsWhole);
392
                //err_msg(err_trace, "%s(): - Pause (%d) - m_CurBlockNum = %d, m_DoneBlock = %d\n", __FUNCTION__, atomic_read(&pDevice->m_TotalIRQ),
393
                //        pDevice->m_DmaChannel[NumberOfChannel]->m_CurBlockNum,
394
                //        pDevice->m_DmaChannel[NumberOfChannel]->m_DoneBlock);
395
            }
396
 
397
            //err_msg(err_trace, "%s(): - Flag Clear\n", __FUNCTION__);
398
            WriteOperationWordReg(pDevice, PEFIFOadr_FLAG_CLR + FifoAddr, 0x10);
399
            WriteOperationWordReg(pDevice, PEFIFOadr_FLAG_CLR + FifoAddr, 0x00);
400
            //err_msg(err_trace, "%s(): - Complete\n", __FUNCTION__);
401
 
402
            atomic_inc(&pDevice->m_TotalIRQ);
403
 
404
            return IRQ_HANDLED;
405
        }
406
    }
407
    return IRQ_NONE;    // we did not interrupt
408
}
409
 
410
//-----------------------------------------------------------------------------
411
 
412
struct file_operations pex_fops = {
413
 
414
    .owner = THIS_MODULE,
415
    .read = NULL,
416
    .write = NULL,
417
 
418
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)
419
    .unlocked_ioctl = pex_device_ioctl,
420
    .compat_ioctl = pex_device_ioctl,
421
#else
422
    .ioctl = pex_device_ioctl,
423
#endif
424
 
425
    .mmap = pex_device_mmap,
426
    .open = pex_device_open,
427
    .release = pex_device_close,
428
    .fasync = pex_device_fasync,
429
    .poll = pex_device_poll,
430
    .aio_read =  pex_device_aio_read,
431
    .aio_write = pex_device_aio_write,
432
};
433
 
434
//-----------------------------------------------------------------------------
435
//-----------------------------------------------------------------------------
436
//-----------------------------------------------------------------------------
437
//-----------------------------------------------------------------------------
438
 
439
static const struct pci_device_id pex_device_id[] = {
440
{
441
        .vendor =       INSYS_VENDOR_ID,
442
        .device =       AMBPEX5_DEVID,
443
        .subvendor =    PCI_ANY_ID,
444
        .subdevice =    PCI_ANY_ID,
445
},
446
{
447
        .vendor =       INSYS_VENDOR_ID,
448
        .device =       AMBPEX8_DEVID,
449
        .subvendor =    PCI_ANY_ID,
450
        .subdevice =    PCI_ANY_ID,
451
},
452
{
453
        .vendor =       INSYS_VENDOR_ID,
454
        .device =       ADP201X1AMB_DEVID,
455
        .subvendor =    PCI_ANY_ID,
456
        .subdevice =    PCI_ANY_ID,
457
},
458
{
459
        .vendor =       INSYS_VENDOR_ID,
460
        .device =       ADP201X1DSP_DEVID,
461
        .subvendor =    PCI_ANY_ID,
462
        .subdevice =    PCI_ANY_ID,
463
},
464
{
465
        .vendor =       INSYS_VENDOR_ID,
466
        .device =       AMBPEXARM_DEVID,
467
        .subvendor =    PCI_ANY_ID,
468
        .subdevice =    PCI_ANY_ID,
469
},
470
{
471
        .vendor =       INSYS_VENDOR_ID,
472
        .device =       AMBFMC106P_DEVID,
473
        .subvendor =    PCI_ANY_ID,
474
        .subdevice =    PCI_ANY_ID,
475
},
476
{ },
477
};
478
 
479
MODULE_DEVICE_TABLE(pci, pex_device_id);
480
 
481
//-----------------------------------------------------------------------------
482
 
483
static int  __devinit pex_device_probe(struct pci_dev *dev, const struct pci_device_id *id)
484
{
485
    int error = 0;
486
    int i = 0;
487
    struct pex_device *brd = NULL;
488
 
489
    mutex_lock(&pex_mutex);
490
 
491
    brd = kzalloc(sizeof(struct pex_device), GFP_KERNEL);
492
    if(!brd) {
493
        error = -ENOMEM;
494
        goto do_out;
495
    }
496
 
497
    INIT_LIST_HEAD(&brd->m_list);
498
    mutex_init(&brd->m_BoardMutex);
499
    sema_init(&brd->m_BoardSem, 1);
500
    spin_lock_init(&brd->m_BoardLock);
501
    atomic_set(&brd->m_TotalIRQ, 0);
502
    init_waitqueue_head(&brd->m_WaitQueue);
503
    init_timer(&brd->m_TimeoutTimer);
504
    spin_lock_init(&brd->m_MemListLock);
505
    atomic_set(&brd->m_MemListCount, 0);
506
    INIT_LIST_HEAD(&brd->m_MemList);
507
    brd->m_pci = dev;
508
    brd->m_Interrupt = -1;
509
    brd->m_DmaIrqEnbl = 0;
510
    brd->m_FlgIrqEnbl = 0;
511
    brd->m_class = pex_class;
512
 
513
    set_device_name(brd, dev->device, boards_count);
514
 
515
    dbg_msg(dbg_trace, "%s(): device_id = %x, vendor_id = %x, board name %s\n", __FUNCTION__, dev->device, dev->vendor, brd->m_name);
516
 
517
    error = pci_enable_device(dev);
518
    if(error) {
519
        err_msg(err_trace, "%s(): error enabling pci device\n", __FUNCTION__);
520
        goto do_free_memory;
521
    }
522
 
523
    if (pci_set_dma_mask(dev, DMA_BIT_MASK(64)) || pci_set_consistent_dma_mask(dev, DMA_BIT_MASK(64))) {
524
        printk("%s(): error set pci dma mask\n", __FUNCTION__);
525
        goto do_disable_device;
526
    }
527
 
528
    pci_set_master(dev);
529
 
530
    brd->m_BAR0.physical_address = pci_resource_start(dev, 0);
531
    brd->m_BAR0.size = pci_resource_len(dev, 0);
532
    brd->m_BAR0.virtual_address = ioremap_nocache(brd->m_BAR0.physical_address, brd->m_BAR0.size);
533
    if(!brd->m_BAR0.virtual_address) {
534
        error = -ENOMEM;
535
        err_msg(err_trace, "%s(): error map device memory at bar%d\n", __FUNCTION__, 0);
536
        goto do_disable_device;
537
    }
538
 
539
    dbg_msg(dbg_trace, "%s(): map bar0 %zx -> %p\n", __FUNCTION__, brd->m_BAR0.physical_address, brd->m_BAR0.virtual_address);
540
 
541
    brd->m_BAR1.physical_address = pci_resource_start(dev, 1);
542
    brd->m_BAR1.size = pci_resource_len(dev, 1);
543
    brd->m_BAR1.virtual_address = ioremap_nocache(brd->m_BAR1.physical_address, brd->m_BAR1.size);
544
    if(!brd->m_BAR1.virtual_address) {
545
        error = -ENOMEM;
546
        err_msg(err_trace, "%s(): error map device memory at bar%d\n", __FUNCTION__, 0);
547
        goto do_unmap_bar0;
548
    }
549
 
550
    dbg_msg(dbg_trace, "%s(): map bar1 %zx -> %p\n", __FUNCTION__, brd->m_BAR1.physical_address, brd->m_BAR1.virtual_address);
551
 
552
    error = request_irq(dev->irq, pex_device_isr, IRQF_SHARED, brd->m_name, brd);
553
    if( error < 0) {
554
        error = -EBUSY;
555
        err_msg( err_trace, "%s(): error in request_irq()\n", __FUNCTION__ );
556
        goto do_unmap_bar1;
557
    }
558
 
559
    brd->m_Interrupt = dev->irq;
560
 
561
    cdev_init(&brd->m_cdev, &pex_fops);
562
    brd->m_cdev.owner = THIS_MODULE;
563
    brd->m_cdev.ops = &pex_fops;
564
    brd->m_devno = MKDEV(MAJOR(devno), boards_count);
565
 
566
    error = cdev_add(&brd->m_cdev, brd->m_devno, 1);
567
    if(error) {
568
        err_msg(err_trace, "%s(): Error add char device %d\n", __FUNCTION__, boards_count);
569
        error = -EINVAL;
570
        goto do_free_irq;
571
    }
572
 
573
    dbg_msg(dbg_trace, "%s(): Add cdev %d\n", __FUNCTION__, boards_count);
574
 
575
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
576
    brd->m_device = device_create(pex_class, NULL, brd->m_devno, "%s", brd->m_name);
577
#else
578
    brd->m_device = device_create(pex_class, NULL, brd->m_devno, NULL, "%s", brd->m_name);
579
#endif
580
    if(!brd->m_device ) {
581
        err_msg(err_trace, "%s(): Error create device for board: %s\n", __FUNCTION__, brd->m_name);
582
        error = -EINVAL;
583
        goto do_delete_cdev;
584
    }
585
 
586
    dbg_msg(dbg_trace, "%s(): Create device file for board: %s\n", __FUNCTION__, brd->m_name);
587
 
588
    brd->m_BoardIndex = boards_count;
589
 
590
    InitializeBoard(brd);
591
 
592
    for(i = 0; i < MAX_NUMBER_OF_DMACHANNELS; i++) {
593
 
594
        if(brd->m_DmaChanMask & (1 << i)) {
595
 
596
            brd->m_DmaChannel[i] = CDmaChannelCreate( i,  brd,
597
                                                      &brd->m_pci->dev,
598
                                                      brd->m_MaxDmaSize[i],
599
                                                      brd->m_BlockFifoId[i], 1 );
600
        }
601
    }
602
 
603
    pex_register_proc(brd->m_name, pex_proc_info, brd);
604
 
605
    list_add_tail(&brd->m_list, &device_list);
606
 
607
    boards_count++;
608
 
609
    dbg_msg(dbg_trace, "%s(): Board %s - setup complete\n", __FUNCTION__, brd->m_name);
610
 
611
    mutex_unlock(&pex_mutex);
612
 
613
    return error;
614
 
615
do_delete_cdev:
616
    cdev_del(&brd->m_cdev);
617
 
618
do_free_irq:
619
    free_irq(brd->m_Interrupt, brd);
620
 
621
do_unmap_bar1:
622
    iounmap(brd->m_BAR1.virtual_address);
623
 
624
do_unmap_bar0:
625
    iounmap(brd->m_BAR0.virtual_address);
626
 
627
 
628
do_disable_device:
629
    pci_disable_device(dev);
630
 
631
do_free_memory:
632
    kfree(brd);
633
 
634
do_out:
635
    mutex_unlock(&pex_mutex);
636
 
637
    return error;
638
}
639
 
640
//-----------------------------------------------------------------------------
641
 
642
static void __devexit pex_device_remove(struct pci_dev *dev)
643
{
644
    struct list_head *pos, *n;
645
    struct pex_device *brd = NULL;
646
 
647
    dbg_msg(dbg_trace, "%s(): device_id = %x, vendor_id = %x\n", __FUNCTION__, dev->device, dev->vendor);
648
 
649
    mutex_lock(&pex_mutex);
650
 
651
    list_for_each_safe(pos, n, &device_list) {
652
 
653
        brd = list_entry(pos, struct pex_device, m_list);
654
 
655
        if(brd->m_pci == dev) {
656
 
657
            free_irq(brd->m_Interrupt, brd);
658
            dbg_msg(dbg_trace, "%s(): free_irq() - complete\n", __FUNCTION__);
659
            pex_remove_proc(brd->m_name);
660
            dbg_msg(dbg_trace, "%s(): pex_remove_proc() - complete\n", __FUNCTION__);
661
            free_memory(brd);
662
            dbg_msg(dbg_trace, "%s(): free_memory() - complete\n", __FUNCTION__);
663
            device_destroy(pex_class, brd->m_devno);
664
            dbg_msg(dbg_trace, "%s(): device_destroy() - complete\n", __FUNCTION__);
665
            cdev_del(&brd->m_cdev);
666
            dbg_msg(dbg_trace, "%s(): cdev_del() - complete\n", __FUNCTION__);
667
            iounmap(brd->m_BAR1.virtual_address);
668
            dbg_msg(dbg_trace, "%s(): iounmap() - complete\n", __FUNCTION__);
669
            iounmap(brd->m_BAR0.virtual_address);
670
            dbg_msg(dbg_trace, "%s(): iounmap() - complete\n", __FUNCTION__);
671
            pci_disable_device(dev);
672
            dbg_msg(dbg_trace, "%s(): pci_disable_device() - complete\n", __FUNCTION__);
673
            list_del(pos);
674
            dbg_msg(dbg_trace, "%s(): list_del() - complete\n", __FUNCTION__);
675
            kfree(brd);
676
            dbg_msg(dbg_trace, "%s(): kfree() - complete\n", __FUNCTION__);
677
        }
678
    }
679
 
680
    mutex_unlock(&pex_mutex);
681
}
682
 
683
//-----------------------------------------------------------------------------
684
 
685
static struct pci_driver pex_pci_driver = {
686
 
687
    .name = PEX_DRIVER_NAME,
688
    .id_table = pex_device_id,
689
    .probe = pex_device_probe,
690
    .remove = pex_device_remove,
691
};
692
 
693
//-----------------------------------------------------------------------------
694
 
695
static int __init pex_module_init(void)
696
{
697
    int error = 0;
698
 
699
    dbg_msg(dbg_trace, "%s()\n", __FUNCTION__);
700
 
701
    mutex_init(&pex_mutex);
702
 
703
    error = alloc_chrdev_region(&devno, 0, MAX_PEXDEVICE_SUPPORT, PEX_DRIVER_NAME);
704
    if(error < 0) {
705
        err_msg(err_trace, "%s(): Erorr allocate char device regions\n", __FUNCTION__);
706
        goto do_out;
707
    }
708
 
709
    dbg_msg(dbg_trace, "%s(): Allocate %d device numbers. Major number = %d\n", __FUNCTION__, MAX_PEXDEVICE_SUPPORT, MAJOR(devno));
710
 
711
    pex_class = class_create(THIS_MODULE, PEX_DRIVER_NAME);
712
    if(!pex_class) {
713
        err_msg(err_trace, "%s(): Erorr allocate char device regions\n", __FUNCTION__);
714
        error = -EINVAL;
715
        goto do_free_chrdev;
716
    }
717
 
718
    error = pci_register_driver(&pex_pci_driver);
719
    if(error < 0) {
720
        err_msg(err_trace, "%s(): Erorr register pci driver\n", __FUNCTION__);
721
        error = -EINVAL;
722
        goto do_delete_class;
723
    }
724
 
725
    return 0;
726
 
727
do_delete_class:
728
    class_destroy(pex_class);
729
 
730
do_free_chrdev:
731
    unregister_chrdev_region(devno, MAX_PEXDEVICE_SUPPORT);
732
 
733
do_out:
734
    return error;
735
}
736
 
737
//-----------------------------------------------------------------------------
738
 
739
static void __exit pex_module_cleanup(void)
740
{
741
    dbg_msg(dbg_trace, "%s()\n", __FUNCTION__);
742
 
743
    pci_unregister_driver(&pex_pci_driver);
744
 
745
    if(pex_class)
746
        class_destroy(pex_class);
747
 
748
    unregister_chrdev_region(devno, MAX_PEXDEVICE_SUPPORT);
749
}
750
 
751
//-----------------------------------------------------------------------------
752
 
753
module_init(pex_module_init);
754
module_exit(pex_module_cleanup);
755
 
756
//-----------------------------------------------------------------------------

powered by: WebSVN 2.1.0

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