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>
68 #include <asm/uaccess.h>
71 #include "dt3155_drv.h"
72 #include "dt3155_isr.h"
73 #include "dt3155_io.h"
74 #include "allocator.h"
77 MODULE_LICENSE("GPL");
79 /* Error variable. Zero means no error. */
82 #ifndef PCI_DEVICE_ID_INTEL_7116
83 #define PCI_DEVICE_ID_INTEL_7116 0x1223
86 #define DT3155_VENDORID PCI_VENDOR_ID_INTEL
87 #define DT3155_DEVICEID PCI_DEVICE_ID_INTEL_7116
91 #define DT_3155_DEBUG_MSG(x,y) printk(x,y)
93 #define DT_3155_DEBUG_MSG(x,y)
96 /* wait queue for interrupts */
97 wait_queue_head_t dt3155_read_wait_queue
[ MAXBOARDS
];
99 #define DT_3155_SUCCESS 0
100 #define DT_3155_FAILURE -EIO
102 /* set to dynamicaly allocate, but it is tunable: */
103 /* insmod DT_3155 dt3155 dt3155_major=XX */
104 int dt3155_major
= 0;
106 /* The minor numbers are 0 and 1 ... they are not tunable.
107 * They are used as the indices for the structure vectors,
108 * and register address vectors
111 /* Global structures and variables */
113 /* Status of each device */
114 struct dt3155_status_s dt3155_status
[ MAXBOARDS
];
116 /* kernel logical address of the board */
117 u8
*dt3155_lbase
[ MAXBOARDS
] = { NULL
122 /* DT3155 registers */
123 u8
*dt3155_bbase
= NULL
; /* kernel logical address of the *
125 u32 dt3155_dev_open
[ MAXBOARDS
] = {0
136 * Stops interrupt generation right away and resets the status
137 * to idle. I don't know why this works and the other way doesn't.
140 static void quick_stop (int minor
)
142 // TODO: scott was here
144 ReadMReg((dt3155_lbase
[ minor
] + INT_CSR
), int_csr_r
.reg
);
145 /* disable interrupts */
146 int_csr_r
.fld
.FLD_END_EVE_EN
= 0;
147 int_csr_r
.fld
.FLD_END_ODD_EN
= 0;
148 WriteMReg((dt3155_lbase
[ minor
] + INT_CSR
), int_csr_r
.reg
);
150 dt3155_status
[ minor
].state
&= ~(DT3155_STATE_STOP
|0xff);
151 /* mark the system stopped: */
152 dt3155_status
[ minor
].state
|= DT3155_STATE_IDLE
;
153 dt3155_fbuffer
[ minor
]->stop_acquire
= 0;
154 dt3155_fbuffer
[ minor
]->even_stopped
= 0;
156 dt3155_status
[minor
].state
|= DT3155_STATE_STOP
;
157 dt3155_status
[minor
].fbuffer
.stop_acquire
= 1;
163 /*****************************************************
164 * dt3155_isr() Interrupt service routien
166 * - looks like this isr supports IRQ sharing (or could) JML
167 * - Assumes irq's are disabled, via SA_INTERRUPT flag
168 * being set in request_irq() call from init_module()
169 *****************************************************/
170 static inline void dt3155_isr( int irq
, void *dev_id
, struct pt_regs
*regs
)
177 /* find out who issued the interrupt */
178 for ( index
= 0; index
< ndevices
; index
++ ) {
179 if( dev_id
== (void*) &dt3155_status
[ index
])
186 /* hopefully we should not get here */
187 if ( minor
< 0 || minor
>= MAXBOARDS
) {
188 printk(KERN_ERR
"dt3155_isr called with invalid dev_id\n");
192 /* Check for corruption and set a flag if so */
193 ReadMReg( (dt3155_lbase
[ minor
] + CSR1
), csr1_r
.reg
);
195 if ( (csr1_r
.fld
.FLD_CRPT_EVE
) || (csr1_r
.fld
.FLD_CRPT_ODD
) )
197 /* TODO: this should probably stop acquisition */
198 /* and set some flags so that dt3155_read */
199 /* returns an error next time it is called */
200 dt3155_errno
= DT_ERR_CORRUPT
;
201 printk("dt3155: corrupt field\n");
205 ReadMReg((dt3155_lbase
[ minor
] + INT_CSR
), int_csr_r
.reg
);
207 /* Handle the even field ... */
208 if (int_csr_r
.fld
.FLD_END_EVE
)
210 if ( (dt3155_status
[ minor
].state
& DT3155_STATE_MODE
) ==
213 dt3155_fbuffer
[ minor
]->frame_count
++;
216 ReadI2C(dt3155_lbase
[ minor
], EVEN_CSR
, &i2c_even_csr
.reg
);
218 /* Clear the interrupt? */
219 int_csr_r
.fld
.FLD_END_EVE
= 1;
221 /* disable the interrupt if last field */
222 if (dt3155_fbuffer
[ minor
]->stop_acquire
)
224 printk("dt3155: even stopped.\n");
225 dt3155_fbuffer
[ minor
]->even_stopped
= 1;
226 if (i2c_even_csr
.fld
.SNGL_EVE
)
228 int_csr_r
.fld
.FLD_END_EVE_EN
= 0;
232 i2c_even_csr
.fld
.SNGL_EVE
= 1;
236 WriteMReg( (dt3155_lbase
[ minor
] + INT_CSR
), int_csr_r
.reg
);
238 /* Set up next DMA if we are doing FIELDS */
239 if ( (dt3155_status
[ minor
].state
& DT3155_STATE_MODE
) ==
242 /* GCS (Aug 2, 2002) -- In field mode, dma the odd field
243 into the lower half of the buffer */
244 const u32 stride
= dt3155_status
[ minor
].config
.cols
;
245 buffer_addr
= dt3155_fbuffer
[ minor
]->
246 frame_info
[ dt3155_fbuffer
[ minor
]->active_buf
].addr
247 + (DT3155_MAX_ROWS
/ 2) * stride
;
248 local_save_flags(flags
);
250 wake_up_interruptible( &dt3155_read_wait_queue
[ minor
] );
252 /* Set up the DMA address for the next field */
253 local_irq_restore(flags
);
254 WriteMReg((dt3155_lbase
[ minor
] + ODD_DMA_START
), buffer_addr
);
257 /* Check for errors. */
258 i2c_even_csr
.fld
.DONE_EVE
= 1;
259 if ( i2c_even_csr
.fld
.ERROR_EVE
)
260 dt3155_errno
= DT_ERR_OVERRUN
;
262 WriteI2C( dt3155_lbase
[ minor
], EVEN_CSR
, i2c_even_csr
.reg
);
264 /* Note that we actually saw an even field meaning */
265 /* that subsequent odd field complete the frame */
266 dt3155_fbuffer
[ minor
]->even_happened
= 1;
268 /* recording the time that the even field finished, this should be */
269 /* about time in the middle of the frame */
270 do_gettimeofday( &(dt3155_fbuffer
[ minor
]->
271 frame_info
[ dt3155_fbuffer
[ minor
]->
272 active_buf
].time
) );
276 /* ... now handle the odd field */
277 if ( int_csr_r
.fld
.FLD_END_ODD
)
279 ReadI2C( dt3155_lbase
[ minor
], ODD_CSR
, &i2c_odd_csr
.reg
);
281 /* Clear the interrupt? */
282 int_csr_r
.fld
.FLD_END_ODD
= 1;
284 if (dt3155_fbuffer
[ minor
]->even_happened
||
285 (dt3155_status
[ minor
].state
& DT3155_STATE_MODE
) ==
288 dt3155_fbuffer
[ minor
]->frame_count
++;
291 if ( dt3155_fbuffer
[ minor
]->stop_acquire
&&
292 dt3155_fbuffer
[ minor
]->even_stopped
)
294 printk(KERN_DEBUG
"dt3155: stopping odd..\n");
295 if ( i2c_odd_csr
.fld
.SNGL_ODD
)
297 /* disable interrupts */
298 int_csr_r
.fld
.FLD_END_ODD_EN
= 0;
299 dt3155_status
[ minor
].state
&= ~(DT3155_STATE_STOP
|0xff);
301 /* mark the system stopped: */
302 dt3155_status
[ minor
].state
|= DT3155_STATE_IDLE
;
303 dt3155_fbuffer
[ minor
]->stop_acquire
= 0;
304 dt3155_fbuffer
[ minor
]->even_stopped
= 0;
306 printk(KERN_DEBUG
"dt3155: state is now %x\n",
307 dt3155_status
[minor
].state
);
311 i2c_odd_csr
.fld
.SNGL_ODD
= 1;
315 WriteMReg( (dt3155_lbase
[ minor
] + INT_CSR
), int_csr_r
.reg
);
317 /* if the odd field has been acquired, then */
318 /* change the next dma location for both fields */
319 /* and wake up the process if sleeping */
320 if ( dt3155_fbuffer
[ minor
]->even_happened
||
321 (dt3155_status
[ minor
].state
& DT3155_STATE_MODE
) ==
325 local_save_flags(flags
);
331 if ( dt3155_fbuffer
[ minor
]->nbuffers
> 2 )
333 if ( !are_empty_buffers( minor
) )
335 /* The number of active + locked buffers is
336 * at most 2, and since there are none empty, there
337 * must be at least nbuffers-2 ready buffers.
338 * This is where we 'drop frames', oldest first. */
339 push_empty( pop_ready( minor
), minor
);
342 /* The ready_que can't be full, since we know
343 * there is one active buffer right now, so it's safe
344 * to push the active buf on the ready_que. */
345 push_ready( minor
, dt3155_fbuffer
[ minor
]->active_buf
);
346 /* There's at least 1 empty -- make it active */
347 dt3155_fbuffer
[ minor
]->active_buf
= pop_empty( minor
);
348 dt3155_fbuffer
[ minor
]->
349 frame_info
[ dt3155_fbuffer
[ minor
]->
350 active_buf
].tag
= ++unique_tag
;
352 else /* nbuffers == 2, special case */
353 { /* There is 1 active buffer.
354 * If there is a locked buffer, keep the active buffer
355 * the same -- that means we drop a frame.
357 if ( dt3155_fbuffer
[ minor
]->locked_buf
< 0 )
360 dt3155_fbuffer
[ minor
]->active_buf
);
361 if (are_empty_buffers( minor
) )
363 dt3155_fbuffer
[ minor
]->active_buf
=
367 { /* no empty or locked buffers, so use a readybuf */
368 dt3155_fbuffer
[ minor
]->active_buf
=
378 dt3155_fbuffer
[ minor
]->even_happened
= 0;
380 wake_up_interruptible( &dt3155_read_wait_queue
[ minor
] );
382 local_irq_restore(flags
);
386 /* Set up the DMA address for the next frame/field */
387 buffer_addr
= dt3155_fbuffer
[ minor
]->
388 frame_info
[ dt3155_fbuffer
[ minor
]->active_buf
].addr
;
389 if ( (dt3155_status
[ minor
].state
& DT3155_STATE_MODE
) ==
392 WriteMReg((dt3155_lbase
[ minor
] + EVEN_DMA_START
), buffer_addr
);
396 WriteMReg((dt3155_lbase
[ minor
] + EVEN_DMA_START
), buffer_addr
);
398 WriteMReg((dt3155_lbase
[ minor
] + ODD_DMA_START
), buffer_addr
399 + dt3155_status
[ minor
].config
.cols
);
402 /* Do error checking */
403 i2c_odd_csr
.fld
.DONE_ODD
= 1;
404 if ( i2c_odd_csr
.fld
.ERROR_ODD
)
405 dt3155_errno
= DT_ERR_OVERRUN
;
407 WriteI2C(dt3155_lbase
[ minor
], ODD_CSR
, i2c_odd_csr
.reg
);
411 /* If we get here, the Odd Field wasn't it either... */
412 printk( "neither even nor odd. shared perhaps?\n");
415 /*****************************************************
416 * init_isr(int minor)
417 * turns on interupt generation for the card
418 * designated by "minor".
419 * It is called *only* from inside ioctl().
420 *****************************************************/
421 static void dt3155_init_isr(int minor
)
423 const u32 stride
= dt3155_status
[ minor
].config
.cols
;
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 WriteMReg((dt3155_lbase
[ minor
] + EVEN_DMA_START
),
436 WriteMReg((dt3155_lbase
[ minor
] + EVEN_DMA_STRIDE
),
438 WriteMReg((dt3155_lbase
[ minor
] + ODD_DMA_STRIDE
),
443 case DT3155_STATE_FRAME
:
446 even_dma_start_r
= dt3155_status
[ minor
].
447 fbuffer
.frame_info
[ dt3155_status
[ minor
].fbuffer
.active_buf
].addr
;
448 odd_dma_start_r
= even_dma_start_r
+ stride
;
449 even_dma_stride_r
= stride
;
450 odd_dma_stride_r
= stride
;
452 WriteMReg((dt3155_lbase
[ minor
] + EVEN_DMA_START
),
454 WriteMReg((dt3155_lbase
[ minor
] + ODD_DMA_START
),
456 WriteMReg((dt3155_lbase
[ minor
] + EVEN_DMA_STRIDE
),
458 WriteMReg((dt3155_lbase
[ minor
] + ODD_DMA_STRIDE
),
464 /* 50/60 Hz should be set before this point but let's make sure it is */
467 ReadI2C(dt3155_lbase
[ minor
], CONFIG
, &i2c_csr2
.reg
);
468 i2c_csr2
.fld
.HZ50
= FORMAT50HZ
;
469 WriteI2C(dt3155_lbase
[ minor
], CONFIG
, i2c_config
.reg
);
471 /* enable busmaster chip, clear flags */
475 * shouldn't we be concered with continuous values of
476 * DT3155_SNAP & DT3155_ACQ here? (SS)
480 csr1_r
.fld
.CAP_CONT_EVE
= 1; /* use continuous capture bits to */
481 csr1_r
.fld
.CAP_CONT_ODD
= 1; /* enable */
482 csr1_r
.fld
.FLD_DN_EVE
= 1; /* writing a 1 clears flags */
483 csr1_r
.fld
.FLD_DN_ODD
= 1;
484 csr1_r
.fld
.SRST
= 1; /* reset - must be 1 */
485 csr1_r
.fld
.FIFO_EN
= 1; /* fifo control - must be 1 */
486 csr1_r
.fld
.FLD_CRPT_EVE
= 1; /* writing a 1 clears flags */
487 csr1_r
.fld
.FLD_CRPT_ODD
= 1;
489 WriteMReg((dt3155_lbase
[ minor
] + CSR1
),csr1_r
.reg
);
491 /* Enable interrupts at the end of each field */
494 int_csr_r
.fld
.FLD_END_EVE_EN
= 1;
495 int_csr_r
.fld
.FLD_END_ODD_EN
= 1;
496 int_csr_r
.fld
.FLD_START_EN
= 0;
498 WriteMReg((dt3155_lbase
[ minor
] + INT_CSR
), int_csr_r
.reg
);
500 /* start internal BUSY bits */
502 ReadI2C(dt3155_lbase
[ minor
], CSR2
, &i2c_csr2
.reg
);
503 i2c_csr2
.fld
.BUSY_ODD
= 1;
504 i2c_csr2
.fld
.BUSY_EVE
= 1;
505 WriteI2C(dt3155_lbase
[ minor
], CSR2
, i2c_csr2
.reg
);
507 /* Now its up to the interrupt routine!! */
513 /*****************************************************
516 *****************************************************/
517 static int dt3155_ioctl(struct inode
*inode
,
522 int minor
= MINOR(inode
->i_rdev
); /* What device are we ioctl()'ing? */
524 if ( minor
>= MAXBOARDS
|| minor
< 0 )
527 /* make sure it is valid command */
528 if (_IOC_NR(cmd
) > DT3155_IOC_MAXNR
)
530 printk("DT3155: invalid IOCTL(0x%x)\n",cmd
);
531 printk("DT3155: Valid commands (0x%x), (0x%x), (0x%x), (0x%x), (0x%x)\n",
532 (unsigned int)DT3155_GET_CONFIG
,
533 (unsigned int)DT3155_SET_CONFIG
,
534 (unsigned int)DT3155_START
,
535 (unsigned int)DT3155_STOP
,
536 (unsigned int)DT3155_FLUSH
);
542 case DT3155_SET_CONFIG
:
544 if (dt3155_status
[minor
].state
!= DT3155_STATE_IDLE
)
548 struct dt3155_config_s tmp
;
549 if (copy_from_user((void *)&tmp
, (void *) arg
, sizeof(tmp
)))
551 /* check for valid settings */
552 if (tmp
.rows
> DT3155_MAX_ROWS
||
553 tmp
.cols
> DT3155_MAX_COLS
||
554 (tmp
.acq_mode
!= DT3155_MODE_FRAME
&&
555 tmp
.acq_mode
!= DT3155_MODE_FIELD
) ||
556 (tmp
.continuous
!= DT3155_SNAP
&&
557 tmp
.continuous
!= DT3155_ACQ
))
561 dt3155_status
[minor
].config
= tmp
;
565 case DT3155_GET_CONFIG
:
567 if (copy_to_user((void *) arg
, (void *) &dt3155_status
[minor
],
568 sizeof(dt3155_status_t
) ))
572 case DT3155_FLUSH
: /* Flushes the buffers -- ensures fresh data */
574 if (dt3155_status
[minor
].state
!= DT3155_STATE_IDLE
)
576 return dt3155_flush(minor
);
580 if (dt3155_status
[minor
].state
& DT3155_STATE_STOP
||
581 dt3155_status
[minor
].fbuffer
.stop_acquire
)
584 if (dt3155_status
[minor
].state
== DT3155_STATE_IDLE
)
588 if (copy_to_user((void *) arg
, (void *) &dt3155_status
[minor
],
589 sizeof(dt3155_status_t
)))
595 if (dt3155_status
[minor
].state
!= DT3155_STATE_IDLE
)
598 dt3155_status
[minor
].fbuffer
.stop_acquire
= 0;
599 dt3155_status
[minor
].fbuffer
.frame_count
= 0;
601 /* Set the MODE in the status -- we default to FRAME */
602 if (dt3155_status
[minor
].config
.acq_mode
== DT3155_MODE_FIELD
)
604 dt3155_status
[minor
].state
= DT3155_STATE_FLD
;
608 dt3155_status
[minor
].state
= DT3155_STATE_FRAME
;
611 dt3155_init_isr(minor
);
612 if (copy_to_user( (void *) arg
, (void *) &dt3155_status
[minor
],
613 sizeof(dt3155_status_t
)))
619 printk("DT3155: invalid IOCTL(0x%x)\n",cmd
);
620 printk("DT3155: Valid commands (0x%x), (0x%x), (0x%x), (0x%x), (0x%x)\n",
621 (unsigned int)DT3155_GET_CONFIG
,
622 (unsigned int)DT3155_SET_CONFIG
,
623 DT3155_START
, DT3155_STOP
, DT3155_FLUSH
);
630 /*****************************************************
633 * only allow the user to mmap the registers and buffer
634 * It is quite possible that this is broken, since the
635 * addition of of the capacity for two cards!!!!!!!!
636 * It *looks* like it should work but since I'm not
637 * sure how to use it, I'm not actually sure. (NJC? ditto by SS)
638 *****************************************************/
639 static int dt3155_mmap (struct file
* file
, struct vm_area_struct
* vma
)
641 /* which device are we mmapping? */
642 int minor
= MINOR(file
->f_dentry
->d_inode
->i_rdev
);
643 unsigned long offset
;
644 offset
= vma
->vm_pgoff
<< PAGE_SHIFT
;
646 if (offset
>= __pa(high_memory
) || (file
->f_flags
& O_SYNC
))
647 vma
->vm_flags
|= VM_IO
;
649 /* Don't try to swap out physical pages.. */
650 vma
->vm_flags
|= VM_RESERVED
;
652 /* they are mapping the registers or the buffer */
653 if ((offset
== dt3155_status
[minor
].reg_addr
&&
654 vma
->vm_end
- vma
->vm_start
== PCI_PAGE_SIZE
) ||
655 (offset
== dt3155_status
[minor
].mem_addr
&&
656 vma
->vm_end
- vma
->vm_start
== dt3155_status
[minor
].mem_size
))
658 if (remap_pfn_range(vma
,
660 offset
>> PAGE_SHIFT
,
661 vma
->vm_end
- vma
->vm_start
,
662 vma
->vm_page_prot
)) {
663 printk("DT3155: remap_page_range() failed.\n");
669 printk("DT3155: dt3155_mmap() bad call.\n");
677 /*****************************************************
680 * Our special open code.
681 * MOD_INC_USE_COUNT make sure that the driver memory is not freed
682 * while the device is in use.
683 *****************************************************/
684 static int dt3155_open( struct inode
* inode
, struct file
* filep
)
686 int minor
= MINOR(inode
->i_rdev
); /* what device are we opening? */
687 if (dt3155_dev_open
[ minor
]) {
688 printk ("DT3155: Already opened by another process.\n");
692 if (dt3155_status
[ minor
].device_installed
==0)
694 printk("DT3155 Open Error: No such device dt3155 minor number %d\n",
699 if (dt3155_status
[ minor
].state
!= DT3155_STATE_IDLE
) {
700 printk ("DT3155: Not in idle state (state = %x)\n",
701 dt3155_status
[ minor
].state
);
705 printk("DT3155: Device opened.\n");
707 dt3155_dev_open
[ minor
] = 1 ;
709 dt3155_flush( minor
);
711 /* Disable ALL interrupts */
713 WriteMReg( (dt3155_lbase
[ minor
] + INT_CSR
), int_csr_r
.reg
);
715 init_waitqueue_head(&(dt3155_read_wait_queue
[minor
]));
721 /*****************************************************
724 * Now decrement the use count.
726 *****************************************************/
727 static int dt3155_close( struct inode
*inode
, struct file
*filep
)
731 minor
= MINOR(inode
->i_rdev
); /* which device are we closing */
732 if (!dt3155_dev_open
[ minor
])
734 printk("DT3155: attempt to CLOSE a not OPEN device\n");
738 dt3155_dev_open
[ minor
] = 0;
740 if (dt3155_status
[ minor
].state
!= DT3155_STATE_IDLE
)
748 /*****************************************************
751 *****************************************************/
752 static ssize_t
dt3155_read(struct file
*filep
, char __user
*buf
,
753 size_t count
, loff_t
*ppos
)
755 /* which device are we reading from? */
756 int minor
= MINOR(filep
->f_dentry
->d_inode
->i_rdev
);
759 frame_info_t
*frame_info_p
;
761 /* TODO: this should check the error flag and */
762 /* return an error on hardware failures */
763 if (count
!= sizeof(dt3155_read_t
))
765 printk("DT3155 ERROR (NJC): count is not right\n");
770 /* Hack here -- I'm going to allow reading even when idle.
771 * this is so that the frames can be read after STOP has
772 * been called. Leaving it here, commented out, as a reminder
773 * for a short while to make sure there are no problems.
774 * Note that if the driver is not opened in non_blocking mode,
775 * and the device is idle, then it could sit here forever! */
777 /* if (dt3155_status[minor].state == DT3155_STATE_IDLE)*/
780 /* non-blocking reads should return if no data */
781 if (filep
->f_flags
& O_NDELAY
)
783 if ((frame_index
= dt3155_get_ready_buffer(minor
)) < 0) {
784 /*printk( "dt3155: no buffers available (?)\n");*/
785 /* printques(minor); */
792 * sleep till data arrives , or we get interrupted.
793 * Note that wait_event_interruptible() does not actually
794 * sleep/wait if it's condition evaluates to true upon entry.
796 wait_event_interruptible(dt3155_read_wait_queue
[minor
],
797 (frame_index
= dt3155_get_ready_buffer(minor
))
802 printk ("DT3155: read: interrupted\n");
809 frame_info_p
= &dt3155_status
[minor
].fbuffer
.frame_info
[frame_index
];
811 /* make this an offset */
812 offset
= frame_info_p
->addr
- dt3155_status
[minor
].mem_addr
;
814 put_user(offset
, (unsigned int *) buf
);
816 put_user( dt3155_status
[minor
].fbuffer
.frame_count
, (unsigned int *) buf
);
818 put_user(dt3155_status
[minor
].state
, (unsigned int *) buf
);
820 if (copy_to_user(buf
, frame_info_p
, sizeof(frame_info_t
)))
823 return sizeof(dt3155_read_t
);
826 static unsigned int dt3155_poll (struct file
* filp
, poll_table
*wait
)
828 int minor
= MINOR(filp
->f_dentry
->d_inode
->i_rdev
);
830 if (!is_ready_buf_empty(minor
))
831 return POLLIN
| POLLRDNORM
;
833 poll_wait (filp
, &dt3155_read_wait_queue
[minor
], wait
);
839 /*****************************************************
840 * file operations supported by DT3155 driver
841 * needed by init_module
843 *****************************************************/
844 static struct file_operations dt3155_fops
= {
850 release
: dt3155_close
854 /*****************************************************
857 * PCI has been totally reworked in 2.1..
858 *****************************************************/
859 static int find_PCI (void)
861 struct pci_dev
*pci_dev
= NULL
;
862 int error
, pci_index
= 0;
863 unsigned short rev_device
;
867 while ((pci_dev
= pci_get_device
868 (DT3155_VENDORID
, DT3155_DEVICEID
, pci_dev
)) != NULL
)
872 /* Is it really there? */
874 pci_read_config_word(pci_dev
, PCI_CLASS_DEVICE
, &rev_device
)))
878 DT_3155_DEBUG_MSG("DT3155: Device number %d \n", pci_index
);
880 /* Make sure the driver was compiled with enough buffers to handle
882 if (pci_index
> MAXBOARDS
) {
883 printk("DT3155: ERROR - found %d devices, but driver only configured "
885 "DT3155: Please change MAXBOARDS in dt3155.h\n",
886 pci_index
, MAXBOARDS
);
890 /* Now, just go out and make sure that this/these device(s) is/are
891 actually mapped into the kernel address space */
892 if ((error
= pci_read_config_dword( pci_dev
, PCI_BASE_ADDRESS_0
,
895 printk("DT3155: Was not able to find device \n");
899 DT_3155_DEBUG_MSG("DT3155: Base address 0 for device is %lx \n", base
);
900 dt3155_status
[pci_index
-1].reg_addr
= base
;
902 /* Remap the base address to a logical address through which we
904 dt3155_lbase
[ pci_index
- 1 ] = ioremap(base
,PCI_PAGE_SIZE
);
905 dt3155_status
[ pci_index
- 1 ].reg_addr
= base
;
906 DT_3155_DEBUG_MSG("DT3155: New logical address is %p \n",
907 dt3155_lbase
[pci_index
-1]);
908 if ( !dt3155_lbase
[pci_index
-1] )
910 printk("DT3155: Unable to remap control registers\n");
914 if ( (error
= pci_read_config_byte( pci_dev
, PCI_INTERRUPT_LINE
, &irq
)) )
916 printk("DT3155: Was not able to find device \n");
920 DT_3155_DEBUG_MSG("DT3155: IRQ is %d \n",irq
);
921 dt3155_status
[ pci_index
-1 ].irq
= irq
;
922 /* Set flag: kth device found! */
923 dt3155_status
[ pci_index
-1 ].device_installed
= 1;
924 printk("DT3155: Installing device %d w/irq %d and address %p\n",
926 dt3155_status
[pci_index
-1].irq
,
927 dt3155_lbase
[pci_index
-1]);
930 ndevices
= pci_index
;
932 return DT_3155_SUCCESS
;
935 pci_dev_put(pci_dev
);
936 return DT_3155_FAILURE
;
939 u32 allocatorAddr
= 0;
941 /*****************************************************
943 *****************************************************/
944 int init_module(void)
948 char *devname
[ MAXBOARDS
];
950 devname
[ 0 ] = "dt3155a";
952 devname
[ 1 ] = "dt3155b";
955 printk("DT3155: Loading module...\n");
957 /* Register the device driver */
958 rcode
= register_chrdev( dt3155_major
, "dt3155", &dt3155_fops
);
961 printk( KERN_INFO
"DT3155: register_chrdev failed \n");
965 if( dt3155_major
== 0 )
966 dt3155_major
= rcode
; /* dynamic */
969 /* init the status variables. */
970 /* DMA memory is taken care of in setup_buffers() */
971 for ( index
= 0; index
< MAXBOARDS
; index
++ )
973 dt3155_status
[ index
].config
.acq_mode
= DT3155_MODE_FRAME
;
974 dt3155_status
[ index
].config
.continuous
= DT3155_ACQ
;
975 dt3155_status
[ index
].config
.cols
= DT3155_MAX_COLS
;
976 dt3155_status
[ index
].config
.rows
= DT3155_MAX_ROWS
;
977 dt3155_status
[ index
].state
= DT3155_STATE_IDLE
;
979 /* find_PCI() will check if devices are installed; */
980 /* first assume they're not: */
981 dt3155_status
[ index
].mem_addr
= 0;
982 dt3155_status
[ index
].mem_size
= 0;
983 dt3155_status
[ index
].state
= DT3155_STATE_IDLE
;
984 dt3155_status
[ index
].device_installed
= 0;
987 /* Now let's find the hardware. find_PCI() will set ndevices to the
988 * number of cards found in this machine. */
990 if ( (rcode
= find_PCI()) != DT_3155_SUCCESS
)
992 printk("DT3155 error: find_PCI() failed to find dt3155 board(s)\n");
993 unregister_chrdev( dt3155_major
, "dt3155" );
998 /* Ok, time to setup the frame buffers */
999 if( (rcode
= dt3155_setup_buffers(&allocatorAddr
)) < 0 )
1001 printk("DT3155: Error: setting up buffer not large enough.");
1002 unregister_chrdev( dt3155_major
, "dt3155" );
1006 /* If we are this far, then there is enough RAM */
1007 /* for the buffers: Print the configuration. */
1008 for( index
= 0; index
< ndevices
; index
++ )
1010 printk("DT3155: Device = %d; acq_mode = %d; "
1011 "continuous = %d; cols = %d; rows = %d;\n",
1013 dt3155_status
[ index
].config
.acq_mode
,
1014 dt3155_status
[ index
].config
.continuous
,
1015 dt3155_status
[ index
].config
.cols
,
1016 dt3155_status
[ index
].config
.rows
);
1017 printk("DT3155: m_addr = 0x%x; m_size = %ld; "
1018 "state = %d; device_installed = %d\n",
1019 dt3155_status
[ index
].mem_addr
,
1020 (long int)dt3155_status
[ index
].mem_size
,
1021 dt3155_status
[ index
].state
,
1022 dt3155_status
[ index
].device_installed
);
1025 /* Disable ALL interrupts */
1027 for( index
= 0; index
< ndevices
; index
++ )
1029 WriteMReg( (dt3155_lbase
[ index
] + INT_CSR
), int_csr_r
.reg
);
1030 if( dt3155_status
[ index
].device_installed
)
1033 * This driver *looks* like it can handle sharing interrupts,
1034 * but I can't actually test myself. I've had reports that it
1035 * DOES work so I'll enable it for now. This comment will remain
1036 * as a reminder in case any problems arise. (SS)
1038 /* in older kernels flags are: SA_SHIRQ | SA_INTERRUPT */
1039 rcode
= request_irq( dt3155_status
[ index
].irq
, (void *)dt3155_isr
,
1040 IRQF_SHARED
| IRQF_DISABLED
, devname
[ index
],
1041 (void*) &dt3155_status
[index
]);
1044 printk("DT3155: minor %d request_irq failed for IRQ %d\n",
1045 index
, dt3155_status
[index
].irq
);
1046 unregister_chrdev( dt3155_major
, "dt3155" );
1052 printk("DT3155: finished loading\n");
1057 /*****************************************************
1058 * cleanup_module(void)
1060 *****************************************************/
1061 void cleanup_module(void)
1065 printk("DT3155: cleanup_module called\n");
1067 /* removed DMA allocated with the allocator */
1068 #ifdef STANDALONE_ALLOCATOR
1069 if (allocatorAddr
!= 0)
1070 allocator_free_dma(allocatorAddr
);
1072 allocator_cleanup();
1075 unregister_chrdev( dt3155_major
, "dt3155" );
1077 for( index
= 0; index
< ndevices
; index
++ )
1079 if( dt3155_status
[ index
].device_installed
== 1 )
1081 printk( "DT3155: Freeing irq %d for device %d\n",
1082 dt3155_status
[ index
].irq
, index
);
1083 free_irq( dt3155_status
[ index
].irq
, (void*)&dt3155_status
[index
] );