Staging: dt3155: Cleanup memory mapped i/o access
[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 // TODO: scott was here
139 #if 1
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);
145
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;
151 #else
152 dt3155_status[minor].state |= DT3155_STATE_STOP;
153 dt3155_status[minor].fbuffer.stop_acquire = 1;
154 #endif
155
156 }
157
158
159 /*****************************************************
160 * dt3155_isr() Interrupt service routien
161 *
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)
167 {
168 int minor = -1;
169 int index;
170 unsigned long flags;
171 u32 buffer_addr;
172 void __iomem *mmio;
173
174 /* find out who issued the interrupt */
175 for (index = 0; index < ndevices; index++) {
176 if(dev_id == (void*) &dt3155_status[index])
177 {
178 minor = index;
179 break;
180 }
181 }
182
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");
186 return;
187 }
188
189 mmio = dt3155_lbase[minor];
190
191 /* Check for corruption and set a flag if so */
192 csr1_r.reg = readl(mmio + CSR1);
193
194 if ((csr1_r.fld.FLD_CRPT_EVE) || (csr1_r.fld.FLD_CRPT_ODD))
195 {
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");
201 return;
202 }
203
204 int_csr_r.reg = readl(mmio + INT_CSR);
205
206 /* Handle the even field ... */
207 if (int_csr_r.fld.FLD_END_EVE)
208 {
209 if ((dt3155_status[minor].state & DT3155_STATE_MODE) ==
210 DT3155_STATE_FLD)
211 {
212 dt3155_fbuffer[minor]->frame_count++;
213 }
214
215 ReadI2C(mmio, EVEN_CSR, &i2c_even_csr.reg);
216
217 /* Clear the interrupt? */
218 int_csr_r.fld.FLD_END_EVE = 1;
219
220 /* disable the interrupt if last field */
221 if (dt3155_fbuffer[minor]->stop_acquire)
222 {
223 printk("dt3155: even stopped.\n");
224 dt3155_fbuffer[minor]->even_stopped = 1;
225 if (i2c_even_csr.fld.SNGL_EVE)
226 {
227 int_csr_r.fld.FLD_END_EVE_EN = 0;
228 }
229 else
230 {
231 i2c_even_csr.fld.SNGL_EVE = 1;
232 }
233 }
234
235 writel(int_csr_r.reg, mmio + INT_CSR);
236
237 /* Set up next DMA if we are doing FIELDS */
238 if ((dt3155_status[minor].state & DT3155_STATE_MODE) ==
239 DT3155_STATE_FLD)
240 {
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);
248 local_irq_disable();
249 wake_up_interruptible(&dt3155_read_wait_queue[minor]);
250
251 /* Set up the DMA address for the next field */
252 local_irq_restore(flags);
253 writel(buffer_addr, mmio + ODD_DMA_START);
254 }
255
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;
260
261 WriteI2C(mmio, EVEN_CSR, i2c_even_csr.reg);
262
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;
266
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]->
271 active_buf].time));
272 return;
273 }
274
275 /* ... now handle the odd field */
276 if (int_csr_r.fld.FLD_END_ODD)
277 {
278 ReadI2C(mmio, ODD_CSR, &i2c_odd_csr.reg);
279
280 /* Clear the interrupt? */
281 int_csr_r.fld.FLD_END_ODD = 1;
282
283 if (dt3155_fbuffer[minor]->even_happened ||
284 (dt3155_status[minor].state & DT3155_STATE_MODE) ==
285 DT3155_STATE_FLD)
286 {
287 dt3155_fbuffer[minor]->frame_count++;
288 }
289
290 if (dt3155_fbuffer[minor]->stop_acquire &&
291 dt3155_fbuffer[minor]->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 dt3155_fbuffer[minor]->stop_acquire = 0;
303 dt3155_fbuffer[minor]->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 (dt3155_fbuffer[minor]->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 (dt3155_fbuffer[minor]->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, 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;
350 }
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.
355 */
356 if (dt3155_fbuffer[minor]->locked_buf < 0)
357 {
358 push_ready(minor,
359 dt3155_fbuffer[minor]->active_buf);
360 if (are_empty_buffers(minor))
361 {
362 dt3155_fbuffer[minor]->active_buf =
363 pop_empty(minor);
364 }
365 else
366 { /* no empty or locked buffers, so use a readybuf */
367 dt3155_fbuffer[minor]->active_buf =
368 pop_ready(minor);
369 }
370 }
371 }
372
373 #ifdef DEBUG_QUES_B
374 printques(minor);
375 #endif
376
377 dt3155_fbuffer[minor]->even_happened = 0;
378
379 wake_up_interruptible(&dt3155_read_wait_queue[minor]);
380
381 local_irq_restore(flags);
382 }
383
384
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) ==
389 DT3155_STATE_FLD)
390 {
391 writel(buffer_addr, mmio + EVEN_DMA_START);
392 }
393 else
394 {
395 writel(buffer_addr, mmio + EVEN_DMA_START);
396
397 writel(buffer_addr + dt3155_status[minor].config.cols,
398 mmio + ODD_DMA_START);
399 }
400
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;
405
406 WriteI2C(mmio, ODD_CSR, i2c_odd_csr.reg);
407
408 return;
409 }
410 /* If we get here, the Odd Field wasn't it either... */
411 printk("neither even nor odd. shared perhaps?\n");
412 }
413
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)
421 {
422 const u32 stride = dt3155_status[minor].config.cols;
423 void __iomem *mmio = dt3155_lbase[minor];
424
425 switch (dt3155_status[minor].state & DT3155_STATE_MODE)
426 {
427 case DT3155_STATE_FLD:
428 {
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;
433
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);
437 break;
438 }
439
440 case DT3155_STATE_FRAME:
441 default:
442 {
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;
448
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);
453 break;
454 }
455 }
456
457 /* 50/60 Hz should be set before this point but let's make sure it is */
458 /* right anyway */
459
460 ReadI2C(mmio, CSR2, &i2c_csr2.reg);
461 i2c_csr2.fld.HZ50 = FORMAT50HZ;
462 WriteI2C(mmio, CSR2, i2c_csr2.reg);
463
464 /* enable busmaster chip, clear flags */
465
466 /*
467 * TODO:
468 * shouldn't we be concered with continuous values of
469 * DT3155_SNAP & DT3155_ACQ here? (SS)
470 */
471
472 csr1_r.reg = 0;
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;
481
482 writel(csr1_r.reg, mmio + CSR1);
483
484 /* Enable interrupts at the end of each field */
485
486 int_csr_r.reg = 0;
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;
490
491 writel(int_csr_r.reg, mmio + INT_CSR);
492
493 /* start internal BUSY bits */
494
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);
499
500 /* Now its up to the interrupt routine!! */
501
502 return;
503 }
504
505
506 /*****************************************************
507 * ioctl()
508 *
509 *****************************************************/
510 static int dt3155_ioctl(struct inode *inode,
511 struct file *file,
512 unsigned int cmd,
513 unsigned long arg)
514 {
515 int minor = MINOR(inode->i_rdev); /* What device are we ioctl()'ing? */
516 void __user *up = (void __user *)arg;
517
518 if (minor >= MAXBOARDS || minor < 0)
519 return -ENODEV;
520
521 /* make sure it is valid command */
522 if (_IOC_NR(cmd) > DT3155_IOC_MAXNR)
523 {
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);
531 return -EINVAL;
532 }
533
534 switch (cmd)
535 {
536 case DT3155_SET_CONFIG:
537 {
538 if (dt3155_status[minor].state != DT3155_STATE_IDLE)
539 return -EBUSY;
540
541 {
542 struct dt3155_config tmp;
543 if (copy_from_user(&tmp, up, sizeof(tmp)))
544 return -EFAULT;
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))
552 {
553 return -EINVAL;
554 }
555 dt3155_status[minor].config = tmp;
556 }
557 return 0;
558 }
559 case DT3155_GET_CONFIG:
560 {
561 if (copy_to_user(up, &dt3155_status[minor],
562 sizeof(struct dt3155_status)))
563 return -EFAULT;
564 return 0;
565 }
566 case DT3155_FLUSH: /* Flushes the buffers -- ensures fresh data */
567 {
568 if (dt3155_status[minor].state != DT3155_STATE_IDLE)
569 return -EBUSY;
570 return dt3155_flush(minor);
571 }
572 case DT3155_STOP:
573 {
574 if (dt3155_status[minor].state & DT3155_STATE_STOP ||
575 dt3155_status[minor].fbuffer.stop_acquire)
576 return -EBUSY;
577
578 if (dt3155_status[minor].state == DT3155_STATE_IDLE)
579 return 0;
580
581 quick_stop(minor);
582 if (copy_to_user(up, &dt3155_status[minor],
583 sizeof(struct dt3155_status)))
584 return -EFAULT;
585 return 0;
586 }
587 case DT3155_START:
588 {
589 if (dt3155_status[minor].state != DT3155_STATE_IDLE)
590 return -EBUSY;
591
592 dt3155_status[minor].fbuffer.stop_acquire = 0;
593 dt3155_status[minor].fbuffer.frame_count = 0;
594
595 /* Set the MODE in the status -- we default to FRAME */
596 if (dt3155_status[minor].config.acq_mode == DT3155_MODE_FIELD)
597 {
598 dt3155_status[minor].state = DT3155_STATE_FLD;
599 }
600 else
601 {
602 dt3155_status[minor].state = DT3155_STATE_FRAME;
603 }
604
605 dt3155_init_isr(minor);
606 if (copy_to_user(up, &dt3155_status[minor],
607 sizeof(struct dt3155_status)))
608 return -EFAULT;
609 return 0;
610 }
611 default:
612 {
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);
618 return -ENOSYS;
619 }
620 }
621 return -ENOSYS;
622 }
623
624 /*****************************************************
625 * mmap()
626 *
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)
634 {
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;
639
640 if (offset >= __pa(high_memory) || (file->f_flags & O_SYNC))
641 vma->vm_flags |= VM_IO;
642
643 /* Don't try to swap out physical pages.. */
644 vma->vm_flags |= VM_RESERVED;
645
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))
651 {
652 if (remap_pfn_range(vma,
653 vma->vm_start,
654 offset >> PAGE_SHIFT,
655 vma->vm_end - vma->vm_start,
656 vma->vm_page_prot)) {
657 printk("DT3155: remap_page_range() failed.\n");
658 return -EAGAIN;
659 }
660 }
661 else
662 {
663 printk("DT3155: dt3155_mmap() bad call.\n");
664 return -ENXIO;
665 }
666
667 return 0;
668 }
669
670
671 /*****************************************************
672 * open()
673 *
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)
679 {
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");
683 return -EBUSY;
684 }
685
686 if (dt3155_status[minor].device_installed==0)
687 {
688 printk("DT3155 Open Error: No such device dt3155 minor number %d\n",
689 minor);
690 return -EIO;
691 }
692
693 if (dt3155_status[minor].state != DT3155_STATE_IDLE) {
694 printk ("DT3155: Not in idle state (state = %x)\n",
695 dt3155_status[minor].state);
696 return -EBUSY;
697 }
698
699 printk("DT3155: Device opened.\n");
700
701 dt3155_dev_open[minor] = 1 ;
702
703 dt3155_flush(minor);
704
705 /* Disable ALL interrupts */
706 int_csr_r.reg = 0;
707 writel(int_csr_r.reg, dt3155_lbase[minor] + INT_CSR);
708
709 init_waitqueue_head(&(dt3155_read_wait_queue[minor]));
710
711 return 0;
712 }
713
714
715 /*****************************************************
716 * close()
717 *
718 * Now decrement the use count.
719 *
720 *****************************************************/
721 static int dt3155_close(struct inode *inode, struct file *filep)
722 {
723 int minor;
724
725 minor = MINOR(inode->i_rdev); /* which device are we closing */
726 if (!dt3155_dev_open[minor])
727 {
728 printk("DT3155: attempt to CLOSE a not OPEN device\n");
729 }
730 else
731 {
732 dt3155_dev_open[minor] = 0;
733
734 if (dt3155_status[minor].state != DT3155_STATE_IDLE)
735 {
736 quick_stop(minor);
737 }
738 }
739 return 0;
740 }
741
742 /*****************************************************
743 * read()
744 *
745 *****************************************************/
746 static ssize_t dt3155_read(struct file *filep, char __user *buf,
747 size_t count, loff_t *ppos)
748 {
749 /* which device are we reading from? */
750 int minor = MINOR(filep->f_dentry->d_inode->i_rdev);
751 u32 offset;
752 int frame_index;
753 struct frame_info *frame_info;
754
755 /* TODO: this should check the error flag and */
756 /* return an error on hardware failures */
757 if (count != sizeof(struct dt3155_read))
758 {
759 printk("DT3155 ERROR (NJC): count is not right\n");
760 return -EINVAL;
761 }
762
763
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! */
770
771 /* if (dt3155_status[minor].state == DT3155_STATE_IDLE)*/
772 /* return -EBUSY;*/
773
774 /* non-blocking reads should return if no data */
775 if (filep->f_flags & O_NDELAY)
776 {
777 if ((frame_index = dt3155_get_ready_buffer(minor)) < 0) {
778 /*printk("dt3155: no buffers available (?)\n");*/
779 /* printques(minor); */
780 return -EAGAIN;
781 }
782 }
783 else
784 {
785 /*
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.
789 */
790 wait_event_interruptible(dt3155_read_wait_queue[minor],
791 (frame_index = dt3155_get_ready_buffer(minor))
792 >= 0);
793
794 if (frame_index < 0)
795 {
796 printk ("DT3155: read: interrupted\n");
797 quick_stop (minor);
798 printques(minor);
799 return -EINTR;
800 }
801 }
802
803 frame_info = &dt3155_status[minor].fbuffer.frame_info[frame_index];
804
805 /* make this an offset */
806 offset = frame_info->addr - dt3155_status[minor].mem_addr;
807
808 put_user(offset, (unsigned int __user *)buf);
809 buf += sizeof(u32);
810 put_user(dt3155_status[minor].fbuffer.frame_count, (unsigned int __user *)buf);
811 buf += sizeof(u32);
812 put_user(dt3155_status[minor].state, (unsigned int __user *)buf);
813 buf += sizeof(u32);
814 if (copy_to_user(buf, frame_info, sizeof(*frame_info)))
815 return -EFAULT;
816
817 return sizeof(struct dt3155_read);
818 }
819
820 static unsigned int dt3155_poll (struct file * filp, poll_table *wait)
821 {
822 int minor = MINOR(filp->f_dentry->d_inode->i_rdev);
823
824 if (!is_ready_buf_empty(minor))
825 return POLLIN | POLLRDNORM;
826
827 poll_wait (filp, &dt3155_read_wait_queue[minor], wait);
828
829 return 0;
830 }
831
832 static long
833 dt3155_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
834 {
835 int ret;
836
837 lock_kernel();
838 ret = dt3155_ioctl(file->f_path.dentry->d_inode, file, cmd, arg);
839 unlock_kernel();
840
841 return ret;
842 }
843
844 /*****************************************************
845 * file operations supported by DT3155 driver
846 * needed by init_module
847 * register_chrdev
848 *****************************************************/
849 static struct file_operations dt3155_fops = {
850 .read = dt3155_read,
851 .unlocked_ioctl = dt3155_unlocked_ioctl,
852 .mmap = dt3155_mmap,
853 .poll = dt3155_poll,
854 .open = dt3155_open,
855 .release = dt3155_close
856 };
857
858
859 /*****************************************************
860 * find_PCI();
861 *
862 * PCI has been totally reworked in 2.1..
863 *****************************************************/
864 static int find_PCI (void)
865 {
866 struct pci_dev *pci_dev = NULL;
867 int error, pci_index = 0;
868 unsigned short rev_device;
869 unsigned long base;
870 unsigned char irq;
871
872 while ((pci_dev = pci_get_device
873 (DT3155_VENDORID, DT3155_DEVICEID, pci_dev)) != NULL)
874 {
875 pci_index ++;
876
877 /* Is it really there? */
878 if ((error =
879 pci_read_config_word(pci_dev, PCI_CLASS_DEVICE, &rev_device)))
880 continue;
881
882 /* Found a board */
883 DT_3155_DEBUG_MSG("DT3155: Device number %d \n", pci_index);
884
885 /* Make sure the driver was compiled with enough buffers to handle
886 this many boards */
887 if (pci_index > MAXBOARDS) {
888 printk("DT3155: ERROR - found %d devices, but driver only configured "
889 "for %d devices\n"
890 "DT3155: Please change MAXBOARDS in dt3155.h\n",
891 pci_index, MAXBOARDS);
892 goto err;
893 }
894
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,
898 (u32 *) &base)))
899 {
900 printk("DT3155: Was not able to find device \n");
901 goto err;
902 }
903
904 DT_3155_DEBUG_MSG("DT3155: Base address 0 for device is %lx \n", base);
905 dt3155_status[pci_index-1].reg_addr = base;
906
907 /* Remap the base address to a logical address through which we
908 * can access it. */
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])
914 {
915 printk("DT3155: Unable to remap control registers\n");
916 goto err;
917 }
918
919 if ((error = pci_read_config_byte(pci_dev, PCI_INTERRUPT_LINE, &irq)))
920 {
921 printk("DT3155: Was not able to find device \n");
922 goto err;
923 }
924
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",
930 pci_index,
931 dt3155_status[pci_index-1].irq,
932 dt3155_lbase[pci_index-1]);
933
934 }
935 ndevices = pci_index;
936
937 return 0;
938
939 err:
940 pci_dev_put(pci_dev);
941 return -EIO;
942 }
943
944 u32 allocatorAddr = 0;
945
946 /*****************************************************
947 * init_module()
948 *****************************************************/
949 int init_module(void)
950 {
951 int index;
952 int rcode = 0;
953 char *devname[MAXBOARDS];
954
955 devname[0] = "dt3155a";
956 #if MAXBOARDS == 2
957 devname[1] = "dt3155b";
958 #endif
959
960 printk("DT3155: Loading module...\n");
961
962 /* Register the device driver */
963 rcode = register_chrdev(dt3155_major, "dt3155", &dt3155_fops);
964 if(rcode < 0)
965 {
966 printk(KERN_INFO "DT3155: register_chrdev failed \n");
967 return rcode;
968 }
969
970 if(dt3155_major == 0)
971 dt3155_major = rcode; /* dynamic */
972
973
974 /* init the status variables. */
975 /* DMA memory is taken care of in setup_buffers() */
976 for (index = 0; index < MAXBOARDS; index++)
977 {
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;
983
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;
990 }
991
992 /* Now let's find the hardware. find_PCI() will set ndevices to the
993 * number of cards found in this machine. */
994 {
995 if ((rcode = find_PCI()) != 0)
996 {
997 printk("DT3155 error: find_PCI() failed to find dt3155 board(s)\n");
998 unregister_chrdev(dt3155_major, "dt3155");
999 return rcode;
1000 }
1001 }
1002
1003 /* Ok, time to setup the frame buffers */
1004 if((rcode = dt3155_setup_buffers(&allocatorAddr)) < 0)
1005 {
1006 printk("DT3155: Error: setting up buffer not large enough.");
1007 unregister_chrdev(dt3155_major, "dt3155");
1008 return rcode;
1009 }
1010
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++)
1014 {
1015 printk("DT3155: Device = %d; acq_mode = %d; "
1016 "continuous = %d; cols = %d; rows = %d;\n",
1017 index ,
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);
1028 }
1029
1030 /* Disable ALL interrupts */
1031 int_csr_r.reg = 0;
1032 for( index = 0; index < ndevices; index++)
1033 {
1034 writel(int_csr_r.reg, dt3155_lbase[index] + INT_CSR);
1035 if(dt3155_status[index].device_installed)
1036 {
1037 /*
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)
1042 */
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]);
1047 if(rcode < 0)
1048 {
1049 printk("DT3155: minor %d request_irq failed for IRQ %d\n",
1050 index, dt3155_status[index].irq);
1051 unregister_chrdev(dt3155_major, "dt3155");
1052 return rcode;
1053 }
1054 }
1055 }
1056
1057 printk("DT3155: finished loading\n");
1058
1059 return 0;
1060 }
1061
1062 /*****************************************************
1063 * cleanup_module(void)
1064 *
1065 *****************************************************/
1066 void cleanup_module(void)
1067 {
1068 int index;
1069
1070 printk("DT3155: cleanup_module called\n");
1071
1072 /* removed DMA allocated with the allocator */
1073 #ifdef STANDALONE_ALLOCATOR
1074 if (allocatorAddr != 0)
1075 allocator_free_dma(allocatorAddr);
1076 #else
1077 allocator_cleanup();
1078 #endif
1079
1080 unregister_chrdev(dt3155_major, "dt3155");
1081
1082 for(index = 0; index < ndevices; index++)
1083 {
1084 if(dt3155_status[index].device_installed == 1)
1085 {
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]);
1089 }
1090 }
1091 }
1092
This page took 0.22074 seconds and 5 git commands to generate.