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 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
#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 6 v.karak
int dbg_trace = 1;
43 2 dsmv
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 6 v.karak
{
477
        .vendor =       INSYS_VENDOR_ID,
478
        .device =       AMBFMC114V_DEVID,
479
        .subvendor =    PCI_ANY_ID,
480
        .subdevice =    PCI_ANY_ID,
481
},
482
{
483
        .vendor =       INSYS_VENDOR_ID,
484
        .device =       AMBKU_SSCOS_DEVID,
485
        .subvendor =    PCI_ANY_ID,
486
        .subdevice =    PCI_ANY_ID,
487
},
488 2 dsmv
{ },
489
};
490
 
491
MODULE_DEVICE_TABLE(pci, pex_device_id);
492
 
493
//-----------------------------------------------------------------------------
494
 
495
static int  __devinit pex_device_probe(struct pci_dev *dev, const struct pci_device_id *id)
496
{
497
    int error = 0;
498
    int i = 0;
499
    struct pex_device *brd = NULL;
500
 
501
    mutex_lock(&pex_mutex);
502
 
503
    brd = kzalloc(sizeof(struct pex_device), GFP_KERNEL);
504
    if(!brd) {
505
        error = -ENOMEM;
506
        goto do_out;
507
    }
508
 
509
    INIT_LIST_HEAD(&brd->m_list);
510
    mutex_init(&brd->m_BoardMutex);
511
    sema_init(&brd->m_BoardSem, 1);
512
    spin_lock_init(&brd->m_BoardLock);
513
    atomic_set(&brd->m_TotalIRQ, 0);
514
    init_waitqueue_head(&brd->m_WaitQueue);
515
    init_timer(&brd->m_TimeoutTimer);
516
    spin_lock_init(&brd->m_MemListLock);
517
    atomic_set(&brd->m_MemListCount, 0);
518
    INIT_LIST_HEAD(&brd->m_MemList);
519
    brd->m_pci = dev;
520
    brd->m_Interrupt = -1;
521
    brd->m_DmaIrqEnbl = 0;
522
    brd->m_FlgIrqEnbl = 0;
523
    brd->m_class = pex_class;
524
 
525
    set_device_name(brd, dev->device, boards_count);
526
 
527
    dbg_msg(dbg_trace, "%s(): device_id = %x, vendor_id = %x, board name %s\n", __FUNCTION__, dev->device, dev->vendor, brd->m_name);
528
 
529
    error = pci_enable_device(dev);
530
    if(error) {
531
        err_msg(err_trace, "%s(): error enabling pci device\n", __FUNCTION__);
532
        goto do_free_memory;
533
    }
534
 
535
    if (pci_set_dma_mask(dev, DMA_BIT_MASK(64)) || pci_set_consistent_dma_mask(dev, DMA_BIT_MASK(64))) {
536
        printk("%s(): error set pci dma mask\n", __FUNCTION__);
537
        goto do_disable_device;
538
    }
539
 
540
    pci_set_master(dev);
541
 
542
    brd->m_BAR0.physical_address = pci_resource_start(dev, 0);
543
    brd->m_BAR0.size = pci_resource_len(dev, 0);
544
    brd->m_BAR0.virtual_address = ioremap_nocache(brd->m_BAR0.physical_address, brd->m_BAR0.size);
545
    if(!brd->m_BAR0.virtual_address) {
546
        error = -ENOMEM;
547
        err_msg(err_trace, "%s(): error map device memory at bar%d\n", __FUNCTION__, 0);
548
        goto do_disable_device;
549
    }
550
 
551
    dbg_msg(dbg_trace, "%s(): map bar0 %zx -> %p\n", __FUNCTION__, brd->m_BAR0.physical_address, brd->m_BAR0.virtual_address);
552
 
553
    brd->m_BAR1.physical_address = pci_resource_start(dev, 1);
554
    brd->m_BAR1.size = pci_resource_len(dev, 1);
555
    brd->m_BAR1.virtual_address = ioremap_nocache(brd->m_BAR1.physical_address, brd->m_BAR1.size);
556
    if(!brd->m_BAR1.virtual_address) {
557
        error = -ENOMEM;
558
        err_msg(err_trace, "%s(): error map device memory at bar%d\n", __FUNCTION__, 0);
559
        goto do_unmap_bar0;
560
    }
561
 
562
    dbg_msg(dbg_trace, "%s(): map bar1 %zx -> %p\n", __FUNCTION__, brd->m_BAR1.physical_address, brd->m_BAR1.virtual_address);
563
 
564
    error = request_irq(dev->irq, pex_device_isr, IRQF_SHARED, brd->m_name, brd);
565
    if( error < 0) {
566
        error = -EBUSY;
567
        err_msg( err_trace, "%s(): error in request_irq()\n", __FUNCTION__ );
568
        goto do_unmap_bar1;
569
    }
570
 
571
    brd->m_Interrupt = dev->irq;
572
 
573
    cdev_init(&brd->m_cdev, &pex_fops);
574
    brd->m_cdev.owner = THIS_MODULE;
575
    brd->m_cdev.ops = &pex_fops;
576
    brd->m_devno = MKDEV(MAJOR(devno), boards_count);
577
 
578
    error = cdev_add(&brd->m_cdev, brd->m_devno, 1);
579
    if(error) {
580
        err_msg(err_trace, "%s(): Error add char device %d\n", __FUNCTION__, boards_count);
581
        error = -EINVAL;
582
        goto do_free_irq;
583
    }
584
 
585
    dbg_msg(dbg_trace, "%s(): Add cdev %d\n", __FUNCTION__, boards_count);
586
 
587
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
588 6 v.karak
    brd->m_device = device_create(pex_class, NULL, brd->m_devno, "%s%d", "pexdrv", boards_count);
589 2 dsmv
#else
590 6 v.karak
    brd->m_device = device_create(pex_class, NULL, brd->m_devno, NULL, "%s%d", "pexdrv", boards_count);
591 2 dsmv
#endif
592
    if(!brd->m_device ) {
593
        err_msg(err_trace, "%s(): Error create device for board: %s\n", __FUNCTION__, brd->m_name);
594
        error = -EINVAL;
595
        goto do_delete_cdev;
596
    }
597
 
598
    dbg_msg(dbg_trace, "%s(): Create device file for board: %s\n", __FUNCTION__, brd->m_name);
599
 
600
    brd->m_BoardIndex = boards_count;
601
 
602
    InitializeBoard(brd);
603
 
604
    for(i = 0; i < MAX_NUMBER_OF_DMACHANNELS; i++) {
605
 
606
        if(brd->m_DmaChanMask & (1 << i)) {
607
 
608
            brd->m_DmaChannel[i] = CDmaChannelCreate( i,  brd,
609
                                                      &brd->m_pci->dev,
610
                                                      brd->m_MaxDmaSize[i],
611
                                                      brd->m_BlockFifoId[i], 1 );
612
        }
613
    }
614
 
615
    pex_register_proc(brd->m_name, pex_proc_info, brd);
616
 
617
    list_add_tail(&brd->m_list, &device_list);
618
 
619
    boards_count++;
620
 
621
    dbg_msg(dbg_trace, "%s(): Board %s - setup complete\n", __FUNCTION__, brd->m_name);
622
 
623
    mutex_unlock(&pex_mutex);
624
 
625
    return error;
626
 
627
do_delete_cdev:
628
    cdev_del(&brd->m_cdev);
629
 
630
do_free_irq:
631
    free_irq(brd->m_Interrupt, brd);
632
 
633
do_unmap_bar1:
634
    iounmap(brd->m_BAR1.virtual_address);
635
 
636
do_unmap_bar0:
637
    iounmap(brd->m_BAR0.virtual_address);
638
 
639
 
640
do_disable_device:
641
    pci_disable_device(dev);
642
 
643
do_free_memory:
644
    kfree(brd);
645
 
646
do_out:
647
    mutex_unlock(&pex_mutex);
648
 
649
    return error;
650
}
651
 
