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 #define DT_3155_SUCCESS 0
101 #define DT_3155_FAILURE -EIO
103 /* set to dynamicaly allocate, but it is tunable: */
104 /* insmod DT_3155 dt3155 dt3155_major=XX */
105 int dt3155_major = 0;
107 /* The minor numbers are 0 and 1 ... they are not tunable.
108 * They are used as the indices for the structure vectors,
109 * and register address vectors
112 /* Global structures and variables */
114 /* Status of each device */
115 struct dt3155_status dt3155_status[MAXBOARDS];
117 /* kernel logical address of the board */
118 u8 *dt3155_lbase[MAXBOARDS] = { NULL
123 /* DT3155 registers */
124 u8 *dt3155_bbase = NULL; /* kernel logical address of the *
126 u32 dt3155_dev_open[MAXBOARDS] = {0
137 * Stops interrupt generation right away and resets the status
138 * to idle. I don't know why this works and the other way doesn't.
141 static void quick_stop (int minor)
143 // TODO: scott was here
145 ReadMReg((dt3155_lbase[minor] + INT_CSR), int_csr_r.reg);
146 /* disable interrupts */
147 int_csr_r.fld.FLD_END_EVE_EN = 0;
148 int_csr_r.fld.FLD_END_ODD_EN = 0;
149 WriteMReg((dt3155_lbase[minor] + INT_CSR), int_csr_r.reg);
151 dt3155_status[minor].state &= ~(DT3155_STATE_STOP|0xff);
152 /* mark the system stopped: */
153 dt3155_status[minor].state |= DT3155_STATE_IDLE;
154 dt3155_fbuffer[minor]->stop_acquire = 0;
155 dt3155_fbuffer[minor]->even_stopped = 0;
157 dt3155_status[minor].state |= DT3155_STATE_STOP;
158 dt3155_status[minor].fbuffer.stop_acquire = 1;
164 /*****************************************************
165 * dt3155_isr() Interrupt service routien
167 * - looks like this isr supports IRQ sharing (or could) JML
168 * - Assumes irq's are disabled, via SA_INTERRUPT flag
169 * being set in request_irq() call from init_module()
170 *****************************************************/
171 static void dt3155_isr(int irq, void *dev_id, struct pt_regs *regs)
178 /* find out who issued the interrupt */
179 for (index = 0; index < ndevices; index++) {
180 if(dev_id == (void*) &dt3155_status[index])
187 /* hopefully we should not get here */
188 if (minor < 0 || minor >= MAXBOARDS) {
189 printk(KERN_ERR "dt3155_isr called with invalid dev_id\n");
193 /* Check for corruption and set a flag if so */
194 ReadMReg((dt3155_lbase[minor] + CSR1), csr1_r.reg);
196 if ((csr1_r.fld.FLD_CRPT_EVE) || (csr1_r.fld.FLD_CRPT_ODD))
198 /* TODO: this should probably stop acquisition */
199 /* and set some flags so that dt3155_read */
200 /* returns an error next time it is called */
201 dt3155_errno = DT_ERR_CORRUPT;
202 printk("dt3155: corrupt field\n");
206 ReadMReg((dt3155_lbase[minor] + INT_CSR), int_csr_r.reg);
208 /* Handle the even field ... */
209 if (int_csr_r.fld.FLD_END_EVE)
211 if ((dt3155_status[minor].state & DT3155_STATE_MODE) ==
214 dt3155_fbuffer[minor]->frame_count++;
217 ReadI2C(dt3155_lbase[minor], EVEN_CSR, &i2c_even_csr.reg);
219 /* Clear the interrupt? */
220 int_csr_r.fld.FLD_END_EVE = 1;
222 /* disable the interrupt if last field */
223 if (dt3155_fbuffer[minor]->stop_acquire)
225 printk("dt3155: even stopped.\n");
226 dt3155_fbuffer[minor]->even_stopped = 1;
227 if (i2c_even_csr.fld.SNGL_EVE)
229 int_csr_r.fld.FLD_END_EVE_EN = 0;
233 i2c_even_csr.fld.SNGL_EVE = 1;
237 WriteMReg((dt3155_lbase[minor] + INT_CSR), int_csr_r.reg);
239 /* Set up next DMA if we are doing FIELDS */
240 if ((dt3155_status[minor].state & DT3155_STATE_MODE) ==
243 /* GCS (Aug 2, 2002) -- In field mode, dma the odd field
244 into the lower half of the buffer */
245 const u32 stride = dt3155_status[minor].config.cols;
246 buffer_addr = dt3155_fbuffer[minor]->
247 frame_info[dt3155_fbuffer[minor]->active_buf].addr
248 + (DT3155_MAX_ROWS / 2) * stride;
249 local_save_flags(flags);
251 wake_up_interruptible(&dt3155_read_wait_queue[minor]);
253 /* Set up the DMA address for the next field */
254 local_irq_restore(flags);
255 WriteMReg((dt3155_lbase[minor] + ODD_DMA_START), buffer_addr);
258 /* Check for errors. */
259 i2c_even_csr.fld.DONE_EVE = 1;
260 if (i2c_even_csr.fld.ERROR_EVE)
261 dt3155_errno = DT_ERR_OVERRUN;
263 WriteI2C(dt3155_lbase[minor], EVEN_CSR, i2c_even_csr.reg);
265 /* Note that we actually saw an even field meaning */
266 /* that subsequent odd field complete the frame */
267 dt3155_fbuffer[minor]->even_happened = 1;
269 /* recording the time that the even field finished, this should be */
270 /* about time in the middle of the frame */
271 do_gettimeofday(&(dt3155_fbuffer[minor]->
272 frame_info[dt3155_fbuffer[minor]->
277 /* ... now handle the odd field */
278 if (int_csr_r.fld.FLD_END_ODD)
280 ReadI2C(dt3155_lbase[minor], ODD_CSR, &i2c_odd_csr.reg);
282 /* Clear the interrupt? */
283 int_csr_r.fld.FLD_END_ODD = 1;
285 if (dt3155_fbuffer[minor]->even_happened ||
286 (dt3155_status[minor].state & DT3155_STATE_MODE) ==
289 dt3155_fbuffer[minor]->frame_count++;
292 if (dt3155_fbuffer[minor]->stop_acquire &&
293 dt3155_fbuffer[minor]->even_stopped)
295 printk(KERN_DEBUG "dt3155: stopping odd..\n");
296 if (i2c_odd_csr.fld.SNGL_ODD)
298 /* disable interrupts */
299 int_csr_r.fld.FLD_END_ODD_EN = 0;
300 dt3155_status[minor].state &= ~(DT3155_STATE_STOP|0xff);
302 /* mark the system stopped: */
303 dt3155_status[minor].state |= DT3155_STATE_IDLE;
304 dt3155_fbuffer[minor]->stop_acquire = 0;
305 dt3155_fbuffer[minor]->even_stopped = 0;
307 printk(KERN_DEBUG "dt3155: state is now %x\n",
308 dt3155_status[minor].state);
312 i2c_odd_csr.fld.SNGL_ODD = 1;
316 WriteMReg((dt3155_lbase[minor] + INT_CSR), int_csr_r.reg);
318 /* if the odd field has been acquired, then */
319 /* change the next dma location for both fields */
320 /* and wake up the process if sleeping */
321 if (dt3155_fbuffer[minor]->even_happened ||
322 (dt3155_status[minor].state & DT3155_STATE_MODE) ==
326 local_save_flags(flags);
332 if (dt3155_fbuffer[minor]->nbuffers > 2)
334 if (!are_empty_buffers(minor))
336 /* The number of active + locked buffers is
337 * at most 2, and since there are none empty, there
338 * must be at least nbuffers-2 ready buffers.
339 * This is where we 'drop frames', oldest first. */
340 push_empty(pop_ready(minor), minor);
343 /* The ready_que can't be full, since we know
344 * there is one active buffer right now, so it's safe
345 * to push the active buf on the ready_que. */
346 push_ready(minor, dt3155_fbuffer[minor]->active_buf);
347 /* There's at least 1 empty -- make it active */
348 dt3155_fbuffer[minor]->active_buf = pop_empty(minor);
349 dt3155_fbuffer[minor]->
350 frame_info[dt3155_fbuffer[minor]->
351 active_buf].tag = ++unique_tag;
353 else /* nbuffers == 2, special case */
354 { /* There is 1 active buffer.
355 * If there is a locked buffer, keep the active buffer
356 * the same -- that means we drop a frame.
358 if (dt3155_fbuffer[minor]->locked_buf < 0)
361 dt3155_fbuffer[minor]->active_buf);
362 if (are_empty_buffers(minor))
364 dt3155_fbuffer[minor]->active_buf =
368 { /* no empty or locked buffers, so use a readybuf */
369 dt3155_fbuffer[minor]->active_buf =
379 dt3155_fbuffer[minor]->even_happened = 0;
381 wake_up_interruptible(&dt3155_read_wait_queue[minor]);
383 local_irq_restore(flags);
387 /* Set up the DMA address for the next frame/field */
388 buffer_addr = dt3155_fbuffer[minor]->
389 frame_info[dt3155_fbuffer[minor]->active_buf].addr;
390 if ((dt3155_status[minor].state & DT3155_STATE_MODE) ==
393 WriteMReg((dt3155_lbase[minor] + EVEN_DMA_START), buffer_addr);
397 WriteMReg((dt3155_lbase[minor] + EVEN_DMA_START), buffer_addr);
399 WriteMReg((dt3155_lbase[minor] + ODD_DMA_START), buffer_addr
400 + dt3155_status[minor].config.cols);
403 /* Do error checking */
404 i2c_odd_csr.fld.DONE_ODD = 1;
405 if (i2c_odd_csr.fld.ERROR_ODD)
406 dt3155_errno = DT_ERR_OVERRUN;
408 WriteI2C(dt3155_lbase[minor], ODD_CSR, i2c_odd_csr.reg);
412 /* If we get here, the Odd Field wasn't it either... */
413 printk("neither even nor odd. shared perhaps?\n");
416 /*****************************************************
417 * init_isr(int minor)
418 * turns on interupt generation for the card
419 * designated by "minor".
420 * It is called *only* from inside ioctl().
421 *****************************************************/
422 static void dt3155_init_isr(int minor)
424 const u32 stride = dt3155_status[minor].config.cols;
426 switch (dt3155_status[minor].state & DT3155_STATE_MODE)
428 case DT3155_STATE_FLD:
430 even_dma_start_r = dt3155_status[minor].
431 fbuffer.frame_info[dt3155_status[minor].fbuffer.active_buf].addr;
432 even_dma_stride_r = 0;
433 odd_dma_stride_r = 0;
435 WriteMReg((dt3155_lbase[minor] + EVEN_DMA_START),
437 WriteMReg((dt3155_lbase[minor] + EVEN_DMA_STRIDE),
439 WriteMReg((dt3155_lbase[minor] + ODD_DMA_STRIDE),
444 case DT3155_STATE_FRAME:
447 even_dma_start_r = dt3155_status[minor].
448 fbuffer.frame_info[dt3155_status[minor].fbuffer.active_buf].addr;
449 odd_dma_start_r = even_dma_start_r + stride;
450 even_dma_stride_r = stride;
451 odd_dma_stride_r = stride;
453 WriteMReg((dt3155_lbase[minor] + EVEN_DMA_START),
455 WriteMReg((dt3155_lbase[minor] + ODD_DMA_START),
457 WriteMReg((dt3155_lbase[minor] + EVEN_DMA_STRIDE),
459 WriteMReg((dt3155_lbase[minor] + ODD_DMA_STRIDE),
465 /* 50/60 Hz should be set before this point but let's make sure it is */
468 ReadI2C(dt3155_lbase[minor], CSR2, &i2c_csr2.reg);
469 i2c_csr2.fld.HZ50 = FORMAT50HZ;
470 WriteI2C(dt3155_lbase[minor], CSR2, i2c_csr2.reg);
472 /* enable busmaster chip, clear flags */
476 * shouldn't we be concered with continuous values of
477 * DT3155_SNAP & DT3155_ACQ here? (SS)
481 csr1_r.fld.CAP_CONT_EVE = 1; /* use continuous capture bits to */
482 csr1_r.fld.CAP_CONT_ODD = 1; /* enable */
483 csr1_r.fld.FLD_DN_EVE = 1; /* writing a 1 clears flags */
484 csr1_r.fld.FLD_DN_ODD = 1;
485 csr1_r.fld.SRST = 1; /* reset - must be 1 */
486 csr1_r.fld.FIFO_EN = 1; /* fifo control - must be 1 */
487 csr1_r.fld.FLD_CRPT_EVE = 1; /* writing a 1 clears flags */
488 csr1_r.fld.FLD_CRPT_ODD = 1;
490 WriteMReg((dt3155_lbase[minor] + CSR1),csr1_r.reg);
492 /* Enable interrupts at the end of each field */
495 int_csr_r.fld.FLD_END_EVE_EN = 1;
496 int_csr_r.fld.FLD_END_ODD_EN = 1;
497 int_csr_r.fld.FLD_START_EN = 0;
499 WriteMReg((dt3155_lbase[minor] + INT_CSR), int_csr_r.reg);
501 /* start internal BUSY bits */
503 ReadI2C(dt3155_lbase[minor], CSR2, &i2c_csr2.reg);
504 i2c_csr2.fld.BUSY_ODD = 1;
505 i2c_csr2.fld.BUSY_EVE = 1;
506 WriteI2C(dt3155_lbase[minor], CSR2, i2c_csr2.reg);
508 /* Now its up to the interrupt routine!! */
514 /*****************************************************
517 *****************************************************/
518 static int dt3155_ioctl(struct inode *inode,
523 int minor = MINOR(inode->i_rdev); /* What device are we ioctl()'ing? */
524 void __user *up = (void __user *)arg;
526 if (minor >= MAXBOARDS || minor < 0)
529 /* make sure it is valid command */
530 if (_IOC_NR(cmd) > DT3155_IOC_MAXNR)
532 printk("DT3155: invalid IOCTL(0x%x)\n",cmd);
533 printk("DT3155: Valid commands (0x%x), (0x%x), (0x%x), (0x%x), (0x%x)\n",
534 (unsigned int)DT3155_GET_CONFIG,
535 (unsigned int)DT3155_SET_CONFIG,
536 (unsigned int)DT3155_START,
537 (unsigned int)DT3155_STOP,
538 (unsigned int)DT3155_FLUSH);
544 case DT3155_SET_CONFIG:
546 if (dt3155_status[minor].state != DT3155_STATE_IDLE)
550 struct dt3155_config tmp;
551 if (copy_from_user(&tmp, up, sizeof(tmp)))
553 /* check for valid settings */
554 if (tmp.rows > DT3155_MAX_ROWS ||
555 tmp.cols > DT3155_MAX_COLS ||
556 (tmp.acq_mode != DT3155_MODE_FRAME &&
557 tmp.acq_mode != DT3155_MODE_FIELD) ||
558 (tmp.continuous != DT3155_SNAP &&
559 tmp.continuous != DT3155_ACQ))
563 dt3155_status[minor].config = tmp;
567 case DT3155_GET_CONFIG:
569 if (copy_to_user(up, &dt3155_status[minor],
570 sizeof(struct dt3155_status)))
574 case DT3155_FLUSH: /* Flushes the buffers -- ensures fresh data */
576 if (dt3155_status[minor].state != DT3155_STATE_IDLE)
578 return dt3155_flush(minor);
582 if (dt3155_status[minor].state & DT3155_STATE_STOP ||
583 dt3155_status[minor].fbuffer.stop_acquire)
586 if (dt3155_status[minor].state == DT3155_STATE_IDLE)
590 if (copy_to_user(up, &dt3155_status[minor],
591 sizeof(struct dt3155_status)))
597 if (dt3155_status[minor].state != DT3155_STATE_IDLE)
600 dt3155_status[minor].fbuffer.stop_acquire = 0;
601 dt3155_status[minor].fbuffer.frame_count = 0;
603 /* Set the MODE in the status -- we default to FRAME */
604 if (dt3155_status[minor].config.acq_mode == DT3155_MODE_FIELD)
606 dt3155_status[minor].state = DT3155_STATE_FLD;
610 dt3155_status[minor].state = DT3155_STATE_FRAME;
613 dt3155_init_isr(minor);
614 if (copy_to_user(up, &dt3155_status[minor],
615 sizeof(struct dt3155_status)))
621 printk("DT3155: invalid IOCTL(0x%x)\n",cmd);
622 printk("DT3155: Valid commands (0x%x), (0x%x), (0x%x), (0x%x), (0x%x)\n",
623 (unsigned int)DT3155_GET_CONFIG,
624 (unsigned int)DT3155_SET_CONFIG,
625 DT3155_START, DT3155_STOP, DT3155_FLUSH);
632 /*****************************************************
635 * only allow the user to mmap the registers and buffer
636 * It is quite possible that this is broken, since the
637 * addition of of the capacity for two cards!!!!!!!!
638 * It *looks* like it should work but since I'm not
639 * sure how to use it, I'm not actually sure. (NJC? ditto by SS)
640 *****************************************************/
641 static int dt3155_mmap (struct file * file, struct vm_area_struct * vma)
643 /* which device are we mmapping? */
644 int minor = MINOR(file->f_dentry->d_inode->i_rdev);
645 unsigned long offset;
646 offset = vma->vm_pgoff << PAGE_SHIFT;
648 if (offset >= __pa(high_memory) || (file->f_flags & O_SYNC))
649 vma->vm_flags |= VM_IO;
651 /* Don't try to swap out physical pages.. */
652 vma->vm_flags |= VM_RESERVED;
654 /* they are mapping the registers or the buffer */
655 if ((offset == dt3155_status[minor].reg_addr &&
656 vma->vm_end - vma->vm_start == PCI_PAGE_SIZE) ||
657 (offset == dt3155_status[minor].mem_addr &&
658 vma->vm_end - vma->vm_start == dt3155_status[minor].mem_size))
660 if (remap_pfn_range(vma,
662 offset >> PAGE_SHIFT,
663 vma->vm_end - vma->vm_start,
664 vma->vm_page_prot)) {
665 printk("DT3155: remap_page_range() failed.\n");
671 printk("DT3155: dt3155_mmap() bad call.\n");
679 /*****************************************************
682 * Our special open code.
683 * MOD_INC_USE_COUNT make sure that the driver memory is not freed
684 * while the device is in use.
685 *****************************************************/
686 static int dt3155_open(struct inode* inode, struct file* filep)
688 int minor = MINOR(inode->i_rdev); /* what device are we opening? */
689 if (dt3155_dev_open[minor]) {
690 printk ("DT3155: Already opened by another process.\n");
694 if (dt3155_status[minor].device_installed==0)
696 printk("DT3155 Open Error: No such device dt3155 minor number %d\n",
701 if (dt3155_status[minor].state != DT3155_STATE_IDLE) {
702 printk ("DT3155: Not in idle state (state = %x)\n",
703 dt3155_status[minor].state);
707 printk("DT3155: Device opened.\n");
709 dt3155_dev_open[minor] = 1 ;
713 /* Disable ALL interrupts */
715 WriteMReg((dt3155_lbase[minor] + INT_CSR), int_csr_r.reg);
717 init_waitqueue_head(&(dt3155_read_wait_queue[minor]));
723 /*****************************************************
726 * Now decrement the use count.
728 *****************************************************/
729 static int dt3155_close(struct inode *inode, struct file *filep)
733 minor = MINOR(inode->i_rdev); /* which device are we closing */
734 if (!dt3155_dev_open[minor])
736 printk("DT3155: attempt to CLOSE a not OPEN device\n");
740 dt3155_dev_open[minor] = 0;
742 if (dt3155_status[minor].state != DT3155_STATE_IDLE)
750 /*****************************************************
753 *****************************************************/
754 static ssize_t dt3155_read(struct file *filep, char __user *buf,
755 size_t count, loff_t *ppos)
757 /* which device are we reading from? */
758 int minor = MINOR(filep->f_dentry->d_inode->i_rdev);
761 struct frame_info *frame_info;
763 /* TODO: this should check the error flag and */
764 /* return an error on hardware failures */
765 if (count != sizeof(struct dt3155_read))
767 printk("DT3155 ERROR (NJC): count is not right\n");
772 /* Hack here -- I'm going to allow reading even when idle.
773 * this is so that the frames can be read after STOP has
774 * been called. Leaving it here, commented out, as a reminder
775 * for a short while to make sure there are no problems.
776 * Note that if the driver is not opened in non_blocking mode,
777 * and the device is idle, then it could sit here forever! */
779 /* if (dt3155_status[minor].state == DT3155_STATE_IDLE)*/
782 /* non-blocking reads should return if no data */
783 if (filep->f_flags & O_NDELAY)
785 if ((frame_index = dt3155_get_ready_buffer(minor)) < 0) {
786 /*printk("dt3155: no buffers available (?)\n");*/
787 /* printques(minor); */
794 * sleep till data arrives , or we get interrupted.
795 * Note that wait_event_interruptible() does not actually
796 * sleep/wait if it's condition evaluates to true upon entry.
798 wait_event_interruptible(dt3155_read_wait_queue[minor],
799 (frame_index = dt3155_get_ready_buffer(minor))
804 printk ("DT3155: read: interrupted\n");
811 frame_info = &dt3155_status[minor].fbuffer.frame_info[frame_index];
813 /* make this an offset */
814 offset = frame_info->addr - dt3155_status[minor].mem_addr;
816 put_user(offset, (unsigned int __user *)buf);
818 put_user(dt3155_status[minor].fbuffer.frame_count, (unsigned int __user *)buf);
820 put_user(dt3155_status[minor].state, (unsigned int __user *)buf);
822 if (copy_to_user(buf, frame_info, sizeof(*frame_info)))
825 return sizeof(struct dt3155_read);
828 static unsigned int dt3155_poll (struct file * filp, poll_table *wait)
830 int minor = MINOR(filp->f_dentry->d_inode->i_rdev);
832 if (!is_ready_buf_empty(minor))
833 return POLLIN | POLLRDNORM;
835 poll_wait (filp, &dt3155_read_wait_queue[minor], wait);
841 dt3155_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
846 ret = dt3155_ioctl(file->f_path.dentry->d_inode, file, cmd, arg);
852 /*****************************************************
853 * file operations supported by DT3155 driver
854 * needed by init_module
856 *****************************************************/
857 static struct file_operations dt3155_fops = {
859 .unlocked_ioctl = dt3155_unlocked_ioctl,
863 .release = dt3155_close
867 /*****************************************************
870 * PCI has been totally reworked in 2.1..
871 *****************************************************/
872 static int find_PCI (void)
874 struct pci_dev *pci_dev = NULL;
875 int error, pci_index = 0;
876 unsigned short rev_device;
880 while ((pci_dev = pci_get_device
881 (DT3155_VENDORID, DT3155_DEVICEID, pci_dev)) != NULL)
885 /* Is it really there? */
887 pci_read_config_word(pci_dev, PCI_CLASS_DEVICE, &rev_device)))
891 DT_3155_DEBUG_MSG("DT3155: Device number %d \n", pci_index);
893 /* Make sure the driver was compiled with enough buffers to handle
895 if (pci_index > MAXBOARDS) {
896 printk("DT3155: ERROR - found %d devices, but driver only configured "
898 "DT3155: Please change MAXBOARDS in dt3155.h\n",
899 pci_index, MAXBOARDS);
903 /* Now, just go out and make sure that this/these device(s) is/are
904 actually mapped into the kernel address space */
905 if ((error = pci_read_config_dword(pci_dev, PCI_BASE_ADDRESS_0,
908 printk("DT3155: Was not able to find device \n");
912 DT_3155_DEBUG_MSG("DT3155: Base address 0 for device is %lx \n", base);
913 dt3155_status[pci_index-1].reg_addr = base;
915 /* Remap the base address to a logical address through which we
917 dt3155_lbase[pci_index - 1] = ioremap(base,PCI_PAGE_SIZE);
918 dt3155_status[pci_index - 1].reg_addr = base;
919 DT_3155_DEBUG_MSG("DT3155: New logical address is %p \n",
920 dt3155_lbase[pci_index-1]);
921 if (!dt3155_lbase[pci_index-1])
923 printk("DT3155: Unable to remap control registers\n");
927 if ((error = pci_read_config_byte(pci_dev, PCI_INTERRUPT_LINE, &irq)))
929 printk("DT3155: Was not able to find device \n");
933 DT_3155_DEBUG_MSG("DT3155: IRQ is %d \n",irq);
934 dt3155_status[pci_index-1].irq = irq;
935 /* Set flag: kth device found! */
936 dt3155_status[pci_index-1].device_installed = 1;
937 printk("DT3155: Installing device %d w/irq %d and address %p\n",
939 dt3155_status[pci_index-1].irq,
940 dt3155_lbase[pci_index-1]);
943 ndevices = pci_index;
945 return DT_3155_SUCCESS;
948 pci_dev_put(pci_dev);
949 return DT_3155_FAILURE;
952 u32 allocatorAddr = 0;
954 /*****************************************************
956 *****************************************************/
957 int init_module(void)
961 char *devname[MAXBOARDS];
963 devname[0] = "dt3155a";
965 devname[1] = "dt3155b";
968 printk("DT3155: Loading module...\n");
970 /* Register the device driver */
971 rcode = register_chrdev(dt3155_major, "dt3155", &dt3155_fops);
974 printk(KERN_INFO "DT3155: register_chrdev failed \n");
978 if(dt3155_major == 0)
979 dt3155_major = rcode; /* dynamic */
982 /* init the status variables. */
983 /* DMA memory is taken care of in setup_buffers() */
984 for (index = 0; index < MAXBOARDS; index++)
986 dt3155_status[index].config.acq_mode = DT3155_MODE_FRAME;
987 dt3155_status[index].config.continuous = DT3155_ACQ;
988 dt3155_status[index].config.cols = DT3155_MAX_COLS;
989 dt3155_status[index].config.rows = DT3155_MAX_ROWS;
990 dt3155_status[index].state = DT3155_STATE_IDLE;
992 /* find_PCI() will check if devices are installed; */
993 /* first assume they're not: */
994 dt3155_status[index].mem_addr = 0;
995 dt3155_status[index].mem_size = 0;
996 dt3155_status[index].state = DT3155_STATE_IDLE;
997 dt3155_status[index].device_installed = 0;
1000 /* Now let's find the hardware. find_PCI() will set ndevices to the
1001 * number of cards found in this machine. */
1003 if ((rcode = find_PCI()) != DT_3155_SUCCESS)
1005 printk("DT3155 error: find_PCI() failed to find dt3155 board(s)\n");
1006 unregister_chrdev(dt3155_major, "dt3155");
1011 /* Ok, time to setup the frame buffers */
1012 if((rcode = dt3155_setup_buffers(&allocatorAddr)) < 0)
1014 printk("DT3155: Error: setting up buffer not large enough.");
1015 unregister_chrdev(dt3155_major, "dt3155");
1019 /* If we are this far, then there is enough RAM */
1020 /* for the buffers: Print the configuration. */
1021 for( index = 0; index < ndevices; index++)
1023 printk("DT3155: Device = %d; acq_mode = %d; "
1024 "continuous = %d; cols = %d; rows = %d;\n",
1026 dt3155_status[index].config.acq_mode,
1027 dt3155_status[index].config.continuous,
1028 dt3155_status[index].config.cols,
1029 dt3155_status[index].config.rows);
1030 printk("DT3155: m_addr = 0x%x; m_size = %ld; "
1031 "state = %d; device_installed = %d\n",
1032 dt3155_status[index].mem_addr,
1033 (long int)dt3155_status[index].mem_size,
1034 dt3155_status[index].state,
1035 dt3155_status[index].device_installed);
1038 /* Disable ALL interrupts */
1040 for( index = 0; index < ndevices; index++)
1042 WriteMReg((dt3155_lbase[index] + INT_CSR), int_csr_r.reg);
1043 if(dt3155_status[index].device_installed)
1046 * This driver *looks* like it can handle sharing interrupts,
1047 * but I can't actually test myself. I've had reports that it
1048 * DOES work so I'll enable it for now. This comment will remain
1049 * as a reminder in case any problems arise. (SS)
1051 /* in older kernels flags are: SA_SHIRQ | SA_INTERRUPT */
1052 rcode = request_irq(dt3155_status[index].irq, (void *)dt3155_isr,
1053 IRQF_SHARED | IRQF_DISABLED, devname[index],
1054 (void*) &dt3155_status[index]);
1057 printk("DT3155: minor %d request_irq failed for IRQ %d\n",
1058 index, dt3155_status[index].irq);
1059 unregister_chrdev(dt3155_major, "dt3155");
1065 printk("DT3155: finished loading\n");
1070 /*****************************************************
1071 * cleanup_module(void)
1073 *****************************************************/
1074 void cleanup_module(void)
1078 printk("DT3155: cleanup_module called\n");
1080 /* removed DMA allocated with the allocator */
1081 #ifdef STANDALONE_ALLOCATOR
1082 if (allocatorAddr != 0)
1083 allocator_free_dma(allocatorAddr);
1085 allocator_cleanup();
1088 unregister_chrdev(dt3155_major, "dt3155");
1090 for(index = 0; index < ndevices; index++)
1092 if(dt3155_status[index].device_installed == 1)
1094 printk("DT3155: Freeing irq %d for device %d\n",
1095 dt3155_status[index].irq, index);
1096 free_irq(dt3155_status[index].irq, (void*)&dt3155_status[index]);