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