652
//-----------------------------------------------------------------------------
653
 
654
static void __devexit pex_device_remove(struct pci_dev *dev)
655
{
656
    struct list_head *pos, *n;
657
    struct pex_device *brd = NULL;
658 6 v.karak
    int i = 0;
659 2 dsmv
 
660
    dbg_msg(dbg_trace, "%s(): device_id = %x, vendor_id = %x\n", __FUNCTION__, dev->device, dev->vendor);
661
 
662
    mutex_lock(&pex_mutex);
663
 
664
    list_for_each_safe(pos, n, &device_list) {
665
 
666
        brd = list_entry(pos, struct pex_device, m_list);
667
 
668
        if(brd->m_pci == dev) {
669
 
670
            free_irq(brd->m_Interrupt, brd);
671
            dbg_msg(dbg_trace, "%s(): free_irq() - complete\n", __FUNCTION__);
672
            pex_remove_proc(brd->m_name);
673
            dbg_msg(dbg_trace, "%s(): pex_remove_proc() - complete\n", __FUNCTION__);
674 6 v.karak
            for(i = 0; i < MAX_NUMBER_OF_DMACHANNELS; i++) {
675
                if(brd->m_DmaChannel[i]) {
676
                     CDmaChannelDelete(brd->m_DmaChannel[i]);
677
                     dbg_msg(dbg_trace, "%s(): free DMA channel %d - complete\n", __FUNCTION__, i);
678
                }
679
            }
680 2 dsmv
            free_memory(brd);
681
            dbg_msg(dbg_trace, "%s(): free_memory() - complete\n", __FUNCTION__);
682
            device_destroy(pex_class, brd->m_devno);
683
            dbg_msg(dbg_trace, "%s(): device_destroy() - complete\n", __FUNCTION__);
684
            cdev_del(&brd->m_cdev);
685
            dbg_msg(dbg_trace, "%s(): cdev_del() - complete\n", __FUNCTION__);
686
            iounmap(brd->m_BAR1.virtual_address);
687
            dbg_msg(dbg_trace, "%s(): iounmap() - complete\n", __FUNCTION__);
688
            iounmap(brd->m_BAR0.virtual_address);
689
            dbg_msg(dbg_trace, "%s(): iounmap() - complete\n", __FUNCTION__);
690
            pci_disable_device(dev);
691
            dbg_msg(dbg_trace, "%s(): pci_disable_device() - complete\n", __FUNCTION__);
692
            list_del(pos);
693
            dbg_msg(dbg_trace, "%s(): list_del() - complete\n", __FUNCTION__);
694
            kfree(brd);
695
            dbg_msg(dbg_trace, "%s(): kfree() - complete\n", __FUNCTION__);
696
        }
697
    }
698
 
699
    mutex_unlock(&pex_mutex);
700
}
701
 
