Merge branch 'for-2.6.34-incoming' into for-2.6.35-incoming
[pandora-kernel.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
67 #include <asm/io.h>
68 #include <asm/uaccess.h>
69
70 #include "dt3155.h"
71 #include "dt3155_drv.h"
72 #include "dt3155_isr.h"
73 #include "dt3155_io.h"
74 #include "allocator.h"
75
76
77 MODULE_LICENSE("GPL");
78
79 /* Error variable.  Zero means no error. */
80 int dt3155_errno = 0;
81
82 #ifndef PCI_DEVICE_ID_INTEL_7116
83 #define PCI_DEVICE_ID_INTEL_7116 0x1223
84 #endif
85
86 #define DT3155_VENDORID    PCI_VENDOR_ID_INTEL
87 #define DT3155_DEVICEID    PCI_DEVICE_ID_INTEL_7116
88 #define MAXPCI    16
89
90 #ifdef DT_DEBUG
91 #define DT_3155_DEBUG_MSG(x,y) printk(x,y)
92 #else
93 #define DT_3155_DEBUG_MSG(x,y)
94 #endif
95
96 /* wait queue for interrupts */
97 wait_queue_head_t dt3155_read_wait_queue[ MAXBOARDS ];
98
99 #define DT_3155_SUCCESS 0
100 #define DT_3155_FAILURE -EIO
101
102 /* set to dynamicaly allocate, but it is tunable: */
103 /* insmod DT_3155 dt3155 dt3155_major=XX */
104 int dt3155_major = 0;
105
106 /* The minor numbers are 0 and 1 ... they are not tunable.
107  * They are used as the indices for the structure vectors,
108  * and register address vectors
109  */
110
111 /* Global structures and variables */
112
113 /* Status of each device */
114 struct dt3155_status_s dt3155_status[ MAXBOARDS ];
115
116 /* kernel logical address of the board */
117 u8 *dt3155_lbase[ MAXBOARDS ] = { NULL
118 #if MAXBOARDS == 2
119                                       , NULL
120 #endif
121 };
122 /* DT3155 registers              */
123 u8 *dt3155_bbase = NULL;                  /* kernel logical address of the *
124                                            * buffer region                 */
125 u32  dt3155_dev_open[ MAXBOARDS ] = {0
126 #if MAXBOARDS == 2
127                                        , 0
128 #endif
129 };
130
131 u32  ndevices = 0;
132 u32 unique_tag = 0;;
133
134
135 /*
136  * Stops interrupt generation right away and resets the status
137  * to idle.  I don't know why this works and the other way doesn't.
138  * (James Rose)
139  */
140 static void quick_stop (int minor)
141 {
142   // TODO: scott was here
143 #if 1
144   ReadMReg((dt3155_lbase[ minor ] + INT_CSR), int_csr_r.reg);
145   /* disable interrupts */
146   int_csr_r.fld.FLD_END_EVE_EN = 0;
147   int_csr_r.fld.FLD_END_ODD_EN = 0;
148   WriteMReg((dt3155_lbase[ minor ] + INT_CSR), int_csr_r.reg );
149
150   dt3155_status[ minor ].state &= ~(DT3155_STATE_STOP|0xff);
151   /* mark the system stopped: */
152   dt3155_status[ minor ].state |= DT3155_STATE_IDLE;
153   dt3155_fbuffer[ minor ]->stop_acquire = 0;
154   dt3155_fbuffer[ minor ]->even_stopped = 0;
155 #else
156   dt3155_status[minor].state |= DT3155_STATE_STOP;
157   dt3155_status[minor].fbuffer.stop_acquire = 1;
158 #endif
159
160 }
161
162
163 /*****************************************************
164  *  dt3155_isr() Interrupt service routien
165  *
166  * - looks like this isr supports IRQ sharing (or could) JML
167  * - Assumes irq's are disabled, via SA_INTERRUPT flag
168  * being set in request_irq() call from init_module()
169  *****************************************************/
170 static inline void dt3155_isr( int irq, void *dev_id, struct pt_regs *regs )
171 {
172   int    minor = -1;
173   int    index;
174   unsigned long flags;
175   u32 buffer_addr;
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   /* Check for corruption and set a flag if so */
193   ReadMReg( (dt3155_lbase[ minor ] + CSR1), csr1_r.reg );
194
195   if ( (csr1_r.fld.FLD_CRPT_EVE) || (csr1_r.fld.FLD_CRPT_ODD) )
196     {
197       /* TODO: this should probably stop acquisition */
198       /* and set some flags so that dt3155_read      */
199       /* returns an error next time it is called     */
200       dt3155_errno = DT_ERR_CORRUPT;
201       printk("dt3155:  corrupt field\n");
202       return;
203     }
204
205   ReadMReg((dt3155_lbase[ minor ] + INT_CSR), int_csr_r.reg);
206
207   /* Handle the even field ... */
208   if (int_csr_r.fld.FLD_END_EVE)
209     {
210       if ( (dt3155_status[ minor ].state & DT3155_STATE_MODE) ==
211            DT3155_STATE_FLD )
212         {
213           dt3155_fbuffer[ minor ]->frame_count++;
214         }
215
216       ReadI2C(dt3155_lbase[ minor ], EVEN_CSR, &i2c_even_csr.reg);
217
218       /* Clear the interrupt? */
219       int_csr_r.fld.FLD_END_EVE = 1;
220
221       /* disable the interrupt if last field */
222       if (dt3155_fbuffer[ minor ]->stop_acquire)
223         {
224           printk("dt3155:  even stopped.\n");
225           dt3155_fbuffer[ minor ]->even_stopped = 1;
226           if (i2c_even_csr.fld.SNGL_EVE)
227             {
228               int_csr_r.fld.FLD_END_EVE_EN = 0;
229             }
230           else
231             {
232               i2c_even_csr.fld.SNGL_EVE  = 1;
233             }
234         }
235
236       WriteMReg( (dt3155_lbase[ minor ] + INT_CSR), int_csr_r.reg );
237
238       /* Set up next DMA if we are doing FIELDS */
239       if ( (dt3155_status[ minor ].state & DT3155_STATE_MODE ) ==
240            DT3155_STATE_FLD)
241         {
242           /* GCS (Aug 2, 2002) -- In field mode, dma the odd field
243              into the lower half of the buffer */
244           const u32 stride =  dt3155_status[ minor ].config.cols;
245           buffer_addr = dt3155_fbuffer[ minor ]->
246             frame_info[ dt3155_fbuffer[ minor ]->active_buf ].addr
247             + (DT3155_MAX_ROWS / 2) * stride;
248           local_save_flags(flags);
249           local_irq_disable();
250           wake_up_interruptible( &dt3155_read_wait_queue[ minor ] );
251
252           /* Set up the DMA address for the next field */
253           local_irq_restore(flags);
254           WriteMReg((dt3155_lbase[ minor ] + ODD_DMA_START), buffer_addr);
255         }
256
257       /* Check for errors. */
258       i2c_even_csr.fld.DONE_EVE = 1;
259       if ( i2c_even_csr.fld.ERROR_EVE )
260         dt3155_errno = DT_ERR_OVERRUN;
261
262       WriteI2C( dt3155_lbase[ minor ], EVEN_CSR, i2c_even_csr.reg );
263
264       /* Note that we actually saw an even field meaning  */
265       /* that subsequent odd field complete the frame     */
266       dt3155_fbuffer[ minor ]->even_happened = 1;
267
268       /* recording the time that the even field finished, this should be */
269       /* about time in the middle of the frame */
270       do_gettimeofday( &(dt3155_fbuffer[ minor ]->
271                          frame_info[ dt3155_fbuffer[ minor ]->
272                                      active_buf ].time) );
273       return;
274     }
275
276   /* ... now handle the odd field */
277   if ( int_csr_r.fld.FLD_END_ODD )
278     {
279       ReadI2C( dt3155_lbase[ minor ], ODD_CSR, &i2c_odd_csr.reg );
280
281       /* Clear the interrupt? */
282       int_csr_r.fld.FLD_END_ODD = 1;
283
284       if (dt3155_fbuffer[ minor ]->even_happened ||
285           (dt3155_status[ minor ].state & DT3155_STATE_MODE) ==
286           DT3155_STATE_FLD)
287         {
288           dt3155_fbuffer[ minor ]->frame_count++;
289         }
290
291       if ( dt3155_fbuffer[ minor ]->stop_acquire &&
292            dt3155_fbuffer[ minor ]->even_stopped )
293         {
294           printk(KERN_DEBUG "dt3155:  stopping odd..\n");
295           if ( i2c_odd_csr.fld.SNGL_ODD )
296             {
297               /* disable interrupts */
298               int_csr_r.fld.FLD_END_ODD_EN = 0;
299               dt3155_status[ minor ].state &= ~(DT3155_STATE_STOP|0xff);
300
301               /* mark the system stopped: */
302               dt3155_status[ minor ].state |= DT3155_STATE_IDLE;
303               dt3155_fbuffer[ minor ]->stop_acquire = 0;
304               dt3155_fbuffer[ minor ]->even_stopped = 0;
305
306               printk(KERN_DEBUG "dt3155:  state is now %x\n",
307                      dt3155_status[minor].state);
308             }
309           else
310             {
311               i2c_odd_csr.fld.SNGL_ODD  = 1;
312             }
313         }
314
315       WriteMReg( (dt3155_lbase[ minor ] + INT_CSR), int_csr_r.reg );
316
317       /* if the odd field has been acquired, then     */
318       /* change the next dma location for both fields */
319       /* and wake up the process if sleeping          */
320       if ( dt3155_fbuffer[ minor ]->even_happened ||
321            (dt3155_status[ minor ].state & DT3155_STATE_MODE) ==
322            DT3155_STATE_FLD )
323         {
324
325           local_save_flags(flags);
326           local_irq_disable();
327
328 #ifdef DEBUG_QUES_B
329           printques( minor );
330 #endif
331           if ( dt3155_fbuffer[ minor ]->nbuffers > 2 )
332             {
333               if ( !are_empty_buffers( minor ) )
334                 {
335                   /* The number of active + locked buffers is
336                    * at most 2, and since there are none empty, there
337                    * must be at least nbuffers-2 ready buffers.
338                    * This is where we 'drop frames', oldest first. */
339                   push_empty( pop_ready( minor ),  minor );
340                 }
341
342               /* The ready_que can't be full, since we know
343                * there is one active buffer right now, so it's safe
344                * to push the active buf on the ready_que. */
345               push_ready( minor, dt3155_fbuffer[ minor ]->active_buf );
346               /* There's at least 1 empty -- make it active */
347               dt3155_fbuffer[ minor ]->active_buf = pop_empty( minor );
348               dt3155_fbuffer[ minor ]->
349                 frame_info[ dt3155_fbuffer[ minor ]->
350                             active_buf ].tag = ++unique_tag;
351             }
352           else /* nbuffers == 2, special case */
353             { /* There is 1 active buffer.
354                * If there is a locked buffer, keep the active buffer
355                * the same -- that means we drop a frame.
356                */
357               if ( dt3155_fbuffer[ minor ]->locked_buf < 0 )
358                 {
359                   push_ready( minor,
360                               dt3155_fbuffer[ minor ]->active_buf );
361                   if (are_empty_buffers( minor ) )
362                     {
363                       dt3155_fbuffer[ minor ]->active_buf =
364                         pop_empty( minor );
365                     }
366                   else
367                     { /* no empty or locked buffers, so use a readybuf */
368                       dt3155_fbuffer[ minor ]->active_buf =
369                         pop_ready( minor );
370                     }
371                 }
372             }
373
374 #ifdef DEBUG_QUES_B
375           printques( minor );
376 #endif
377
378           dt3155_fbuffer[ minor ]->even_happened = 0;
379
380           wake_up_interruptible( &dt3155_read_wait_queue[ minor ] );
381
382           local_irq_restore(flags);
383         }
384
385
386       /* Set up the DMA address for the next frame/field */
387       buffer_addr = dt3155_fbuffer[ minor ]->
388         frame_info[ dt3155_fbuffer[ minor ]->active_buf ].addr;
389       if ( (dt3155_status[ minor ].state & DT3155_STATE_MODE) ==
390            DT3155_STATE_FLD )
391         {
392           WriteMReg((dt3155_lbase[ minor ] + EVEN_DMA_START), buffer_addr);
393         }
394       else
395         {
396           WriteMReg((dt3155_lbase[ minor ] + EVEN_DMA_START), buffer_addr);
397
398           WriteMReg((dt3155_lbase[ minor ] + ODD_DMA_START), buffer_addr
399                     + dt3155_status[ minor ].config.cols);
400         }
401
402       /* Do error checking */
403       i2c_odd_csr.fld.DONE_ODD = 1;
404       if ( i2c_odd_csr.fld.ERROR_ODD )
405         dt3155_errno = DT_ERR_OVERRUN;
406
407       WriteI2C(dt3155_lbase[ minor ], ODD_CSR, i2c_odd_csr.reg );
408
409       return;
410     }
411   /* If we get here, the Odd Field wasn't it either... */
412   printk( "neither even nor odd.  shared perhaps?\n");
413 }
414
415 /*****************************************************
416  * init_isr(int minor)
417  *   turns on interupt generation for the card
418  *   designated by "minor".
419  *   It is called *only* from inside ioctl().
420  *****************************************************/
421 static void dt3155_init_isr(int minor)
422 {
423   const u32 stride =  dt3155_status[ minor ].config.cols;
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         WriteMReg((dt3155_lbase[ minor ] + EVEN_DMA_START),
435                   even_dma_start_r);
436         WriteMReg((dt3155_lbase[ minor ] + EVEN_DMA_STRIDE),
437                   even_dma_stride_r);
438         WriteMReg((dt3155_lbase[ minor ] + ODD_DMA_STRIDE),
439                   odd_dma_stride_r);
440         break;
441       }
442
443     case DT3155_STATE_FRAME:
444     default:
445       {
446         even_dma_start_r  = dt3155_status[ minor ].
447           fbuffer.frame_info[ dt3155_status[ minor ].fbuffer.active_buf ].addr;
448         odd_dma_start_r   =  even_dma_start_r + stride;
449         even_dma_stride_r =  stride;
450         odd_dma_stride_r  =  stride;
451
452         WriteMReg((dt3155_lbase[ minor ] + EVEN_DMA_START),
453                   even_dma_start_r);
454         WriteMReg((dt3155_lbase[ minor ] + ODD_DMA_START),
455                   odd_dma_start_r);
456         WriteMReg((dt3155_lbase[ minor ] + EVEN_DMA_STRIDE),
457                   even_dma_stride_r);
458         WriteMReg((dt3155_lbase[ minor ] + ODD_DMA_STRIDE),
459                   odd_dma_stride_r);
460         break;
461       }
462     }
463
464   /* 50/60 Hz should be set before this point but let's make sure it is */
465   /* right anyway */
466
467   ReadI2C(dt3155_lbase[ minor ], CSR2, &i2c_csr2.reg);
468   i2c_csr2.fld.HZ50 = FORMAT50HZ;
469   WriteI2C(dt3155_lbase[ minor ], CSR2, i2c_csr2.reg);
470
471   /* enable busmaster chip, clear flags */
472
473   /*
474    * TODO:
475    * shouldn't we be concered with continuous values of
476    * DT3155_SNAP & DT3155_ACQ here? (SS)
477    */
478
479   csr1_r.reg                = 0;
480   csr1_r.fld.CAP_CONT_EVE   = 1; /* use continuous capture bits to */
481   csr1_r.fld.CAP_CONT_ODD   = 1; /* enable */
482   csr1_r.fld.FLD_DN_EVE     = 1; /* writing a 1 clears flags */
483   csr1_r.fld.FLD_DN_ODD     = 1;
484   csr1_r.fld.SRST           = 1; /* reset        - must be 1 */
485   csr1_r.fld.FIFO_EN        = 1; /* fifo control - must be 1 */
486   csr1_r.fld.FLD_CRPT_EVE   = 1; /* writing a 1 clears flags */
487   csr1_r.fld.FLD_CRPT_ODD   = 1;
488
489   WriteMReg((dt3155_lbase[ minor ] + CSR1),csr1_r.reg);
490
491   /* Enable interrupts at the end of each field */
492
493   int_csr_r.reg = 0;
494   int_csr_r.fld.FLD_END_EVE_EN = 1;
495   int_csr_r.fld.FLD_END_ODD_EN = 1;
496   int_csr_r.fld.FLD_START_EN = 0;
497
498   WriteMReg((dt3155_lbase[ minor ] + INT_CSR), int_csr_r.reg);
499
500   /* start internal BUSY bits */
501
502   ReadI2C(dt3155_lbase[ minor ], CSR2, &i2c_csr2.reg);
503   i2c_csr2.fld.BUSY_ODD  = 1;
504   i2c_csr2.fld.BUSY_EVE  = 1;
505   WriteI2C(dt3155_lbase[ minor ], CSR2, i2c_csr2.reg);
506
507   /* Now its up to the interrupt routine!! */
508
509   return;
510 }
511
512
513 /*****************************************************
514  * ioctl()
515  *
516  *****************************************************/
517 static int dt3155_ioctl(struct inode *inode,
518                         struct file *file,
519                         unsigned int cmd,
520                         unsigned long arg)
521 {
522   int minor = MINOR(inode->i_rdev); /* What device are we ioctl()'ing? */
523
524   if ( minor >= MAXBOARDS || minor < 0 )
525     return -ENODEV;
526
527   /* make sure it is valid command */
528   if (_IOC_NR(cmd) > DT3155_IOC_MAXNR)
529     {
530       printk("DT3155: invalid IOCTL(0x%x)\n",cmd);
531       printk("DT3155: Valid commands (0x%x), (0x%x), (0x%x), (0x%x), (0x%x)\n",
532              (unsigned int)DT3155_GET_CONFIG,
533              (unsigned int)DT3155_SET_CONFIG,
534              (unsigned int)DT3155_START,
535              (unsigned int)DT3155_STOP,
536              (unsigned int)DT3155_FLUSH);
537       return -EINVAL;
538     }
539
540   switch (cmd)
541     {
542     case DT3155_SET_CONFIG:
543       {
544         if (dt3155_status[minor].state != DT3155_STATE_IDLE)
545           return -EBUSY;
546
547         {
548           struct dt3155_config_s tmp;
549           if (copy_from_user((void *)&tmp, (void *) arg, sizeof(tmp)))
550               return -EFAULT;
551           /* check for valid settings */
552           if (tmp.rows > DT3155_MAX_ROWS ||
553               tmp.cols > DT3155_MAX_COLS ||
554               (tmp.acq_mode != DT3155_MODE_FRAME &&
555                tmp.acq_mode != DT3155_MODE_FIELD) ||
556               (tmp.continuous != DT3155_SNAP &&
557                tmp.continuous != DT3155_ACQ))
558             {
559               return -EINVAL;
560             }
561           dt3155_status[minor].config = tmp;
562         }
563         return 0;
564       }
565     case DT3155_GET_CONFIG:
566       {
567         if (copy_to_user((void *) arg, (void *) &dt3155_status[minor],
568                      sizeof(dt3155_status_t) ))
569             return -EFAULT;
570         return 0;
571       }
572     case DT3155_FLUSH: /* Flushes the buffers -- ensures fresh data */
573       {
574         if (dt3155_status[minor].state != DT3155_STATE_IDLE)
575           return -EBUSY;
576         return dt3155_flush(minor);
577       }
578     case DT3155_STOP:
579       {
580         if (dt3155_status[minor].state & DT3155_STATE_STOP ||
581             dt3155_status[minor].fbuffer.stop_acquire)
582           return -EBUSY;
583
584         if (dt3155_status[minor].state == DT3155_STATE_IDLE)
585           return 0;
586
587         quick_stop(minor);
588         if (copy_to_user((void *) arg, (void *) &dt3155_status[minor],
589                      sizeof(dt3155_status_t)))
590             return -EFAULT;
591         return 0;
592       }
593     case DT3155_START:
594       {
595         if (dt3155_status[minor].state != DT3155_STATE_IDLE)
596           return -EBUSY;
597
598         dt3155_status[minor].fbuffer.stop_acquire = 0;
599         dt3155_status[minor].fbuffer.frame_count = 0;
600
601         /* Set the MODE in the status -- we default to FRAME */
602         if (dt3155_status[minor].config.acq_mode == DT3155_MODE_FIELD)
603           {
604             dt3155_status[minor].state = DT3155_STATE_FLD;
605           }
606         else
607           {
608             dt3155_status[minor].state = DT3155_STATE_FRAME;
609           }
610
611         dt3155_init_isr(minor);
612         if (copy_to_user( (void *) arg, (void *) &dt3155_status[minor],
613                       sizeof(dt3155_status_t)))
614             return -EFAULT;
615         return 0;
616       }
617     default:
618       {
619         printk("DT3155: invalid IOCTL(0x%x)\n",cmd);
620       printk("DT3155: Valid commands (0x%x), (0x%x), (0x%x), (0x%x), (0x%x)\n",
621              (unsigned int)DT3155_GET_CONFIG,
622              (unsigned int)DT3155_SET_CONFIG,
623              DT3155_START, DT3155_STOP, DT3155_FLUSH);
624         return -ENOSYS;
625       }
626     }
627   return -ENOSYS;
628 }
629
630 /*****************************************************
631  * mmap()
632  *
633  * only allow the user to mmap the registers and buffer
634  * It is quite possible that this is broken, since the
635  * addition of of the capacity for two cards!!!!!!!!
636  * It *looks* like it should work but since I'm not
637  * sure how to use it, I'm not actually sure. (NJC? ditto by SS)
638  *****************************************************/
639 static int dt3155_mmap (struct file * file, struct vm_area_struct * vma)
640 {
641   /* which device are we mmapping? */
642   int                           minor = MINOR(file->f_dentry->d_inode->i_rdev);
643   unsigned long offset;
644   offset = vma->vm_pgoff << PAGE_SHIFT;
645
646   if (offset >= __pa(high_memory) || (file->f_flags & O_SYNC))
647     vma->vm_flags |= VM_IO;
648
649   /* Don't try to swap out physical pages.. */
650   vma->vm_flags |= VM_RESERVED;
651
652   /* they are mapping the registers or the buffer */
653   if ((offset == dt3155_status[minor].reg_addr &&
654        vma->vm_end - vma->vm_start == PCI_PAGE_SIZE) ||
655       (offset == dt3155_status[minor].mem_addr &&
656        vma->vm_end - vma->vm_start == dt3155_status[minor].mem_size))
657     {
658       if (remap_pfn_range(vma,
659                         vma->vm_start,
660                         offset >> PAGE_SHIFT,
661                         vma->vm_end - vma->vm_start,
662                         vma->vm_page_prot)) {
663           printk("DT3155: remap_page_range() failed.\n");
664           return -EAGAIN;
665         }
666     }
667   else
668     {
669       printk("DT3155: dt3155_mmap() bad call.\n");
670       return -ENXIO;
671     }
672
673   return 0;
674 }
675
676
677 /*****************************************************
678  * open()
679  *
680  * Our special open code.
681  * MOD_INC_USE_COUNT make sure that the driver memory is not freed
682  * while the device is in use.
683  *****************************************************/
684 static int dt3155_open( struct inode* inode, struct file* filep)
685 {
686   int minor = MINOR(inode->i_rdev); /* what device are we opening? */
687   if (dt3155_dev_open[ minor ]) {
688     printk ("DT3155:  Already opened by another process.\n");
689     return -EBUSY;
690   }
691
692   if (dt3155_status[ minor ].device_installed==0)
693     {
694       printk("DT3155 Open Error: No such device dt3155 minor number %d\n",
695              minor);
696       return -EIO;
697     }
698
699   if (dt3155_status[ minor ].state != DT3155_STATE_IDLE) {
700     printk ("DT3155:  Not in idle state (state = %x)\n",
701             dt3155_status[ minor ].state);
702     return -EBUSY;
703   }
704
705   printk("DT3155: Device opened.\n");
706
707   dt3155_dev_open[ minor ] = 1 ;
708
709   dt3155_flush( minor );
710
711   /* Disable ALL interrupts */
712   int_csr_r.reg = 0;
713   WriteMReg( (dt3155_lbase[ minor ] + INT_CSR), int_csr_r.reg );
714
715   init_waitqueue_head(&(dt3155_read_wait_queue[minor]));
716
717   return 0;
718 }
719
720
721 /*****************************************************
722  * close()
723  *
724  * Now decrement the use count.
725  *
726  *****************************************************/
727 static int dt3155_close( struct inode *inode, struct file *filep)
728 {
729   int minor;
730
731   minor = MINOR(inode->i_rdev); /* which device are we closing */
732   if (!dt3155_dev_open[ minor ])
733     {
734       printk("DT3155: attempt to CLOSE a not OPEN device\n");
735     }
736   else
737     {
738       dt3155_dev_open[ minor ] = 0;
739
740       if (dt3155_status[ minor ].state != DT3155_STATE_IDLE)
741         {
742           quick_stop(minor);
743         }
744     }
745   return 0;
746 }
747
748 /*****************************************************
749  * read()
750  *
751  *****************************************************/
752 static ssize_t dt3155_read(struct file *filep, char __user *buf,
753                            size_t count, loff_t *ppos)
754 {
755   /* which device are we reading from? */
756   int           minor = MINOR(filep->f_dentry->d_inode->i_rdev);
757   u32           offset;
758   int           frame_index;
759   frame_info_t  *frame_info_p;
760
761   /* TODO: this should check the error flag and */
762   /*   return an error on hardware failures */
763   if (count != sizeof(dt3155_read_t))
764     {
765       printk("DT3155 ERROR (NJC): count is not right\n");
766       return -EINVAL;
767     }
768
769
770   /* Hack here -- I'm going to allow reading even when idle.
771    * this is so that the frames can be read after STOP has
772    * been called.  Leaving it here, commented out, as a reminder
773    * for a short while to make sure there are no problems.
774    * Note that if the driver is not opened in non_blocking mode,
775    * and the device is idle, then it could sit here forever! */
776
777   /*  if (dt3155_status[minor].state == DT3155_STATE_IDLE)*/
778   /*    return -EBUSY;*/
779
780   /* non-blocking reads should return if no data */
781   if (filep->f_flags & O_NDELAY)
782     {
783       if ((frame_index = dt3155_get_ready_buffer(minor)) < 0) {
784         /*printk( "dt3155:  no buffers available (?)\n");*/
785         /*              printques(minor); */
786         return -EAGAIN;
787       }
788     }
789   else
790     {
791       /*
792        * sleep till data arrives , or we get interrupted.
793        * Note that wait_event_interruptible() does not actually
794        * sleep/wait if it's condition evaluates to true upon entry.
795        */
796       wait_event_interruptible(dt3155_read_wait_queue[minor],
797                                (frame_index = dt3155_get_ready_buffer(minor))
798                                >= 0);
799
800       if (frame_index < 0)
801         {
802           printk ("DT3155: read: interrupted\n");
803           quick_stop (minor);
804           printques(minor);
805           return -EINTR;
806         }
807     }
808
809   frame_info_p = &dt3155_status[minor].fbuffer.frame_info[frame_index];
810
811   /* make this an offset */
812   offset = frame_info_p->addr - dt3155_status[minor].mem_addr;
813
814   put_user(offset, (unsigned int *) buf);
815   buf += sizeof(u32);
816   put_user( dt3155_status[minor].fbuffer.frame_count, (unsigned int *) buf);
817   buf += sizeof(u32);
818   put_user(dt3155_status[minor].state, (unsigned int *) buf);
819   buf += sizeof(u32);
820   if (copy_to_user(buf, frame_info_p, sizeof(frame_info_t)))
821       return -EFAULT;
822
823   return sizeof(dt3155_read_t);
824 }
825
826 static unsigned int dt3155_poll (struct file * filp, poll_table *wait)
827 {
828   int minor = MINOR(filp->f_dentry->d_inode->i_rdev);
829
830   if (!is_ready_buf_empty(minor))
831     return POLLIN | POLLRDNORM;
832
833   poll_wait (filp, &dt3155_read_wait_queue[minor], wait);
834
835   return 0;
836 }
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   ioctl:                dt3155_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 DT_3155_SUCCESS;
933
934 err:
935   pci_dev_put(pci_dev);
936   return DT_3155_FAILURE;
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()) !=  DT_3155_SUCCESS )
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       WriteMReg( (dt3155_lbase[ index ] + INT_CSR), int_csr_r.reg );
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