Staging: d53155_drv.c: cleanup fbuffer usage
[deliverable/linux.git] / drivers / staging / dt3155 / dt3155_drv.c
1 /*
2
3 Copyright 1996,2002,2005 Gregory D. Hager, Alfred A. Rizzi, Noah J. Cowan,
4 Jason Lapenta, Scott Smedley, Greg Sharp
5
6 This file is part of the DT3155 Device Driver.
7
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.
12
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.
17
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,
21 MA 02111-1307 USA
22
23 -- Changes --
24
25 Date Programmer Description of changes made
26 -------------------------------------------------------------------
27 03-Jul-2000 JML n/a
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.
40
41 -- Notes --
42
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)
46
47 + might want to get rid of MAXboards for allocating initial buffer.
48 confusing and not necessary
49
50 + in cleanup_module the MOD_IN_USE looks like it is check after it should
51
52 * GFP_DMA should not be set with a PCI system (pg 291)
53
54 - NJC why are only two buffers allowed? (see isr, approx line 358)
55
56 */
57
58 extern void printques(int);
59
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>
67 #include <linux/io.h>
68
69 #include <asm/uaccess.h>
70
71 #include "dt3155.h"
72 #include "dt3155_drv.h"
73 #include "dt3155_isr.h"
74 #include "dt3155_io.h"
75 #include "allocator.h"
76
77
78 MODULE_LICENSE("GPL");
79
80 /* Error variable. Zero means no error. */
81 int dt3155_errno = 0;
82
83 #ifndef PCI_DEVICE_ID_INTEL_7116
84 #define PCI_DEVICE_ID_INTEL_7116 0x1223
85 #endif
86
87 #define DT3155_VENDORID PCI_VENDOR_ID_INTEL
88 #define DT3155_DEVICEID PCI_DEVICE_ID_INTEL_7116
89 #define MAXPCI 16
90
91 #ifdef DT_DEBUG
92 #define DT_3155_DEBUG_MSG(x,y) printk(x,y)
93 #else
94 #define DT_3155_DEBUG_MSG(x,y)
95 #endif
96
97 /* wait queue for interrupts */
98 wait_queue_head_t dt3155_read_wait_queue[MAXBOARDS];
99
100 /* set to dynamicaly allocate, but it is tunable: */
101 /* insmod DT_3155 dt3155 dt3155_major=XX */
102 int dt3155_major = 0;
103
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
107 */
108
109 /* Global structures and variables */
110
111 /* Status of each device */
112 struct dt3155_status dt3155_status[MAXBOARDS];
113
114 /* kernel logical address of the board */
115 static void __iomem *dt3155_lbase[MAXBOARDS] = { NULL
116 #if MAXBOARDS == 2
117 , NULL
118 #endif
119 };
120
121 u32 dt3155_dev_open[MAXBOARDS] = {0
122 #if MAXBOARDS == 2
123 , 0
124 #endif
125 };
126
127 u32 ndevices = 0;
128 u32 unique_tag = 0;;
129
130
131 /*
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.
134 * (James Rose)
135 */
136 static void quick_stop (int minor)
137 {
138 struct dt3155_fbuffer *fb = &dt3155_status[minor].fbuffer;
139
140 // TODO: scott was here
141 #if 1
142 int_csr_r.reg = readl(dt3155_lbase[minor] + INT_CSR);
143 /* disable interrupts */
144 int_csr_r.fld.FLD_END_EVE_EN = 0;
145 int_csr_r.fld.FLD_END_ODD_EN = 0;
146 writel(int_csr_r.reg, dt3155_lbase[minor] + INT_CSR);
147
148 dt3155_status[minor].state &= ~(DT3155_STATE_STOP|0xff);
149 /* mark the system stopped: */
150 dt3155_status[minor].state |= DT3155_STATE_IDLE;
151 fb->stop_acquire = 0;
152 fb->even_stopped = 0;
153 #else
154 dt3155_status[minor].state |= DT3155_STATE_STOP;
155 fb->stop_acquire = 1;
156 #endif
157
158 }
159
160
161 /*****************************************************
162 * dt3155_isr() Interrupt service routien
163 *
164 * - looks like this isr supports IRQ sharing (or could) JML
165 * - Assumes irq's are disabled, via SA_INTERRUPT flag
166 * being set in request_irq() call from init_module()
167 *****************************************************/
168 static void dt3155_isr(int irq, void *dev_id, struct pt_regs *regs)
169 {
170 int minor = -1;
171 int index;
172 unsigned long flags;
173 u32 buffer_addr;
174 void __iomem *mmio;
175 struct dt3155_fbuffer *fb;
176
177 /* find out who issued the interrupt */
178 for (index = 0; index < ndevices; index++) {
179 if(dev_id == (void*) &dt3155_status[index])
180 {
181 minor = index;
182 break;
183 }
184 }
185
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");
189 return;
190 }
191
192 mmio = dt3155_lbase[minor];
193 fb = &dt3155_status[minor].fbuffer;
194
195 /* Check for corruption and set a flag if so */
196 csr1_r.reg = readl(mmio + CSR1);
197
198 if ((csr1_r.fld.FLD_CRPT_EVE) || (csr1_r.fld.FLD_CRPT_ODD))
199 {
200 /* TODO: this should probably stop acquisition */
201 /* and set some flags so that dt3155_read */
202 /* returns an error next time it is called */
203 dt3155_errno = DT_ERR_CORRUPT;
204 printk("dt3155: corrupt field\n");
205 return;
206 }
207
208 int_csr_r.reg = readl(mmio + INT_CSR);
209
210 /* Handle the even field ... */
211 if (int_csr_r.fld.FLD_END_EVE)
212 {
213 if ((dt3155_status[minor].state & DT3155_STATE_MODE) ==
214 DT3155_STATE_FLD)
215 {
216 fb->frame_count++;
217 }
218
219 ReadI2C(mmio, EVEN_CSR, &i2c_even_csr.reg);
220
221 /* Clear the interrupt? */
222 int_csr_r.fld.FLD_END_EVE = 1;
223
224 /* disable the interrupt if last field */
225 if (fb->stop_acquire)
226 {
227 printk("dt3155: even stopped.\n");
228 fb->even_stopped = 1;
229 if (i2c_even_csr.fld.SNGL_EVE)
230 {
231 int_csr_r.fld.FLD_END_EVE_EN = 0;
232 }
233 else
234 {
235 i2c_even_csr.fld.SNGL_EVE = 1;
236 }
237 }
238
239 writel(int_csr_r.reg, mmio + INT_CSR);
240
241 /* Set up next DMA if we are doing FIELDS */
242 if ((dt3155_status[minor].state & DT3155_STATE_MODE) ==
243 DT3155_STATE_FLD)
244 {
245 /* GCS (Aug 2, 2002) -- In field mode, dma the odd field
246 into the lower half of the buffer */
247 const u32 stride = dt3155_status[minor].config.cols;
248 buffer_addr = fb->frame_info[fb->active_buf].addr +
249 (DT3155_MAX_ROWS / 2) * stride;
250 local_save_flags(flags);
251 local_irq_disable();
252 wake_up_interruptible(&dt3155_read_wait_queue[minor]);
253
254 /* Set up the DMA address for the next field */
255 local_irq_restore(flags);
256 writel(buffer_addr, mmio + ODD_DMA_START);
257 }
258
259 /* Check for errors. */
260 i2c_even_csr.fld.DONE_EVE = 1;
261 if (i2c_even_csr.fld.ERROR_EVE)
262 dt3155_errno = DT_ERR_OVERRUN;
263
264 WriteI2C(mmio, EVEN_CSR, i2c_even_csr.reg);
265
266 /* Note that we actually saw an even field meaning */
267 /* that subsequent odd field complete the frame */
268 fb->even_happened = 1;
269
270 /* recording the time that the even field finished, this should be */
271 /* about time in the middle of the frame */
272 do_gettimeofday(&fb->frame_info[fb->active_buf].time);
273 return;
274 }
275
276 /* ... now handle the odd field */
277 if (int_csr_r.fld.FLD_END_ODD)
278 {
279 ReadI2C(mmio, ODD_CSR, &i2c_odd_csr.reg);
280
281 /* Clear the interrupt? */
282 int_csr_r.fld.FLD_END_ODD = 1;
283
284 if (fb->even_happened ||
285 (dt3155_status[minor].state & DT3155_STATE_MODE) ==
286 DT3155_STATE_FLD)
287 {
288 fb->frame_count++;
289 }
290
291 if (fb->stop_acquire && fb->even_stopped)
292 {
293 printk(KERN_DEBUG "dt3155: stopping odd..\n");
294 if (i2c_odd_csr.fld.SNGL_ODD)
295 {
296 /* disable interrupts */
297 int_csr_r.fld.FLD_END_ODD_EN = 0;
298 dt3155_status[minor].state &= ~(DT3155_STATE_STOP|0xff);
299
300 /* mark the system stopped: */
301 dt3155_status[minor].state |= DT3155_STATE_IDLE;
302 fb->stop_acquire = 0;
303 fb->even_stopped = 0;
304
305 printk(KERN_DEBUG "dt3155: state is now %x\n",
306 dt3155_status[minor].state);
307 }
308 else
309 {
310 i2c_odd_csr.fld.SNGL_ODD = 1;
311 }
312 }
313
314 writel(int_csr_r.reg, mmio + INT_CSR);
315
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 (fb->even_happened ||
320 (dt3155_status[minor].state & DT3155_STATE_MODE) ==
321 DT3155_STATE_FLD)
322 {
323
324 local_save_flags(flags);
325 local_irq_disable();
326
327 #ifdef DEBUG_QUES_B
328 printques(minor);
329 #endif
330 if (fb->nbuffers > 2)
331 {
332 if (!are_empty_buffers(minor))
333 {
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);
339 }
340
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, fb->active_buf);
345 /* There's at least 1 empty -- make it active */
346 fb->active_buf = pop_empty(minor);
347 fb->frame_info[fb->active_buf].tag = ++unique_tag;
348 }
349 else /* nbuffers == 2, special case */
350 { /* There is 1 active buffer.
351 * If there is a locked buffer, keep the active buffer
352 * the same -- that means we drop a frame.
353 */
354 if (fb->locked_buf < 0)
355 {
356 push_ready(minor, fb->active_buf);
357 if (are_empty_buffers(minor))
358 {
359 fb->active_buf = pop_empty(minor);
360 }
361 else
362 { /* no empty or locked buffers, so use a readybuf */
363 fb->active_buf = pop_ready(minor);
364 }
365 }
366 }
367
368 #ifdef DEBUG_QUES_B
369 printques(minor);
370 #endif
371
372 fb->even_happened = 0;
373
374 wake_up_interruptible(&dt3155_read_wait_queue[minor]);
375
376 local_irq_restore(flags);
377 }
378
379
380 /* Set up the DMA address for the next frame/field */
381 buffer_addr = fb->frame_info[fb->active_buf].addr;
382 if ((dt3155_status[minor].state & DT3155_STATE_MODE) ==
383 DT3155_STATE_FLD)
384 {
385 writel(buffer_addr, mmio + EVEN_DMA_START);
386 }
387 else
388 {
389 writel(buffer_addr, mmio + EVEN_DMA_START);
390
391 writel(buffer_addr + dt3155_status[minor].config.cols,
392 mmio + ODD_DMA_START);
393 }
394
395 /* Do error checking */
396 i2c_odd_csr.fld.DONE_ODD = 1;
397 if (i2c_odd_csr.fld.ERROR_ODD)
398 dt3155_errno = DT_ERR_OVERRUN;
399
400 WriteI2C(mmio, ODD_CSR, i2c_odd_csr.reg);
401
402 return;
403 }
404 /* If we get here, the Odd Field wasn't it either... */
405 printk("neither even nor odd. shared perhaps?\n");
406 }
407
408 /*****************************************************
409 * init_isr(int minor)
410 * turns on interupt generation for the card
411 * designated by "minor".
412 * It is called *only* from inside ioctl().
413 *****************************************************/
414 static void dt3155_init_isr(int minor)
415 {
416 const u32 stride = dt3155_status[minor].config.cols;
417 void __iomem *mmio = dt3155_lbase[minor];
418 struct dt3155_fbuffer *fb = &dt3155_status[minor].fbuffer;
419
420 switch (dt3155_status[minor].state & DT3155_STATE_MODE)
421 {
422 case DT3155_STATE_FLD:
423 {
424 even_dma_start_r = fb->frame_info[fb->active_buf].addr;
425 even_dma_stride_r = 0;
426 odd_dma_stride_r = 0;
427
428 writel(even_dma_start_r, mmio + EVEN_DMA_START);
429 writel(even_dma_stride_r, mmio + EVEN_DMA_STRIDE);
430 writel(odd_dma_stride_r, mmio + ODD_DMA_STRIDE);
431 break;
432 }
433
434 case DT3155_STATE_FRAME:
435 default:
436 {
437 even_dma_start_r = fb->frame_info[fb->active_buf].addr;
438 odd_dma_start_r = even_dma_start_r + stride;
439 even_dma_stride_r = stride;
440 odd_dma_stride_r = stride;
441
442 writel(even_dma_start_r, mmio + EVEN_DMA_START);
443 writel(odd_dma_start_r, mmio + ODD_DMA_START);
444 writel(even_dma_stride_r, mmio + EVEN_DMA_STRIDE);
445 writel(odd_dma_stride_r, mmio + ODD_DMA_STRIDE);
446 break;
447 }
448 }
449
450 /* 50/60 Hz should be set before this point but let's make sure it is */
451 /* right anyway */
452
453 ReadI2C(mmio, CSR2, &i2c_csr2.reg);
454 i2c_csr2.fld.HZ50 = FORMAT50HZ;
455 WriteI2C(mmio, CSR2, i2c_csr2.reg);
456
457 /* enable busmaster chip, clear flags */
458
459 /*
460 * TODO:
461 * shouldn't we be concered with continuous values of
462 * DT3155_SNAP & DT3155_ACQ here? (SS)
463 */
464
465 csr1_r.reg = 0;
466 csr1_r.fld.CAP_CONT_EVE = 1; /* use continuous capture bits to */
467 csr1_r.fld.CAP_CONT_ODD = 1; /* enable */
468 csr1_r.fld.FLD_DN_EVE = 1; /* writing a 1 clears flags */
469 csr1_r.fld.FLD_DN_ODD = 1;
470 csr1_r.fld.SRST = 1; /* reset - must be 1 */
471 csr1_r.fld.FIFO_EN = 1; /* fifo control - must be 1 */
472 csr1_r.fld.FLD_CRPT_EVE = 1; /* writing a 1 clears flags */
473 csr1_r.fld.FLD_CRPT_ODD = 1;
474
475 writel(csr1_r.reg, mmio + CSR1);
476
477 /* Enable interrupts at the end of each field */
478
479 int_csr_r.reg = 0;
480 int_csr_r.fld.FLD_END_EVE_EN = 1;
481 int_csr_r.fld.FLD_END_ODD_EN = 1;
482 int_csr_r.fld.FLD_START_EN = 0;
483
484 writel(int_csr_r.reg, mmio + INT_CSR);
485
486 /* start internal BUSY bits */
487
488 ReadI2C(mmio, CSR2, &i2c_csr2.reg);
489 i2c_csr2.fld.BUSY_ODD = 1;
490 i2c_csr2.fld.BUSY_EVE = 1;
491 WriteI2C(mmio, CSR2, i2c_csr2.reg);
492
493 /* Now its up to the interrupt routine!! */
494
495 return;
496 }
497
498
499 /*****************************************************
500 * ioctl()
501 *
502 *****************************************************/
503 static int dt3155_ioctl(struct inode *inode,
504 struct file *file,
505 unsigned int cmd,
506 unsigned long arg)
507 {
508 int minor = MINOR(inode->i_rdev); /* What device are we ioctl()'ing? */
509 void __user *up = (void __user *)arg;
510 struct dt3155_fbuffer *fb = &dt3155_status[minor].fbuffer;
511
512 if (minor >= MAXBOARDS || minor < 0)
513 return -ENODEV;
514
515 /* make sure it is valid command */
516 if (_IOC_NR(cmd) > DT3155_IOC_MAXNR)
517 {
518 printk("DT3155: invalid IOCTL(0x%x)\n",cmd);
519 printk("DT3155: Valid commands (0x%x), (0x%x), (0x%x), (0x%x), (0x%x)\n",
520 (unsigned int)DT3155_GET_CONFIG,
521 (unsigned int)DT3155_SET_CONFIG,
522 (unsigned int)DT3155_START,
523 (unsigned int)DT3155_STOP,
524 (unsigned int)DT3155_FLUSH);
525 return -EINVAL;
526 }
527
528 switch (cmd)
529 {
530 case DT3155_SET_CONFIG:
531 {
532 if (dt3155_status[minor].state != DT3155_STATE_IDLE)
533 return -EBUSY;
534
535 {
536 struct dt3155_config tmp;
537 if (copy_from_user(&tmp, up, sizeof(tmp)))
538 return -EFAULT;
539 /* check for valid settings */
540 if (tmp.rows > DT3155_MAX_ROWS ||
541 tmp.cols > DT3155_MAX_COLS ||
542 (tmp.acq_mode != DT3155_MODE_FRAME &&
543 tmp.acq_mode != DT3155_MODE_FIELD) ||
544 (tmp.continuous != DT3155_SNAP &&
545 tmp.continuous != DT3155_ACQ))
546 {
547 return -EINVAL;
548 }
549 dt3155_status[minor].config = tmp;
550 }
551 return 0;
552 }
553 case DT3155_GET_CONFIG:
554 {
555 if (copy_to_user(up, &dt3155_status[minor],
556 sizeof(struct dt3155_status)))
557 return -EFAULT;
558 return 0;
559 }
560 case DT3155_FLUSH: /* Flushes the buffers -- ensures fresh data */
561 {
562 if (dt3155_status[minor].state != DT3155_STATE_IDLE)
563 return -EBUSY;
564 return dt3155_flush(minor);
565 }
566 case DT3155_STOP:
567 {
568 if (dt3155_status[minor].state & DT3155_STATE_STOP ||
569 fb->stop_acquire)
570 return -EBUSY;
571
572 if (dt3155_status[minor].state == DT3155_STATE_IDLE)
573 return 0;
574
575 quick_stop(minor);
576 if (copy_to_user(up, &dt3155_status[minor],
577 sizeof(struct dt3155_status)))
578 return -EFAULT;
579 return 0;
580 }
581 case DT3155_START:
582 {
583 if (dt3155_status[minor].state != DT3155_STATE_IDLE)
584 return -EBUSY;
585
586 fb->stop_acquire = 0;
587 fb->frame_count = 0;
588
589 /* Set the MODE in the status -- we default to FRAME */
590 if (dt3155_status[minor].config.acq_mode == DT3155_MODE_FIELD)
591 {
592 dt3155_status[minor].state = DT3155_STATE_FLD;
593 }
594 else
595 {
596 dt3155_status[minor].state = DT3155_STATE_FRAME;
597 }
598
599 dt3155_init_isr(minor);
600 if (copy_to_user(up, &dt3155_status[minor],
601 sizeof(struct dt3155_status)))
602 return -EFAULT;
603 return 0;
604 }
605 default:
606 {
607 printk("DT3155: invalid IOCTL(0x%x)\n",cmd);
608 printk("DT3155: Valid commands (0x%x), (0x%x), (0x%x), (0x%x), (0x%x)\n",
609 (unsigned int)DT3155_GET_CONFIG,
610 (unsigned int)DT3155_SET_CONFIG,
611 DT3155_START, DT3155_STOP, DT3155_FLUSH);
612 return -ENOSYS;
613 }
614 }
615 return -ENOSYS;
616 }
617
618 /*****************************************************
619 * mmap()
620 *
621 * only allow the user to mmap the registers and buffer
622 * It is quite possible that this is broken, since the
623 * addition of of the capacity for two cards!!!!!!!!
624 * It *looks* like it should work but since I'm not
625 * sure how to use it, I'm not actually sure. (NJC? ditto by SS)
626 *****************************************************/
627 static int dt3155_mmap (struct file * file, struct vm_area_struct * vma)
628 {
629 /* which device are we mmapping? */
630 int minor = MINOR(file->f_dentry->d_inode->i_rdev);
631 unsigned long offset;
632 offset = vma->vm_pgoff << PAGE_SHIFT;
633
634 if (offset >= __pa(high_memory) || (file->f_flags & O_SYNC))
635 vma->vm_flags |= VM_IO;
636
637 /* Don't try to swap out physical pages.. */
638 vma->vm_flags |= VM_RESERVED;
639
640 /* they are mapping the registers or the buffer */
641 if ((offset == dt3155_status[minor].reg_addr &&
642 vma->vm_end - vma->vm_start == PCI_PAGE_SIZE) ||
643 (offset == dt3155_status[minor].mem_addr &&
644 vma->vm_end - vma->vm_start == dt3155_status[minor].mem_size))
645 {
646 if (remap_pfn_range(vma,
647 vma->vm_start,
648 offset >> PAGE_SHIFT,
649 vma->vm_end - vma->vm_start,
650 vma->vm_page_prot)) {
651 printk("DT3155: remap_page_range() failed.\n");
652 return -EAGAIN;
653 }
654 }
655 else
656 {
657 printk("DT3155: dt3155_mmap() bad call.\n");
658 return -ENXIO;
659 }
660
661 return 0;
662 }
663
664
665 /*****************************************************
666 * open()
667 *
668 * Our special open code.
669 * MOD_INC_USE_COUNT make sure that the driver memory is not freed
670 * while the device is in use.
671 *****************************************************/
672 static int dt3155_open(struct inode* inode, struct file* filep)
673 {
674 int minor = MINOR(inode->i_rdev); /* what device are we opening? */
675 if (dt3155_dev_open[minor]) {
676 printk ("DT3155: Already opened by another process.\n");
677 return -EBUSY;
678 }
679
680 if (dt3155_status[minor].device_installed==0)
681 {
682 printk("DT3155 Open Error: No such device dt3155 minor number %d\n",
683 minor);
684 return -EIO;
685 }
686
687 if (dt3155_status[minor].state != DT3155_STATE_IDLE) {
688 printk ("DT3155: Not in idle state (state = %x)\n",
689 dt3155_status[minor].state);
690 return -EBUSY;
691 }
692
693 printk("DT3155: Device opened.\n");
694
695 dt3155_dev_open[minor] = 1 ;
696
697 dt3155_flush(minor);
698
699 /* Disable ALL interrupts */
700 int_csr_r.reg = 0;
701 writel(int_csr_r.reg, dt3155_lbase[minor] + INT_CSR);
702
703 init_waitqueue_head(&(dt3155_read_wait_queue[minor]));
704
705 return 0;
706 }
707
708
709 /*****************************************************
710 * close()
711 *
712 * Now decrement the use count.
713 *
714 *****************************************************/
715 static int dt3155_close(struct inode *inode, struct file *filep)
716 {
717 int minor;
718
719 minor = MINOR(inode->i_rdev); /* which device are we closing */
720 if (!dt3155_dev_open[minor])
721 {
722 printk("DT3155: attempt to CLOSE a not OPEN device\n");
723 }
724 else
725 {
726 dt3155_dev_open[minor] = 0;
727
728 if (dt3155_status[minor].state != DT3155_STATE_IDLE)
729 {
730 quick_stop(minor);
731 }
732 }
733 return 0;
734 }
735
736 /*****************************************************
737 * read()
738 *
739 *****************************************************/
740 static ssize_t dt3155_read(struct file *filep, char __user *buf,
741 size_t count, loff_t *ppos)
742 {
743 /* which device are we reading from? */
744 int minor = MINOR(filep->f_dentry->d_inode->i_rdev);
745 u32 offset;
746 int frame_index;
747 struct dt3155_fbuffer *fb = &dt3155_status[minor].fbuffer;
748 struct frame_info *frame_info;
749
750 /* TODO: this should check the error flag and */
751 /* return an error on hardware failures */
752 if (count != sizeof(struct dt3155_read))
753 {
754 printk("DT3155 ERROR (NJC): count is not right\n");
755 return -EINVAL;
756 }
757
758
759 /* Hack here -- I'm going to allow reading even when idle.
760 * this is so that the frames can be read after STOP has
761 * been called. Leaving it here, commented out, as a reminder
762 * for a short while to make sure there are no problems.
763 * Note that if the driver is not opened in non_blocking mode,
764 * and the device is idle, then it could sit here forever! */
765
766 /* if (dt3155_status[minor].state == DT3155_STATE_IDLE)*/
767 /* return -EBUSY;*/
768
769 /* non-blocking reads should return if no data */
770 if (filep->f_flags & O_NDELAY)
771 {
772 if ((frame_index = dt3155_get_ready_buffer(minor)) < 0) {
773 /*printk("dt3155: no buffers available (?)\n");*/
774 /* printques(minor); */
775 return -EAGAIN;
776 }
777 }
778 else
779 {
780 /*
781 * sleep till data arrives , or we get interrupted.
782 * Note that wait_event_interruptible() does not actually
783 * sleep/wait if it's condition evaluates to true upon entry.
784 */
785 wait_event_interruptible(dt3155_read_wait_queue[minor],
786 (frame_index = dt3155_get_ready_buffer(minor))
787 >= 0);
788
789 if (frame_index < 0)
790 {
791 printk ("DT3155: read: interrupted\n");
792 quick_stop (minor);
793 printques(minor);
794 return -EINTR;
795 }
796 }
797
798 frame_info = &fb->frame_info[frame_index];
799
800 /* make this an offset */
801 offset = frame_info->addr - dt3155_status[minor].mem_addr;
802
803 put_user(offset, (unsigned int __user *)buf);
804 buf += sizeof(u32);
805 put_user(fb->frame_count, (unsigned int __user *)buf);
806 buf += sizeof(u32);
807 put_user(dt3155_status[minor].state, (unsigned int __user *)buf);
808 buf += sizeof(u32);
809 if (copy_to_user(buf, frame_info, sizeof(*frame_info)))
810 return -EFAULT;
811
812 return sizeof(struct dt3155_read);
813 }
814
815 static unsigned int dt3155_poll (struct file * filp, poll_table *wait)
816 {
817 int minor = MINOR(filp->f_dentry->d_inode->i_rdev);
818
819 if (!is_ready_buf_empty(minor))
820 return POLLIN | POLLRDNORM;
821
822 poll_wait (filp, &dt3155_read_wait_queue[minor], wait);
823
824 return 0;
825 }
826
827 static long
828 dt3155_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
829 {
830 int ret;
831
832 lock_kernel();
833 ret = dt3155_ioctl(file->f_path.dentry->d_inode, file, cmd, arg);
834 unlock_kernel();
835
836 return ret;
837 }
838
839 /*****************************************************
840 * file operations supported by DT3155 driver
841 * needed by init_module
842 * register_chrdev
843 *****************************************************/
844 static struct file_operations dt3155_fops = {
845 .read = dt3155_read,
846 .unlocked_ioctl = dt3155_unlocked_ioctl,
847 .mmap = dt3155_mmap,
848 .poll = dt3155_poll,
849 .open = dt3155_open,
850 .release = dt3155_close
851 };
852
853
854 /*****************************************************
855 * find_PCI();
856 *
857 * PCI has been totally reworked in 2.1..
858 *****************************************************/
859 static int find_PCI (void)
860 {
861 struct pci_dev *pci_dev = NULL;
862 int error, pci_index = 0;
863 unsigned short rev_device;
864 unsigned long base;
865 unsigned char irq;
866
867 while ((pci_dev = pci_get_device
868 (DT3155_VENDORID, DT3155_DEVICEID, pci_dev)) != NULL)
869 {
870 pci_index ++;
871
872 /* Is it really there? */
873 if ((error =
874 pci_read_config_word(pci_dev, PCI_CLASS_DEVICE, &rev_device)))
875 continue;
876
877 /* Found a board */
878 DT_3155_DEBUG_MSG("DT3155: Device number %d \n", pci_index);
879
880 /* Make sure the driver was compiled with enough buffers to handle
881 this many boards */
882 if (pci_index > MAXBOARDS) {
883 printk("DT3155: ERROR - found %d devices, but driver only configured "
884 "for %d devices\n"
885 "DT3155: Please change MAXBOARDS in dt3155.h\n",
886 pci_index, MAXBOARDS);
887 goto err;
888 }
889
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,
893 (u32 *) &base)))
894 {
895 printk("DT3155: Was not able to find device \n");
896 goto err;
897 }
898
899 DT_3155_DEBUG_MSG("DT3155: Base address 0 for device is %lx \n", base);
900 dt3155_status[pci_index-1].reg_addr = base;
901
902 /* Remap the base address to a logical address through which we
903 * can access it. */
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])
909 {
910 printk("DT3155: Unable to remap control registers\n");
911 goto err;
912 }
913
914 if ((error = pci_read_config_byte(pci_dev, PCI_INTERRUPT_LINE, &irq)))
915 {
916 printk("DT3155: Was not able to find device \n");
917 goto err;
918 }
919
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",
925 pci_index,
926 dt3155_status[pci_index-1].irq,
927 dt3155_lbase[pci_index-1]);
928
929 }
930 ndevices = pci_index;
931
932 return 0;
933
934 err:
935 pci_dev_put(pci_dev);
936 return -EIO;
937 }
938
939 u32 allocatorAddr = 0;
940
941 /*****************************************************
942 * init_module()
943 *****************************************************/
944 int init_module(void)
945 {
946 int index;
947 int rcode = 0;
948 char *devname[MAXBOARDS];
949
950 devname[0] = "dt3155a";
951 #if MAXBOARDS == 2
952 devname[1] = "dt3155b";
953 #endif
954
955 printk("DT3155: Loading module...\n");
956
957 /* Register the device driver */
958 rcode = register_chrdev(dt3155_major, "dt3155", &dt3155_fops);
959 if(rcode < 0)
960 {
961 printk(KERN_INFO "DT3155: register_chrdev failed \n");
962 return rcode;
963 }
964
965 if(dt3155_major == 0)
966 dt3155_major = rcode; /* dynamic */
967
968
969 /* init the status variables. */
970 /* DMA memory is taken care of in setup_buffers() */
971 for (index = 0; index < MAXBOARDS; index++)
972 {
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;
978
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;
985 }
986
987 /* Now let's find the hardware. find_PCI() will set ndevices to the
988 * number of cards found in this machine. */
989 {
990 if ((rcode = find_PCI()) != 0)
991 {
992 printk("DT3155 error: find_PCI() failed to find dt3155 board(s)\n");
993 unregister_chrdev(dt3155_major, "dt3155");
994 return rcode;
995 }
996 }
997
998 /* Ok, time to setup the frame buffers */
999 if((rcode = dt3155_setup_buffers(&allocatorAddr)) < 0)
1000 {
1001 printk("DT3155: Error: setting up buffer not large enough.");
1002 unregister_chrdev(dt3155_major, "dt3155");
1003 return rcode;
1004 }
1005
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++)
1009 {
1010 printk("DT3155: Device = %d; acq_mode = %d; "
1011 "continuous = %d; cols = %d; rows = %d;\n",
1012 index ,
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);
1023 }
1024
1025 /* Disable ALL interrupts */
1026 int_csr_r.reg = 0;
1027 for( index = 0; index < ndevices; index++)
1028 {
1029 writel(int_csr_r.reg, dt3155_lbase[index] + INT_CSR);
1030 if(dt3155_status[index].device_installed)
1031 {
1032 /*
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)
1037 */
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]);
1042 if(rcode < 0)
1043 {
1044 printk("DT3155: minor %d request_irq failed for IRQ %d\n",
1045 index, dt3155_status[index].irq);
1046 unregister_chrdev(dt3155_major, "dt3155");
1047 return rcode;
1048 }
1049 }
1050 }
1051
1052 printk("DT3155: finished loading\n");
1053
1054 return 0;
1055 }
1056
1057 /*****************************************************
1058 * cleanup_module(void)
1059 *
1060 *****************************************************/
1061 void cleanup_module(void)
1062 {
1063 int index;
1064
1065 printk("DT3155: cleanup_module called\n");
1066
1067 /* removed DMA allocated with the allocator */
1068 #ifdef STANDALONE_ALLOCATOR
1069 if (allocatorAddr != 0)
1070 allocator_free_dma(allocatorAddr);
1071 #else
1072 allocator_cleanup();
1073 #endif
1074
1075 unregister_chrdev(dt3155_major, "dt3155");
1076
1077 for(index = 0; index < ndevices; index++)
1078 {
1079 if(dt3155_status[index].device_installed == 1)
1080 {
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]);
1084 }
1085 }
1086 }
1087
This page took 0.071412 seconds and 5 git commands to generate.