702
//-----------------------------------------------------------------------------
703
 
704
static struct pci_driver pex_pci_driver = {
705
 
706
    .name = PEX_DRIVER_NAME,
707
    .id_table = pex_device_id,
708
    .probe = pex_device_probe,
709
    .remove = pex_device_remove,
710
};
711
 
712
//-----------------------------------------------------------------------------
713
 
714
static int __init pex_module_init(void)
715
{
716
    int error = 0;
717
 
718
    dbg_msg(dbg_trace, "%s()\n", __FUNCTION__);
719
 
720
    mutex_init(&pex_mutex);
721
 
722
    error = alloc_chrdev_region(&devno, 0, MAX_PEXDEVICE_SUPPORT, PEX_DRIVER_NAME);
723
    if(error < 0) {
724
        err_msg(err_trace, "%s(): Erorr allocate char device regions\n", __FUNCTION__);
725
        goto do_out;
726
    }
727
 
728
    dbg_msg(dbg_trace, "%s(): Allocate %d device numbers. Major number = %d\n", __FUNCTION__, MAX_PEXDEVICE_SUPPORT, MAJOR(devno));
729
 
730
    pex_class = class_create(THIS_MODULE, PEX_DRIVER_NAME);
731
    if(!pex_class) {
732
        err_msg(err_trace, "%s(): Erorr allocate char device regions\n", __FUNCTION__);
733
        error = -EINVAL;
734
        goto do_free_chrdev;
735
    }
736
 
737
    error = pci_register_driver(&pex_pci_driver);
738
    if(error < 0) {
739
        err_msg(err_trace, "%s(): Erorr register pci driver\n", __FUNCTION__);
740
        error = -EINVAL;
741
        goto do_delete_class;
742
    }
743
 
744
    return 0;
745
 
746
do_delete_class:
747
    class_destroy(pex_class);
748
 
749
do_free_chrdev:
750
    unregister_chrdev_region(devno, MAX_PEXDEVICE_SUPPORT);
751
 
752
do_out:
753
    return error;
754
}
755
 
756
//-----------------------------------------------------------------------------
757
 
758
static void __exit pex_module_cleanup(void)
759
{
760
    dbg_msg(dbg_trace, "%s()\n", __FUNCTION__);
761
 
762
    pci_unregister_driver(&pex_pci_driver);
763
 
764
    if(pex_class)
765
        class_destroy(pex_class);
766
 
767
    unregister_chrdev_region(devno, MAX_PEXDEVICE_SUPPORT);
768
}
769
 
770
//-----------------------------------------------------------------------------
771
 
772
module_init(pex_module_init);
773
module_exit(pex_module_cleanup);
774
 
775
//-----------------------------------------------------------------------------

powered by: WebSVN 2.1.0

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