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