f19cc1fe9f5a6aa200531b334d03e322a35301f6
[firefly-linux-kernel-4.4.55.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