Staging: dt3155: Cleanup memory mapped i/o access
[cascardo/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