3 Copyright 1996,2002,2005 Gregory D. Hager, Alfred A. Rizzi, Noah J. Cowan,
4 Jason Lapenta, Scott Smedley, Greg Sharp
6 This file is part of the DT3155 Device Driver.
8 The DT3155 Device Driver is free software; you can redistribute it
9 and/or modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2 of the
11 License, or (at your option) any later version.
13 The DT3155 Device Driver is distributed in the hope that it will be
14 useful, but WITHOUT ANY WARRANTY; without even the implied warranty
15 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with the DT3155 Device Driver; if not, write to the Free
20 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
25 Date Programmer Description of changes made
26 -------------------------------------------------------------------
28 10-Oct-2001 SS port to 2.4 kernel
29 02-Apr-2002 SS Mods to use allocator as a standalone module;
30 Merged John Roll's changes (john@cfa.harvard.edu)
31 to make work with multiple boards.
32 02-Jul-2002 SS Merged James Rose's chages (rosejr@purdue.edu) to:
33 * fix successive interrupt-driven captures
34 * add select/poll support.
35 10-Jul-2002 GCS Add error check when ndevices > MAXBOARDS.
36 02-Aug-2002 GCS Fix field mode so that odd (lower) field is stored
37 in lower half of buffer.
38 05-Aug-2005 SS port to 2.6 kernel.
39 26-Oct-2009 SS port to 2.6.30 kernel.
43 ** appended "mem=124" in lilo.conf to allow for 4megs free on my 128meg system.
44 * using allocator.c and allocator.h from o'reilly book (alessandro rubini)
45 ftp://ftp.systemy.it/pub/develop (see README.allocator)
47 + might want to get rid of MAXboards for allocating initial buffer.
48 confusing and not necessary
50 + in cleanup_module the MOD_IN_USE looks like it is check after it should
52 * GFP_DMA should not be set with a PCI system (pg 291)
54 - NJC why are only two buffers allowed? (see isr, approx line 358)
58 extern void printques(int);
60 #include <linux/module.h>
61 #include <linux/interrupt.h>
62 #include <linux/pci.h>
63 #include <linux/types.h>
64 #include <linux/poll.h>
65 #include <linux/sched.h>
66 #include <linux/smp_lock.h>
69 #include <asm/uaccess.h>
72 #include "dt3155_drv.h"
73 #include "dt3155_isr.h"
74 #include "dt3155_io.h"
75 #include "allocator.h"
78 MODULE_LICENSE("GPL");
80 /* Error variable. Zero means no error. */
83 #ifndef PCI_DEVICE_ID_INTEL_7116
84 #define PCI_DEVICE_ID_INTEL_7116 0x1223
87 #define DT3155_VENDORID PCI_VENDOR_ID_INTEL
88 #define DT3155_DEVICEID PCI_DEVICE_ID_INTEL_7116
92 #define DT_3155_DEBUG_MSG(x,y) printk(x,y)
94 #define DT_3155_DEBUG_MSG(x,y)
97 /* wait queue for interrupts */
98 wait_queue_head_t dt3155_read_wait_queue
[MAXBOARDS
];
100 /* set to dynamicaly allocate, but it is tunable: */
101 /* insmod DT_3155 dt3155 dt3155_major=XX */
102 int dt3155_major
= 0;
104 /* The minor numbers are 0 and 1 ... they are not tunable.
105 * They are used as the indices for the structure vectors,
106 * and register address vectors
109 /* Global structures and variables */
111 /* Status of each device */
112 struct dt3155_status dt3155_status
[MAXBOARDS
];
114 /* kernel logical address of the board */
115 static void __iomem
*dt3155_lbase
[MAXBOARDS
] = { NULL
121 u32 dt3155_dev_open
[MAXBOARDS
] = {0
132 * Stops interrupt generation right away and resets the status
133 * to idle. I don't know why this works and the other way doesn't.
136 static void quick_stop (int minor
)
138 // TODO: scott was here
140 int_csr_r
.reg
= readl(dt3155_lbase
[minor
] + INT_CSR
);
141 /* disable interrupts */
142 int_csr_r
.fld
.FLD_END_EVE_EN
= 0;
143 int_csr_r
.fld
.FLD_END_ODD_EN
= 0;
144 writel(int_csr_r
.reg
, dt3155_lbase
[minor
] + INT_CSR
);
146 dt3155_status
[minor
].state
&= ~(DT3155_STATE_STOP
|0xff);
147 /* mark the system stopped: */
148 dt3155_status
[minor
].state
|= DT3155_STATE_IDLE
;
149 dt3155_fbuffer
[minor
]->stop_acquire
= 0;
150 dt3155_fbuffer
[minor
]->even_stopped
= 0;
152 dt3155_status
[minor
].state
|= DT3155_STATE_STOP
;
153 dt3155_status
[minor
].fbuffer
.stop_acquire
= 1;
159 /*****************************************************
160 * dt3155_isr() Interrupt service routien
162 * - looks like this isr supports IRQ sharing (or could) JML
163 * - Assumes irq's are disabled, via SA_INTERRUPT flag
164 * being set in request_irq() call from init_module()
165 *****************************************************/
166 static void dt3155_isr(int irq
, void *dev_id
, struct pt_regs
*regs
)
174 /* find out who issued the interrupt */
175 for (index
= 0; index
< ndevices
; index
++) {
176 if(dev_id
== (void*) &dt3155_status
[index
])
183 /* hopefully we should not get here */
184 if (minor
< 0 || minor
>= MAXBOARDS
) {
185 printk(KERN_ERR
"dt3155_isr called with invalid dev_id\n");
189 mmio
= dt3155_lbase
[minor
];
191 /* Check for corruption and set a flag if so */
192 csr1_r
.reg
= readl(mmio
+ CSR1
);
194 if ((csr1_r
.fld
.FLD_CRPT_EVE
) || (csr1_r
.fld
.FLD_CRPT_ODD
))
196 /* TODO: this should probably stop acquisition */
197 /* and set some flags so that dt3155_read */
198 /* returns an error next time it is called */
199 dt3155_errno
= DT_ERR_CORRUPT
;
200 printk("dt3155: corrupt field\n");
204 int_csr_r
.reg
= readl(mmio
+ INT_CSR
);
206 /* Handle the even field ... */
207 if (int_csr_r
.fld
.FLD_END_EVE
)
209 if ((dt3155_status
[minor
].state
& DT3155_STATE_MODE
) ==
212 dt3155_fbuffer
[minor
]->frame_count
++;
215 ReadI2C(mmio
, EVEN_CSR
, &i2c_even_csr
.reg
);
217 /* Clear the interrupt? */
218 int_csr_r
.fld
.FLD_END_EVE
= 1;
220 /* disable the interrupt if last field */
221 if (dt3155_fbuffer
[minor
]->stop_acquire
)
223 printk("dt3155: even stopped.\n");
224 dt3155_fbuffer
[minor
]->even_stopped
= 1;
225 if (i2c_even_csr
.fld
.SNGL_EVE
)
227 int_csr_r
.fld
.FLD_END_EVE_EN
= 0;
231 i2c_even_csr
.fld
.SNGL_EVE
= 1;
235 writel(int_csr_r
.reg
, mmio
+ INT_CSR
);
237 /* Set up next DMA if we are doing FIELDS */
238 if ((dt3155_status
[minor
].state
& DT3155_STATE_MODE
) ==
241 /* GCS (Aug 2, 2002) -- In field mode, dma the odd field
242 into the lower half of the buffer */
243 const u32 stride
= dt3155_status
[minor
].config
.cols
;
244 buffer_addr
= dt3155_fbuffer
[minor
]->
245 frame_info
[dt3155_fbuffer
[minor
]->active_buf
].addr
246 + (DT3155_MAX_ROWS
/ 2) * stride
;
247 local_save_flags(flags
);
249 wake_up_interruptible(&dt3155_read_wait_queue
[minor
]);
251 /* Set up the DMA address for the next field */
252 local_irq_restore(flags
);
253 writel(buffer_addr
, mmio
+ ODD_DMA_START
);
256 /* Check for errors. */
257 i2c_even_csr
.fld
.DONE_EVE
= 1;
258 if (i2c_even_csr
.fld
.ERROR_EVE
)
259 dt3155_errno
= DT_ERR_OVERRUN
;
261 WriteI2C(mmio
, EVEN_CSR
, i2c_even_csr
.reg
);
263 /* Note that we actually saw an even field meaning */
264 /* that subsequent odd field complete the frame */
265 dt3155_fbuffer
[minor
]->even_happened
= 1;
267 /* recording the time that the even field finished, this should be */
268 /* about time in the middle of the frame */
269 do_gettimeofday(&(dt3155_fbuffer
[minor
]->
270 frame_info
[dt3155_fbuffer
[minor
]->
275 /* ... now handle the odd field */
276 if (int_csr_r
.fld
.FLD_END_ODD
)
278 ReadI2C(mmio
, ODD_CSR
, &i2c_odd_csr
.reg
);
280 /* Clear the interrupt? */
281 int_csr_r
.fld
.FLD_END_ODD
= 1;
283 if (dt3155_fbuffer
[minor
]->even_happened
||
284 (dt3155_status
[minor
].state
& DT3155_STATE_MODE
) ==
287 dt3155_fbuffer
[minor
]->frame_count
++;
290 if (dt3155_fbuffer
[minor
]->stop_acquire
&&
291 dt3155_fbuffer
[minor
]->even_stopped
)
293 printk(KERN_DEBUG
"dt3155: stopping odd..\n");
294 if (i2c_odd_csr
.fld
.SNGL_ODD
)
296 /* disable interrupts */
297 int_csr_r
.fld
.FLD_END_ODD_EN
= 0;
298 dt3155_status
[minor
].state
&= ~(DT3155_STATE_STOP
|0xff);
300 /* mark the system stopped: */
301 dt3155_status
[minor
].state
|= DT3155_STATE_IDLE
;
302 dt3155_fbuffer
[minor
]->stop_acquire
= 0;
303 dt3155_fbuffer
[minor
]->even_stopped
= 0;
305 printk(KERN_DEBUG
"dt3155: state is now %x\n",
306 dt3155_status
[minor
].state
);
310 i2c_odd_csr
.fld
.SNGL_ODD
= 1;
314 writel(int_csr_r
.reg
, mmio
+ INT_CSR
);
316 /* if the odd field has been acquired, then */
317 /* change the next dma location for both fields */
318 /* and wake up the process if sleeping */
319 if (dt3155_fbuffer
[minor
]->even_happened
||
320 (dt3155_status
[minor
].state
& DT3155_STATE_MODE
) ==
324 local_save_flags(flags
);
330 if (dt3155_fbuffer
[minor
]->nbuffers
> 2)
332 if (!are_empty_buffers(minor
))
334 /* The number of active + locked buffers is
335 * at most 2, and since there are none empty, there
336 * must be at least nbuffers-2 ready buffers.
337 * This is where we 'drop frames', oldest first. */
338 push_empty(pop_ready(minor
), minor
);
341 /* The ready_que can't be full, since we know
342 * there is one active buffer right now, so it's safe
343 * to push the active buf on the ready_que. */
344 push_ready(minor
, dt3155_fbuffer
[minor
]->active_buf
);
345 /* There's at least 1 empty -- make it active */
346 dt3155_fbuffer
[minor
]->active_buf
= pop_empty(minor
);
347 dt3155_fbuffer
[minor
]->
348 frame_info
[dt3155_fbuffer
[minor
]->
349 active_buf
].tag
= ++unique_tag
;
351 else /* nbuffers == 2, special case */
352 { /* There is 1 active buffer.
353 * If there is a locked buffer, keep the active buffer
354 * the same -- that means we drop a frame.
356 if (dt3155_fbuffer
[minor
]->locked_buf
< 0)
359 dt3155_fbuffer
[minor
]->active_buf
);
360 if (are_empty_buffers(minor
))
362 dt3155_fbuffer
[minor
]->active_buf
=
366 { /* no empty or locked buffers, so use a readybuf */
367 dt3155_fbuffer
[minor
]->active_buf
=
377 dt3155_fbuffer
[minor
]->even_happened
= 0;
379 wake_up_interruptible(&dt3155_read_wait_queue
[minor
]);
381 local_irq_restore(flags
);
385 /* Set up the DMA address for the next frame/field */
386 buffer_addr
= dt3155_fbuffer
[minor
]->
387 frame_info
[dt3155_fbuffer
[minor
]->active_buf
].addr
;
388 if ((dt3155_status
[minor
].state
& DT3155_STATE_MODE
) ==
391 writel(buffer_addr
, mmio
+ EVEN_DMA_START
);
395 writel(buffer_addr
, mmio
+ EVEN_DMA_START
);
397 writel(buffer_addr
+ dt3155_status
[minor
].config
.cols
,
398 mmio
+ ODD_DMA_START
);
401 /* Do error checking */
402 i2c_odd_csr
.fld
.DONE_ODD
= 1;
403 if (i2c_odd_csr
.fld
.ERROR_ODD
)
404 dt3155_errno
= DT_ERR_OVERRUN
;
406 WriteI2C(mmio
, ODD_CSR
, i2c_odd_csr
.reg
);
410 /* If we get here, the Odd Field wasn't it either... */
411 printk("neither even nor odd. shared perhaps?\n");
414 /*****************************************************
415 * init_isr(int minor)
416 * turns on interupt generation for the card
417 * designated by "minor".
418 * It is called *only* from inside ioctl().
419 *****************************************************/
420 static void dt3155_init_isr(int minor
)
422 const u32 stride
= dt3155_status
[minor
].config
.cols
;
423 void __iomem
*mmio
= dt3155_lbase
[minor
];
425 switch (dt3155_status
[minor
].state
& DT3155_STATE_MODE
)
427 case DT3155_STATE_FLD
:
429 even_dma_start_r
= dt3155_status
[minor
].
430 fbuffer
.frame_info
[dt3155_status
[minor
].fbuffer
.active_buf
].addr
;
431 even_dma_stride_r
= 0;
432 odd_dma_stride_r
= 0;
434 writel(even_dma_start_r
, mmio
+ EVEN_DMA_START
);
435 writel(even_dma_stride_r
, mmio
+ EVEN_DMA_STRIDE
);
436 writel(odd_dma_stride_r
, mmio
+ ODD_DMA_STRIDE
);
440 case DT3155_STATE_FRAME
:
443 even_dma_start_r
= dt3155_status
[minor
].
444 fbuffer
.frame_info
[dt3155_status
[minor
].fbuffer
.active_buf
].addr
;
445 odd_dma_start_r
= even_dma_start_r
+ stride
;
446 even_dma_stride_r
= stride
;
447 odd_dma_stride_r
= stride
;
449 writel(even_dma_start_r
, mmio
+ EVEN_DMA_START
);
450 writel(odd_dma_start_r
, mmio
+ ODD_DMA_START
);
451 writel(even_dma_stride_r
, mmio
+ EVEN_DMA_STRIDE
);
452 writel(odd_dma_stride_r
, mmio
+ ODD_DMA_STRIDE
);
457 /* 50/60 Hz should be set before this point but let's make sure it is */
460 ReadI2C(mmio
, CSR2
, &i2c_csr2
.reg
);
461 i2c_csr2
.fld
.HZ50
= FORMAT50HZ
;
462 WriteI2C(mmio
, CSR2
, i2c_csr2
.reg
);
464 /* enable busmaster chip, clear flags */
468 * shouldn't we be concered with continuous values of
469 * DT3155_SNAP & DT3155_ACQ here? (SS)
473 csr1_r
.fld
.CAP_CONT_EVE
= 1; /* use continuous capture bits to */
474 csr1_r
.fld
.CAP_CONT_ODD
= 1; /* enable */
475 csr1_r
.fld
.FLD_DN_EVE
= 1; /* writing a 1 clears flags */
476 csr1_r
.fld
.FLD_DN_ODD
= 1;
477 csr1_r
.fld
.SRST
= 1; /* reset - must be 1 */
478 csr1_r
.fld
.FIFO_EN
= 1; /* fifo control - must be 1 */
479 csr1_r
.fld
.FLD_CRPT_EVE
= 1; /* writing a 1 clears flags */
480 csr1_r
.fld
.FLD_CRPT_ODD
= 1;
482 writel(csr1_r
.reg
, mmio
+ CSR1
);
484 /* Enable interrupts at the end of each field */
487 int_csr_r
.fld
.FLD_END_EVE_EN
= 1;
488 int_csr_r
.fld
.FLD_END_ODD_EN
= 1;
489 int_csr_r
.fld
.FLD_START_EN
= 0;
491 writel(int_csr_r
.reg
, mmio
+ INT_CSR
);
493 /* start internal BUSY bits */
495 ReadI2C(mmio
, CSR2
, &i2c_csr2
.reg
);
496 i2c_csr2
.fld
.BUSY_ODD
= 1;
497 i2c_csr2
.fld
.BUSY_EVE
= 1;
498 WriteI2C(mmio
, CSR2
, i2c_csr2
.reg
);
500 /* Now its up to the interrupt routine!! */
506 /*****************************************************
509 *****************************************************/
510 static int dt3155_ioctl(struct inode
*inode
,
515 int minor
= MINOR(inode
->i_rdev
); /* What device are we ioctl()'ing? */
516 void __user
*up
= (void __user
*)arg
;
518 if (minor
>= MAXBOARDS
|| minor
< 0)
521 /* make sure it is valid command */
522 if (_IOC_NR(cmd
) > DT3155_IOC_MAXNR
)
524 printk("DT3155: invalid IOCTL(0x%x)\n",cmd
);
525 printk("DT3155: Valid commands (0x%x), (0x%x), (0x%x), (0x%x), (0x%x)\n",
526 (unsigned int)DT3155_GET_CONFIG
,
527 (unsigned int)DT3155_SET_CONFIG
,
528 (unsigned int)DT3155_START
,
529 (unsigned int)DT3155_STOP
,
530 (unsigned int)DT3155_FLUSH
);
536 case DT3155_SET_CONFIG
:
538 if (dt3155_status
[minor
].state
!= DT3155_STATE_IDLE
)
542 struct dt3155_config tmp
;
543 if (copy_from_user(&tmp
, up
, sizeof(tmp
)))
545 /* check for valid settings */
546 if (tmp
.rows
> DT3155_MAX_ROWS
||
547 tmp
.cols
> DT3155_MAX_COLS
||
548 (tmp
.acq_mode
!= DT3155_MODE_FRAME
&&
549 tmp
.acq_mode
!= DT3155_MODE_FIELD
) ||
550 (tmp
.continuous
!= DT3155_SNAP
&&
551 tmp
.continuous
!= DT3155_ACQ
))
555 dt3155_status
[minor
].config
= tmp
;
559 case DT3155_GET_CONFIG
:
561 if (copy_to_user(up
, &dt3155_status
[minor
],
562 sizeof(struct dt3155_status
)))
566 case DT3155_FLUSH
: /* Flushes the buffers -- ensures fresh data */
568 if (dt3155_status
[minor
].state
!= DT3155_STATE_IDLE
)
570 return dt3155_flush(minor
);
574 if (dt3155_status
[minor
].state
& DT3155_STATE_STOP
||
575 dt3155_status
[minor
].fbuffer
.stop_acquire
)
578 if (dt3155_status
[minor
].state
== DT3155_STATE_IDLE
)
582 if (copy_to_user(up
, &dt3155_status
[minor
],
583 sizeof(struct dt3155_status
)))
589 if (dt3155_status
[minor
].state
!= DT3155_STATE_IDLE
)
592 dt3155_status
[minor
].fbuffer
.stop_acquire
= 0;
593 dt3155_status
[minor
].fbuffer
.frame_count
= 0;
595 /* Set the MODE in the status -- we default to FRAME */
596 if (dt3155_status
[minor
].config
.acq_mode
== DT3155_MODE_FIELD
)
598 dt3155_status
[minor
].state
= DT3155_STATE_FLD
;
602 dt3155_status
[minor
].state
= DT3155_STATE_FRAME
;
605 dt3155_init_isr(minor
);
606 if (copy_to_user(up
, &dt3155_status
[minor
],
607 sizeof(struct dt3155_status
)))
613 printk("DT3155: invalid IOCTL(0x%x)\n",cmd
);
614 printk("DT3155: Valid commands (0x%x), (0x%x), (0x%x), (0x%x), (0x%x)\n",
615 (unsigned int)DT3155_GET_CONFIG
,
616 (unsigned int)DT3155_SET_CONFIG
,
617 DT3155_START
, DT3155_STOP
, DT3155_FLUSH
);
624 /*****************************************************
627 * only allow the user to mmap the registers and buffer
628 * It is quite possible that this is broken, since the
629 * addition of of the capacity for two cards!!!!!!!!
630 * It *looks* like it should work but since I'm not
631 * sure how to use it, I'm not actually sure. (NJC? ditto by SS)
632 *****************************************************/
633 static int dt3155_mmap (struct file
* file
, struct vm_area_struct
* vma
)
635 /* which device are we mmapping? */
636 int minor
= MINOR(file
->f_dentry
->d_inode
->i_rdev
);
637 unsigned long offset
;
638 offset
= vma
->vm_pgoff
<< PAGE_SHIFT
;
640 if (offset
>= __pa(high_memory
) || (file
->f_flags
& O_SYNC
))
641 vma
->vm_flags
|= VM_IO
;
643 /* Don't try to swap out physical pages.. */
644 vma
->vm_flags
|= VM_RESERVED
;
646 /* they are mapping the registers or the buffer */
647 if ((offset
== dt3155_status
[minor
].reg_addr
&&
648 vma
->vm_end
- vma
->vm_start
== PCI_PAGE_SIZE
) ||
649 (offset
== dt3155_status
[minor
].mem_addr
&&
650 vma
->vm_end
- vma
->vm_start
== dt3155_status
[minor
].mem_size
))
652 if (remap_pfn_range(vma
,
654 offset
>> PAGE_SHIFT
,
655 vma
->vm_end
- vma
->vm_start
,
656 vma
->vm_page_prot
)) {
657 printk("DT3155: remap_page_range() failed.\n");
663 printk("DT3155: dt3155_mmap() bad call.\n");
671 /*****************************************************
674 * Our special open code.
675 * MOD_INC_USE_COUNT make sure that the driver memory is not freed
676 * while the device is in use.
677 *****************************************************/
678 static int dt3155_open(struct inode
* inode
, struct file
* filep
)
680 int minor
= MINOR(inode
->i_rdev
); /* what device are we opening? */
681 if (dt3155_dev_open
[minor
]) {
682 printk ("DT3155: Already opened by another process.\n");
686 if (dt3155_status
[minor
].device_installed
==0)
688 printk("DT3155 Open Error: No such device dt3155 minor number %d\n",
693 if (dt3155_status
[minor
].state
!= DT3155_STATE_IDLE
) {
694 printk ("DT3155: Not in idle state (state = %x)\n",
695 dt3155_status
[minor
].state
);
699 printk("DT3155: Device opened.\n");
701 dt3155_dev_open
[minor
] = 1 ;
705 /* Disable ALL interrupts */
707 writel(int_csr_r
.reg
, dt3155_lbase
[minor
] + INT_CSR
);
709 init_waitqueue_head(&(dt3155_read_wait_queue
[minor
]));
715 /*****************************************************
718 * Now decrement the use count.
720 *****************************************************/
721 static int dt3155_close(struct inode
*inode
, struct file
*filep
)
725 minor
= MINOR(inode
->i_rdev
); /* which device are we closing */
726 if (!dt3155_dev_open
[minor
])
728 printk("DT3155: attempt to CLOSE a not OPEN device\n");
732 dt3155_dev_open
[minor
] = 0;
734 if (dt3155_status
[minor
].state
!= DT3155_STATE_IDLE
)
742 /*****************************************************
745 *****************************************************/
746 static ssize_t
dt3155_read(struct file
*filep
, char __user
*buf
,
747 size_t count
, loff_t
*ppos
)
749 /* which device are we reading from? */
750 int minor
= MINOR(filep
->f_dentry
->d_inode
->i_rdev
);
753 struct frame_info
*frame_info
;
755 /* TODO: this should check the error flag and */
756 /* return an error on hardware failures */
757 if (count
!= sizeof(struct dt3155_read
))
759 printk("DT3155 ERROR (NJC): count is not right\n");
764 /* Hack here -- I'm going to allow reading even when idle.
765 * this is so that the frames can be read after STOP has
766 * been called. Leaving it here, commented out, as a reminder
767 * for a short while to make sure there are no problems.
768 * Note that if the driver is not opened in non_blocking mode,
769 * and the device is idle, then it could sit here forever! */
771 /* if (dt3155_status[minor].state == DT3155_STATE_IDLE)*/
774 /* non-blocking reads should return if no data */
775 if (filep
->f_flags
& O_NDELAY
)
777 if ((frame_index
= dt3155_get_ready_buffer(minor
)) < 0) {
778 /*printk("dt3155: no buffers available (?)\n");*/
779 /* printques(minor); */
786 * sleep till data arrives , or we get interrupted.
787 * Note that wait_event_interruptible() does not actually
788 * sleep/wait if it's condition evaluates to true upon entry.
790 wait_event_interruptible(dt3155_read_wait_queue
[minor
],
791 (frame_index
= dt3155_get_ready_buffer(minor
))
796 printk ("DT3155: read: interrupted\n");
803 frame_info
= &dt3155_status
[minor
].fbuffer
.frame_info
[frame_index
];
805 /* make this an offset */
806 offset
= frame_info
->addr
- dt3155_status
[minor
].mem_addr
;
808 put_user(offset
, (unsigned int __user
*)buf
);
810 put_user(dt3155_status
[minor
].fbuffer
.frame_count
, (unsigned int __user
*)buf
);
812 put_user(dt3155_status
[minor
].state
, (unsigned int __user
*)buf
);
814 if (copy_to_user(buf
, frame_info
, sizeof(*frame_info
)))
817 return sizeof(struct dt3155_read
);
820 static unsigned int dt3155_poll (struct file
* filp
, poll_table
*wait
)
822 int minor
= MINOR(filp
->f_dentry
->d_inode
->i_rdev
);
824 if (!is_ready_buf_empty(minor
))
825 return POLLIN
| POLLRDNORM
;
827 poll_wait (filp
, &dt3155_read_wait_queue
[minor
], wait
);
833 dt3155_unlocked_ioctl(struct file
*file
, unsigned int cmd
, unsigned long arg
)
838 ret
= dt3155_ioctl(file
->f_path
.dentry
->d_inode
, file
, cmd
, arg
);
844 /*****************************************************
845 * file operations supported by DT3155 driver
846 * needed by init_module
848 *****************************************************/
849 static struct file_operations dt3155_fops
= {
851 .unlocked_ioctl
= dt3155_unlocked_ioctl
,
855 .release
= dt3155_close
859 /*****************************************************
862 * PCI has been totally reworked in 2.1..
863 *****************************************************/
864 static int find_PCI (void)
866 struct pci_dev
*pci_dev
= NULL
;
867 int error
, pci_index
= 0;
868 unsigned short rev_device
;
872 while ((pci_dev
= pci_get_device
873 (DT3155_VENDORID
, DT3155_DEVICEID
, pci_dev
)) != NULL
)
877 /* Is it really there? */
879 pci_read_config_word(pci_dev
, PCI_CLASS_DEVICE
, &rev_device
)))
883 DT_3155_DEBUG_MSG("DT3155: Device number %d \n", pci_index
);
885 /* Make sure the driver was compiled with enough buffers to handle
887 if (pci_index
> MAXBOARDS
) {
888 printk("DT3155: ERROR - found %d devices, but driver only configured "
890 "DT3155: Please change MAXBOARDS in dt3155.h\n",
891 pci_index
, MAXBOARDS
);
895 /* Now, just go out and make sure that this/these device(s) is/are
896 actually mapped into the kernel address space */
897 if ((error
= pci_read_config_dword(pci_dev
, PCI_BASE_ADDRESS_0
,
900 printk("DT3155: Was not able to find device \n");
904 DT_3155_DEBUG_MSG("DT3155: Base address 0 for device is %lx \n", base
);
905 dt3155_status
[pci_index
-1].reg_addr
= base
;
907 /* Remap the base address to a logical address through which we
909 dt3155_lbase
[pci_index
- 1] = ioremap(base
, PCI_PAGE_SIZE
);
910 dt3155_status
[pci_index
- 1].reg_addr
= base
;
911 DT_3155_DEBUG_MSG("DT3155: New logical address is %p \n",
912 dt3155_lbase
[pci_index
-1]);
913 if (!dt3155_lbase
[pci_index
-1])
915 printk("DT3155: Unable to remap control registers\n");
919 if ((error
= pci_read_config_byte(pci_dev
, PCI_INTERRUPT_LINE
, &irq
)))
921 printk("DT3155: Was not able to find device \n");
925 DT_3155_DEBUG_MSG("DT3155: IRQ is %d \n",irq
);
926 dt3155_status
[pci_index
-1].irq
= irq
;
927 /* Set flag: kth device found! */
928 dt3155_status
[pci_index
-1].device_installed
= 1;
929 printk("DT3155: Installing device %d w/irq %d and address %p\n",
931 dt3155_status
[pci_index
-1].irq
,
932 dt3155_lbase
[pci_index
-1]);
935 ndevices
= pci_index
;
940 pci_dev_put(pci_dev
);
944 u32 allocatorAddr
= 0;
946 /*****************************************************
948 *****************************************************/
949 int init_module(void)
953 char *devname
[MAXBOARDS
];
955 devname
[0] = "dt3155a";
957 devname
[1] = "dt3155b";
960 printk("DT3155: Loading module...\n");
962 /* Register the device driver */
963 rcode
= register_chrdev(dt3155_major
, "dt3155", &dt3155_fops
);
966 printk(KERN_INFO
"DT3155: register_chrdev failed \n");
970 if(dt3155_major
== 0)
971 dt3155_major
= rcode
; /* dynamic */
974 /* init the status variables. */
975 /* DMA memory is taken care of in setup_buffers() */
976 for (index
= 0; index
< MAXBOARDS
; index
++)
978 dt3155_status
[index
].config
.acq_mode
= DT3155_MODE_FRAME
;
979 dt3155_status
[index
].config
.continuous
= DT3155_ACQ
;
980 dt3155_status
[index
].config
.cols
= DT3155_MAX_COLS
;
981 dt3155_status
[index
].config
.rows
= DT3155_MAX_ROWS
;
982 dt3155_status
[index
].state
= DT3155_STATE_IDLE
;
984 /* find_PCI() will check if devices are installed; */
985 /* first assume they're not: */
986 dt3155_status
[index
].mem_addr
= 0;
987 dt3155_status
[index
].mem_size
= 0;
988 dt3155_status
[index
].state
= DT3155_STATE_IDLE
;
989 dt3155_status
[index
].device_installed
= 0;
992 /* Now let's find the hardware. find_PCI() will set ndevices to the
993 * number of cards found in this machine. */
995 if ((rcode
= find_PCI()) != 0)
997 printk("DT3155 error: find_PCI() failed to find dt3155 board(s)\n");
998 unregister_chrdev(dt3155_major
, "dt3155");
1003 /* Ok, time to setup the frame buffers */
1004 if((rcode
= dt3155_setup_buffers(&allocatorAddr
)) < 0)
1006 printk("DT3155: Error: setting up buffer not large enough.");
1007 unregister_chrdev(dt3155_major
, "dt3155");
1011 /* If we are this far, then there is enough RAM */
1012 /* for the buffers: Print the configuration. */
1013 for( index
= 0; index
< ndevices
; index
++)
1015 printk("DT3155: Device = %d; acq_mode = %d; "
1016 "continuous = %d; cols = %d; rows = %d;\n",
1018 dt3155_status
[index
].config
.acq_mode
,
1019 dt3155_status
[index
].config
.continuous
,
1020 dt3155_status
[index
].config
.cols
,
1021 dt3155_status
[index
].config
.rows
);
1022 printk("DT3155: m_addr = 0x%x; m_size = %ld; "
1023 "state = %d; device_installed = %d\n",
1024 dt3155_status
[index
].mem_addr
,
1025 (long int)dt3155_status
[index
].mem_size
,
1026 dt3155_status
[index
].state
,
1027 dt3155_status
[index
].device_installed
);
1030 /* Disable ALL interrupts */
1032 for( index
= 0; index
< ndevices
; index
++)
1034 writel(int_csr_r
.reg
, dt3155_lbase
[index
] + INT_CSR
);
1035 if(dt3155_status
[index
].device_installed
)
1038 * This driver *looks* like it can handle sharing interrupts,
1039 * but I can't actually test myself. I've had reports that it
1040 * DOES work so I'll enable it for now. This comment will remain
1041 * as a reminder in case any problems arise. (SS)
1043 /* in older kernels flags are: SA_SHIRQ | SA_INTERRUPT */
1044 rcode
= request_irq(dt3155_status
[index
].irq
, (void *)dt3155_isr
,
1045 IRQF_SHARED
| IRQF_DISABLED
, devname
[index
],
1046 (void*) &dt3155_status
[index
]);
1049 printk("DT3155: minor %d request_irq failed for IRQ %d\n",
1050 index
, dt3155_status
[index
].irq
);
1051 unregister_chrdev(dt3155_major
, "dt3155");
1057 printk("DT3155: finished loading\n");
1062 /*****************************************************
1063 * cleanup_module(void)
1065 *****************************************************/
1066 void cleanup_module(void)
1070 printk("DT3155: cleanup_module called\n");
1072 /* removed DMA allocated with the allocator */
1073 #ifdef STANDALONE_ALLOCATOR
1074 if (allocatorAddr
!= 0)
1075 allocator_free_dma(allocatorAddr
);
1077 allocator_cleanup();
1080 unregister_chrdev(dt3155_major
, "dt3155");
1082 for(index
= 0; index
< ndevices
; index
++)
1084 if(dt3155_status
[index
].device_installed
== 1)
1086 printk("DT3155: Freeing irq %d for device %d\n",
1087 dt3155_status
[index
].irq
, index
);
1088 free_irq(dt3155_status
[index
].irq
, (void*)&dt3155_status
[index
]);