Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  1 /*
  2  * hrt.c
  3  * 
  4  * last updated - 17 June 2005
  5  * Atulya Mahajan / Sean Toh
  6  * 
  7 
  8 
  9    This is a device driver for the PixelSmart512-8 (greyscale)
 10    and Video Gala (color) framegrabbers.  
 11    For more information on these devices, see http://www.pixelsmart.com.
 12   
 13    This driver is produced as a course project for the 'linux kernel programming'
 14    course at the Florida State University, as a term project submitted by the team
 15    comprising of Atulya Mahajan and Sean Toh, in the summer of 2005.
 16    
 17    This driver carries forward the work done by other teams in the last 2 years
 18    by Brett W. Thompson, Gilberto Morejon, Veena Adityan, Arthi Gokarn and
 19    Alex Rudnick under the guidance of Dr Ted Baker.   
 20 
 21    This driver supports the following features
 22    1. Support for the greyscale as well as color frame grabber cards
 23    2. Support for interrupt driven I/O
 24    3. Support for streaming I/O from color/grey scale devices
 25    4. Automatic detection of the type of device present
 26 
 27 */
 28 
 29 #ifndef __KERNEL__
 30 #define __KERNEL__
 31 #endif
 32 
 33 #include <linux/config.h>
 34 #include <linux/delay.h>           /* udelay */
 35 #include <linux/errno.h>           /* error codes */
 36 #include <linux/file.h>
 37 #include <linux/fs.h>
 38 #include <linux/interrupt.h>
 39 #include <linux/ioport.h>
 40 #include <linux/kernel.h>
 41 #include <linux/mm.h>
 42 #include <linux/module.h>
 43 #include <linux/pci.h>
 44 #include <linux/proc_fs.h>
 45 #include <linux/sched.h>
 46 #include <linux/slab.h>
 47 #include <linux/spinlock.h>
 48 #include <linux/version.h>
 49 
 50 #include <linux/config.h>
 51 #include <linux/moduleparam.h>
 52 
 53 #include <linux/interrupt.h>
 54 
 55 #include <asm/io.h>
 56 #include <asm/segment.h>
 57 #include <asm/uaccess.h>
 58 
 59 #include <linux/videodev.h>
 60 
 61 #include "hrt.h"
 62 
 63 #ifndef HAVE_V4L2
 64 #  error Sorry, this module requires v4l2. You should patch your kernel with v4l2 or you could download the non-v4l2 dependent module hrtmem.c.
 65 #endif
 66 
 67 
 68 #define HRT_DEBUG
 69 
 70 #define HRT_ERROR_MSG(args...) do{printk("<1>hrt:  "); printk(args);\
 71  printk("\n");}while(0)
 72 
 73 /*********************
 74  * Module Parameters *
 75  *********************/
 76 
 77 #ifndef module_param
 78 #define hrt_parm(name, pstr, type, perm) MODULE_PARM(name, pstr)
 79 #else
 80 #define hrt_parm(name, pstr, type, perm) module_param(name, type, perm)
 81 #endif
 82 
 83 static
 84 int  major_number = 82;
 85 hrt_parm(major_number, "i", int, 0);
 86 
 87 #ifndef HRT_MAX_DEVICES
 88 #define HRT_MAX_DEVICES 4
 89 #endif
 90 
 91 #ifndef HRT_IO_SIZE            
 92 #define HRT_IO_SIZE            0x4000
 93 #endif
 94 
 95 /********************************************************************/
 96 /**
 97  * hrt_ctls - controls the user can set via V4L ioctl's
 98  */
 99 static const struct v4l2_queryctrl hrt_ctls[] = {
100          {
101                   .id = V4L2_CID_BRIGHTNESS,
102                   .name = "Brightness",
103                   .minimum = 0,
104                   .maximum = 255,
105                   .step = 1,
106                   .default_value = 0x9b, // (decimal: 155)
107                   .type = V4L2_CTRL_TYPE_INTEGER,
108          }, 
109          {
110                   .id = V4L2_CID_CONTRAST,
111                   .name = "Contrast",
112                   .minimum = 0,
113                   .maximum = 255,
114                   .step = 1,
115                   .default_value = 0x5e, // (decimal: 94)
116                   .type = V4L2_CTRL_TYPE_INTEGER,
117          }
118 };
119 
120 
121 /********************************************************************/
122 /**
123  * hrt_addresses - a list of possible jumper-selected addresses
124  *  jumper A on  = plug and play address (above one MB address)
125  *  jumper A off = hardwired to 0xdc000 or 0xd4000
126  *  jumper B on  = address 0xd4000 (ignored if jumper A is on) 
127  *  jumper B off = address 0xdc000 (ignored if jumper A is on) 
128  */
129 const unsigned long hrt_addresses[] = { 0xd4000, 0xdc000 };
130 
131 /***************************
132  * Card-specific constants *
133  ***************************/
134 
135 #define HRT_VENDOR_ID         0x0004
136 #define HRT_DEVICE_ID_GREY    0x0404
137 #define HRT_DEVICE_ID_COLOR   0x0408
138 
139 /* Number of registers on the board- checked in i2c_init() */
140 #define HRT_SAA7110_MAXREG 0x34
141 
142 
143 /********************************************************************/
144 /**
145  * struct stream_buffer - represents a single buffer for streaming
146  */
147 struct stream_buffer {
148          struct v4l2_buffer vidbuf; /* For the V4L ioctl's */
149          int fields_grabbed; /* Two-bit pair of flags indicating which fields
150                                 have been grabbed (i.e., 00 = no fields,
151                                 11 = both) */
152          struct list_head node; /* Connection into queues */
153          int requested; /* Set by REQBUF ioctl */
154          unsigned char *vaddress; /* This is the pointer to the vmalloc()'d
155                                      memory into which the actual frame goes */
156          int vma_refcount; /* Reference count */
157 };
158 
159 
160 /********************************************************************/
161 /**
162  * struct stream_buffer_queue - FIFO of stream_buffer structs
163  */
164 struct stream_buffer_queue {
165          struct stream_buffer *streambuf; /* Pointer to node data */
166          struct list_head head; /* Start of the queue */
167          rwlock_t lock; /* Lock to protect the queue */
168          int length; /* How many nodes are on the queue */
169 };
170 
171 
172 /********************************************************************/
173 /**
174  * HRT device descriptor
175  */
176 typedef struct {
177          int                     num;
178          int                     state;
179          /* minor device number, index in hrt_devices[] */
180          unsigned long           virt_addr;
181          unsigned long           phys_addr;
182          /* cannot be opened again until released */
183 
184          /* spinlock and is_locked control access to the device */
185          spinlock_t              spinlock;
186          int                     is_locked;
187          wait_queue_head_t       wait_queue;
188          struct timer_list       timer;
189          struct tasklet_struct   tasklet;
190          int                     timer_active;
191          int                     tasklet_active;
192          /* timer_active != 0 iff timer or irq is active */
193          int                     irq;
194          /* irq != 0 if board supports interrupts
195             = -irq if handler not installed
196             = irq if handler is installed */
197          volatile
198          int                     irq_count;
199          volatile
200          int                     i2c_bits;
201          /* last values written to i2c */
202          char                    saa7110_registers[HRT_SAA7110_MAXREG+1];
203          /* video data format, and dependent values */
204          int                     mode;
205          int                     rows, cols, bytes_per_pixel;
206          int                     win_row, win_col, win_width, win_height;
207          /* current field being digitized */
208          int                     field;
209          /* how many field changes we are waiting for */
210          int                     field_changes;
211          /* the device is either frozen or being frozen */
212          int                     is_frozen;
213         
214          /* Local buffer for storing the frame currently read from the device */
215          /* Added june 8,2005 - atulya/sean */
216          unsigned char *framedata;
217          /* Variable to keep track of the field being read inside the current frame */
218          unsigned int field_id;
219          /* Semaphore for the device structure */
220          struct semaphore sem;
221          /* Local buffer used for manipulation of the data returned 
222           * by the color device.
223           * ONLY used by the color device
224           */
225          unsigned char *localbuf;
226          /* Flag for streaming mode */
227          int streaming;
228          /* Number of buffers for streaming */ 
229          int numbufs; 
230          /* Array of buffers */
231          struct stream_buffer *streambufs; 
232          /* List of queued buffers */
233          struct stream_buffer_queue capture_list; 
234          /* List of filled buffers */
235          struct stream_buffer_queue done_list; 
236          int stream_buffers_mapped;
237          struct stream_buffer stream_buf[MAX_CAPTURE_BUFFERS];
238          int stream_buffers_requested;
239 
240          /* Variable used to keep track of our state while streaming 
241           * added 13 June 2005 - Atulya/Sean
242           */
243          int streaming_state;
244         
245          /* We allow the user to make the view upside down too !
246           * came out of compulsion actually since we have the cameras installed
247           * upside down !
248           * the following variable determines what sort of output we return to the user
249           * set using an ioctl
250           */
251          int upside_down;       
252 
253          /* Following structure used for registering with V4L */
254          struct video_device video_dev; 
255          struct v4l2_format clientfmt;
256          struct v4l2_captureparm capture;
257          
258          /* Bytes per raster line. 640 for grey scale card
259           * and 2*640 = 1280 for the color card
260           */
261          unsigned int bytesperline; 
262          /* Memory size of the entire frame
263           * = 512 X 480 X 1 bytes per pixel= 240 KB for grey scale card
264           * = 640 X 480 X 2 bytes per pixel= 600 KB for color card
265           */
266          unsigned int framesize;
267          /* Current region of interest 
268           * fields = width,height,starty,startx
269           */
270          struct subwindow *win; 
271 
272 #ifdef CONFIG_PCI
273          /* structure to represent a pci device */
274          struct pci_dev          *pci_dev;
275 #endif
276 } hrt_t;
277 
278 
279 /********************************************************************
280  *************** basic file operations (fops) ********************
281  */
282 int          hrt_open   (struct inode *inode, struct file *file);
283 int          hrt_release(struct inode *inode, struct file *file);
284 int          hrt_read   (struct file *file, char *buf, size_t count, loff_t * ppos);
285 int          hrt_ioctl  (struct inode *inode, struct file *filp,
286                          unsigned int cmd, unsigned long arg);
287 int          hrt_mmap   (struct file *file, struct vm_area_struct *vma);
288 unsigned int hrt_poll   (struct file *file, poll_table *wait);
289 static int   hrt_do_private_ioctl(hrt_t *hrtdev, unsigned int cmd,
290                                   unsigned long arg);
291 
292 
293 /********************************************************************/
294 static struct file_operations hrt_fops = {
295          .owner                = THIS_MODULE,
296          .open                 = hrt_open,
297          .release              = hrt_release,
298          .read                 = hrt_read,
299          .ioctl                = hrt_ioctl,
300          .mmap                 = hrt_mmap,
301          .llseek               = no_llseek,
302          .poll                 = hrt_poll,
303 
304 };
305 
306 /********************************************************************/
307 /* XXX: Get an actual official number from kraxel@bytesex.org
308    (see /usr/src/linux/include/linux/videodev.h) */
309 #define VID_HARDWARE_HRT 36
310 
311 /********************************************************************/
312 static struct video_device videodev_template = {
313          .owner = THIS_MODULE,
314          .name = "HRT Pixelsmart (PS512-8-PCI)",
315          .type = HRT_VID_TYPE,
316          .hardware = VID_HARDWARE_HRT,
317          .fops = &hrt_fops,
318 };
319 
320 /********************************************************************/
321 /**
322  * struct hrt_per_file - contains data to be stored per file handle
323  * 
324  * Private data for a device is not just the hrt_t structure
325  * but also the subwindow structure that represents the subwindow 
326  * of the entire frame being displayed
327  */
328 struct hrt_per_file {
329          struct subwindow win;
330          hrt_t *hrtdev;
331 };
332 /********************************************************************/
333 
334 /* Minor number, or -1 for first free */
335 static int video_minor = -1;
336 
337 /* Don't put V4L2_CAP_STREAMING in capabilities; recommended for xawtv */
338 static unsigned int disable_streaming = 0;
339 
340 MODULE_PARM(video_minor, "i");
341 MODULE_PARM_DESC(video_minor, "Device's minor number (default: dynamic)");
342 MODULE_PARM(disable_streaming, "i");
343 MODULE_PARM_DESC(disable_streaming, "Don't return V4L2_CAP_STREAMING; recommended for xawtv (default: off)");
344 
345 MODULE_AUTHOR("Brett W. Thompson, Gilberto Morejon, Veena Adityan, Arthi Gokarn, Alex Rudnick, Sean Toh, Atulya Mahajan");
346 MODULE_DESCRIPTION("Driver for HRT Pixelsmart 512-8-PCI");
347 MODULE_LICENSE("GPL");
348 
349 
350 /********************************************************************/
351 /**
352  * dprintk, hrt_printk - thin wrappers around printk()
353  */
354 #define dprintk(fmt, arg...) {  printk("hrt: " fmt, ## arg); }
355 #define hrt_printk(fmt, arg...)  { printk(KERN_ALERT "hrt: " fmt, ## arg); }
356 /********************************************************************/
357 
358 /* values for field hrt_t->state */
359 #define HRT_UNINITIALIZED_STATE 1
360 #define HRT_INITIALIZING_STATE 2
361 #define HRT_CLOSED_STATE 4
362 #define HRT_OPEN_STATE 8
363 #define HRT_FINALIZING_STATE 16
364 
365 /* values for field hrt_t->mode */
366 #define HRT_DUAL_PORTED_MODE 1
367 #define HRT_COLOR_MODE 2
368 #define HRT_STREAMING_MODE 4
369 #define HRT_IRQ_MODE 8
370 #define HRT_ISA_MODE 16
371 
372 /* values for global hrt_module_state */
373 
374 #define HRT_MODULE_UNINITIALIZED_STATE 1
375 #define HRT_MODULE_INITIALIZING_STATE 2
376 #define HRT_MODULE_INITIALIZED_STATE 4
377 #define HRT_MODULE_FINALIZING_STATE 8
378 /********************************************************************/
379 
380 
381 int hrt_module_state = HRT_MODULE_UNINITIALIZED_STATE;
382 
383 int  hrt_nonpci_devices = 0;  /* number of non-pci devices detected */
384                               /* non-pci devices have lower numbers */
385 int  hrt_num_devices = 0;     /* total number of devices detected */
386 
387 #define HRT_IS_PCI(X) ((X) >= hrt_nonpci_devices)
388 
389 /* ??? consider dynamically allocating the device
390    objects as they are probed and detected, and
391    using a linked list here instead of an array */
392 
393 hrt_t hrt_devices[HRT_MAX_DEVICES];
394 
395 /* Flag to change semantics of mmap() upon the IOC_HRT_NEXT_MMAP_IS_DIRECT
396    ioctl */
397 static unsigned int next_mmap_is_direct = 0;
398 struct hrt_per_file *per_file_init( hrt_t *hrtdev);
399 
400 
401 /* Veena and Arthi's streaming functions */
402 int mmap_request_buffers(hrt_t *dev,
403                          struct v4l2_requestbuffers *req);
404 int  hrt_streamon(hrt_t *hrtdev, __u32 type);
405 void hrt_streamoff(hrt_t *hrtdev, __u32 type);
406 int  hrt_dequeuebuffer(hrt_t *hrtdev,
407                       struct v4l2_buffer *buf);
408 int  hrt_queuebuffer(hrt_t *hrtdev,
409                     struct v4l2_buffer *buf);
410 
411 
412 
413 #ifdef HRT_DEBUG
414 /******************************
415  * optional debugging support *
416  ******************************/
417 
418 #define HRT_DEBUG_LEVEL 3
419 
420 #define HRT_CHECK(dev,states,msg) \
421   {if (dev->state & ~(states))\
422   {HRT_DEBUG_MSG(1, "* unexpected state 0x%2x (%s)", dev->state, msg);}}
423 
424 #define HRT_MODULE_CHECK(states,msg) \
425   {if (hrt_module_state & ~(states))\
426   {HRT_DEBUG_MSG(1, "* unexpected state 0x%2x (%s)", hrt_module_state, msg);}}
427 
428 #define HRT_DEBUG_MSG(level,args...) {if (level <= HRT_DEBUG_LEVEL)\
429  {printk("<1>hrt * "); printk(args); printk("\n");}}
430 
431 struct proc_dir_entry *hrt_proc_read_entry = NULL;
432 
433 #define write_buf(args...)         \
434            do { \
435            n = snprintf(buf, count, args); \
436            buf += n; \
437            count -= n; \
438            } while(0)
439 
440 /********************************************************************/
441 int hrt_read_proc(char *buf, char **start, off_t offset,
442                   int count, int *eof, void *data)
443 {
444          int n, i;
445          int ips, tps, rps;
446          char *org_buf = buf;
447 
448          ips = 0;
449          tps = 0;
450          rps = 0;
451 
452          /* dont excede count bytes when writing to buf */
453          /* just write to buf as a normal ptr to a file */
454 
455          write_buf("dev  HZ/10    int   timer   read   int/s   timer/s   read/s\n");
456          for (i=0; i<HRT_MAX_DEVICES; i++) {
457                   write_buf("%6i %6i %7i %9i %8i\n", i,
458                             hrt_devices[i].irq_count,
459                             ips, tps, rps);
460          }
461          *eof = 1;
462          return buf - org_buf;
463 }
464 /********************************************************************/
465 
466 #define hrt_debug_init()\
467 { hrt_proc_read_entry = create_proc_read_entry("hrt0", 0, 0, hrt_read_proc, 0);}
468 
469 #define hrt_debug_cleanup()\
470 {if (hrt_proc_read_entry) remove_proc_entry("hrt", 0);}
471 
472 #else
473 /* hrt debugging is off */
474 
475 #define HRT_CHECK(dev,states,msg) do{}while(0)
476 #define HRT_MODULE_CHECK(states,msg) do{}while(0)
477 #define HRT_DEBUG_MSG(args...) do{}while(0)
478 #define hrt_debug_init() do{}while(0)
479 #define hrt_debug_cleanup() do{}while(0)
480 #endif
481 
482 /****************************
483  * low-level device control *
484  ****************************/
485 
486 /* I2C bits */
487 #define HRT_I2C_SCL   0x01
488 #define HRT_I2C_SDA   0x02
489 
490 #define HRT_CONTROL(addr) (addr + HRT_CONTROL_REG)
491 #define I2C_CONTROL(addr) (addr + HRT_I2C_REG)
492 #define I2C_BUSY(addr) (!(ioread8((void *) HRT_CONTROL(addr)) & 0x80))
493 
494 /* Bit 7 at 0x2000 (the HRT512-8 control register) tells whether
495  * the CPU is sending data across the I2C bus */
496 
497 #define hrt_freeze_next(dev) \
498         dev->is_frozen = 1;\
499         iowrite8(HRT_FREEZE_NEXT_CMD, (void *) (dev->virt_addr + HRT_CONTROL_REG))
500 #define hrt_freeze_immediate(dev) \
501         dev->is_frozen = 1;\
502         iowrite8(HRT_FREEZE_IMM_CMD, (void *) (dev->virt_addr + HRT_CONTROL_REG))
503 #define hrt_go_live(dev) \
504         dev->is_frozen = 0;\
505         iowrite8(HRT_LIVE_CMD, (void *) (dev->virt_addr + HRT_CONTROL_REG))
506 #define hrt_get_field(dev) \
507         ioread8((void *) (dev->virt_addr + HRT_CONTROL_REG)) & 0x1
508 #define hrt_is_live(dev) \
509         ioread8((void *) (dev->virt_addr + HRT_CONTROL_REG)) & 0x1
510 #define hrt_i2c_delay() udelay(5)
511 
512 /* Unique I2C bus address of the SAA7110 (A/D) device */
513 #define HRT_AD_DEVICE_ID (128+16+8+4)
514 
515 /********************************************************************/
516 const unsigned char saa7110_default_init_regs[] = {
517          94,                                 /* there are 94 bytes that follow */
518          0x00, 0x4c,                   /* increment delay (IDEL) */
519          0x01, 0x3c,                   /* HSY begin 50 Hz */
520          0x02, 0x0d,                   /* HSY stop 50 Hz */
521          0x03, 0xef,                   /* HCL begin 50 Hz */
522          0x04, 0xbd,                   /* HCL stop 50 Hz */
523          0x05, 0xf0,                   /* HSY after PHI1 50 Hz */
524          0x06, 0x00,                   /* luminance control */
525          0x07, 0x00,                   /* hue control */
526          0x08, 0xf8,                   /* colour killer threshold QUAM (PAL/NTSC) */
527          0x09, 0xf8,                   /* colour killer threshold SECAM */
528          0x0A, 0x60,                   /* PAL switch sensitivity */
529          0x0B, 0x50,                   /* SECAM switch sensitivity */
530          0x0C, 0x00,                   /* gain control chrominance */
531          0x0D, 0x86,                   /* standard/mode control */
532          /* 7 VTRC = 1  (VCR mode, not TV)
533             6 XXX
534             5 XXX
535             4 XXX
536             3 RTSE = 0  (PLIN switched to output)
537             2 HRMV = 1  (HREF normal position)
538             1 SSTB = 1  (status byte = 1)
539             0 SECS = 0  (other standards, not SECAM) */
540          0x0E, 0x18,                   /* I/O and clock control */
541          0x0F, 0x90,                   /* control #1 */
542          0x10, 0x00,                   /* control #2 */
543          0x11, 0x2c,                   /* chrominance gain reference */
544          0x12, 0x7f,                   /* chrominance saturation */
545          0x13, 0x5e,                   /* luminance contrast */
546          0x14, 0x42,                   /* HSY begin 60 Hz */
547          0x15, 0x1a,                   /* HSY stop 60 Hz */
548          0x16, 0xff,                   /* HCL begin 60 Hz */
549          0x17, 0xda,                   /* HCL stop 60 Hz */
550          0x18, 0xf0,                   /* HSY after PHI1 60 Hz */
551          0x19, 0x9b,                   /* luminance brightness */
552          /*
553            0x1A - not used
554            0x1B - not used
555            0x1C - not used
556            0x1D - not used
557            0x1E - not used
558            0x1F - not used
559          */
560          0x20, 0x7c,                   /* analog control #1 */
561          0x21, 0x03,                   /* analog control #2 */
562          0x22, 0xd2,                   /* mixer control #1 */
563          0x23, 0x41,                   /* clamping level control 21 */
564          0x24, 0x80,                   /* clamping level control 22 */
565          0x25, 0x41,                   /* clamping level control 31 */
566          0x26, 0x80,                   /* clamping level control 32 */
567          0x27, 0x4f,                   /* gain control #1 */
568          0x28, 0xfe,                   /* white peak control */
569          0x29, 0x01,                   /* sync bottom control */
570          0x2A, 0xcf,                   /* gain control analog #2 */
571          0x2B, 0x0f,                   /* gain control analog #3 */
572          0x2C, 0x83,                   /* mixer control #2 */
573          0x2D, 0x01,                   /* integration value gain */
574          0x2E, 0x81,                   /* vertical blanking pulse set */
575          0x2F, 0x03,                   /* vertical blanking pulse reset */
576          0x30, 0x60,                   /* ADCs gain control */
577          0x31, 0x71,                   /* mixer control #3 */
578          0x32, 0x02,                   /* integration value white peak */
579          0x33, 0x8c,                   /* mixer control #4 */
580          0x34, 0x03,                   /* gain update level */
581 };
582 
583 /********************************************************************/
584 /* 
585  *  sda = set data bit on I2C bus
586  *           to the value given by parameter high
587  */
588 static inline
589 void hrt_sda(hrt_t *dev, unsigned long addr, int high)
590 {
591          if (high) dev->i2c_bits |= HRT_I2C_SDA;
592          else         dev->i2c_bits &= ~HRT_I2C_SDA;
593          iowrite8(dev->i2c_bits, (void *) I2C_CONTROL(addr));
594          wmb();
595 }
596 
597 /********************************************************************/
598 /* 
599  *  scl = set clock bit on I2C bus
600  *           to the value given by parameter high
601  */
602 static inline
603 void hrt_scl(hrt_t *dev, unsigned long addr, int high)
604 {
605          if (high) dev->i2c_bits |= HRT_I2C_SCL;
606          else         dev->i2c_bits &= ~HRT_I2C_SCL;
607          iowrite8(dev->i2c_bits, (void *) I2C_CONTROL(addr));
608          wmb();
609 }
610 
611 /********************************************************************/
612 /**
613  * Queue manipulation functions (basically wrappers for the Linux
614  * linked list functions)
615  */
616 void queue_add_tail(struct stream_buffer *streambuf,
617                     struct stream_buffer_queue *q)
618 {
619          unsigned long flags;
620 
621          if (streambuf == NULL || q == NULL) return;
622 
623          write_lock_irqsave(&q->lock, flags);
624          list_add_tail(&streambuf->node, &q->head);
625          q->length++;
626          write_unlock_irqrestore(&q->lock, flags);
627 }
628 
629 /********************************************************************/
630 void queue_del(struct stream_buffer *streambuf,
631                struct stream_buffer_queue *q)
632 {
633          unsigned long flags;
634 
635          if (q == NULL) return;
636 
637          write_lock_irqsave(&q->lock, flags);
638          list_del(&streambuf->node);
639          q->length--;
640          write_unlock_irqrestore(&q->lock, flags);
641 }
642 
643 /********************************************************************/
644 struct stream_buffer *queue_peek_head(struct stream_buffer_queue *q)
645 {
646          unsigned long flags;
647          struct stream_buffer *streambuf;
648 
649          if (q == NULL) return NULL;
650 
651          read_lock_irqsave(&q->lock, flags);
652          streambuf = list_entry(q->head.next, struct stream_buffer, node);
653          read_unlock_irqrestore(&q->lock, flags);
654 
655          return streambuf;
656 }
657 
658 /********************************************************************/
659 struct stream_buffer *queue_del_head(struct stream_buffer_queue *q)
660 {
661          unsigned long flags;
662          struct stream_buffer *streambuf;
663 
664          if (q == NULL) return NULL;
665          if (!q->length) return NULL;
666 
667          read_lock_irqsave(&q->lock, flags);
668          streambuf = list_entry(q->head.next, struct stream_buffer, node);
669          list_del(&streambuf->node);
670          q->length--;
671          read_unlock_irqrestore(&q->lock, flags);
672          return streambuf;
673 }
674 
675 /********************************************************************/
676 /**
677  * hrt_streamoff - called by the STREAMOFF ioctl.
678  * Used to turn off the streaming read from the device
679  */
680 void hrt_streamoff(hrt_t *hrtdev, __u32 type)
681 {
682          int i = 0;
683          struct stream_buffer *buf;
684          /* Cant turn streaming off if it isnt on !! */
685          if (!hrtdev->streaming) {
686                   hrt_printk("STREAMOFF - Not in streaming mode\n");
687                   return;
688          }
689          /* We can only have the following type specified
690           * anything else is an error
691           */
692          if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
693                   hrt_printk("STREAMOFF - Wrong buffer type\n");
694                   return;
695          }
696          /* Set the 'streaming' variable to 0
697           *  indicates that we are no more in streaming mode
698           *  used by the timer handler to determine what to do
699           */
700          hrtdev->streaming = 0;
701         
702          /* Added 13 June 2005 - Atulya/Sean */
703          hrtdev->streaming_state = 0;
704 
705         hrtdev->upside_down = 0;        
706         
707          /* Wait till the queue is empty */
708          while ((buf = queue_del_head(&hrtdev->done_list))) {
709                   buf->vidbuf.flags &= ~V4L2_BUF_FLAG_QUEUED;
710                   i++;
711          }
712 
713          hrt_printk("Streaming is turned off\n");
714 }
715 
716 
717 
718 /********************************************************************/
719 /**
720  * hrt_do_private_ioctl - handle private ioctl's on device
721  */
722 static int hrt_do_private_ioctl(hrt_t *hrtdev, unsigned int cmd,
723                                 unsigned long arg)
724 {
725          if (cmd == IOC_HRT_NEXT_MMAP_IS_DIRECT) {
726                   /* The next mmap() that's called on /dev/video<n>
727                      will map the device's memory directly- this is
728                      for userspace drivers */
729                   next_mmap_is_direct = 1;
730                   return 0;
731          } 
732          /*else if (cmd == IOC_HRT_SET_I2CREG) {
733            struct i2c_regval r;
734 
735            if (copy_from_user(&r, (void *) arg, sizeof(r))) {
736            return -EFAULT;
737            }
738            i2c_set_reg(hrtdev, r.reg, r.val);
739            return 0;
740            } else if (cmd == IOC_HRT_GET_I2CREG) {
741            struct i2c_regval r;
742 
743            r.val = hrtdev->regvals[r.reg];
744            if (copy_to_user((void *) arg, &r, sizeof(r))) {
745            return -EFAULT;
746            }
747            return 0;
748            } 
749          */
750          /* Set the region of interest - subwindow */
751          else if (cmd == IOC_HRT_SET_ROI) {
752                   struct subwindow win;
753 
754                   if (copy_from_user(&win, (void *) arg, sizeof(win))) {
755                            hrt_printk("ioctl IOC_HRT_SET_ROI failed\n");
756                            return -EFAULT;
757                   }
758                   /* Check if the specified height and width are valid values */        
759                   if (win.height > HRT_HEIGHT || win.height < 0) return -EINVAL;
760                   if(hrtdev->mode & HRT_COLOR_MODE){
761                            if (win.width > HRT_COLOR_WIDTH || win.width < 0) return -EINVAL;
762                   }
763                   else{
764                            if (win.width > HRT_GRAY_WIDTH || win.width < 0) return -EINVAL;
765                   }
766                   if (win.startx > win.width || win.startx < 0) return -EINVAL;
767                   if (win.starty > win.height || win.starty < 0) return -EINVAL;
768                   hrt_printk ("setting hrtdev->win\n");
769                   *hrtdev->win = win;
770                   return 0;
771                   /* Return the current region of interest parameters to the user */
772          } else if (cmd == IOC_HRT_GET_ROI) {
773                   if (copy_to_user((void *) arg, hrtdev->win,
774                                    sizeof(*hrtdev->win))) {
775                            hrt_printk("ioctl IOC_HRT_GET_ROI failed\n");
776                            return -EFAULT;
777                   }
778                   return 0;
779          } 
780          /*     else if (cmd == IOC_HRT_SET_I2CREGS) { */
781          /*                 unsigned char len; */
782          /*                 int retval; */
783          /*                 unsigned char *buf; */
784 
785          /*                 /\* Stop the timer first *\/ */
786          /*                 del_timer_sync(&timer); */
787          /*                 timer_running = 0; */
788 
789          /*                 /\* First byte is the length of the array *\/ */
790          /*                 if (copy_from_user(&len, (void *) arg, 1)) */
791          /*                         return -EFAULT; */
792          /*                 dprintk("size of array = %d\n", len); */
793 
794          /*                 buf = vmalloc(len + 1); */
795          /*                 if (copy_from_user(buf, (void *) arg, len)) { */
796          /*                         vfree(buf); */
797          /*                         return -EFAULT; */
798          /*                 } */
799          /*                 retval = i2c_init(hrtdev, buf); */
800          /*                 vfree(buf); */
801 
802          /*                 /\* Start the timer again *\/ */
803          /*                 timer.expires = jiffies + (HZ/100); */
804          /*                 add_timer(&timer); */
805          /*                 timer_running = 1; */
806          /*                 return retval; */
807 
808          return -EINVAL;
809 }
810 
811 
812 /********************************************************************/
813 /**
814  * hrt_direct_mmap - provides direct access to the card's memory
815  */
816 static int hrt_direct_mmap(struct file *file, struct vm_area_struct *vma)
817 {
818          struct hrt_per_file *per_file = file->private_data;
819          hrt_t *hrtdev = per_file->hrtdev;
820          vma->vm_flags |= (VM_IO | VM_RESERVED);
821          /* Just map the pages directly */
822          if (remap_pfn_range(vma,
823                              vma->vm_start, hrtdev->phys_addr, vma->vm_end - vma->vm_start,
824                              vma->vm_page_prot))
825                   return -EAGAIN;
826 
827          return 0;
828 }
829 
830 
831 /********************************************************************/
832 /**
833  * mmap_stream_buffer_from_offset - get a buffer via the specified offset
834  */
835 static struct stream_buffer *mmap_stream_buffer_from_offset(hrt_t *dev,
836                                                             unsigned long offset)
837 {
838          int i;
839          offset *= PAGE_SIZE;
840          for (i = 0; i < MAX_CAPTURE_BUFFERS; ++i) {
841                   if (offset == dev->stream_buf[i].vidbuf.m.offset) {
842                            hrt_printk("mmap_stream_buffer_from_offset: offset found at : 0x%lx", offset);
843                            return &dev->stream_buf[i];
844                   }
845          }
846          hrt_printk("mmap_stream_buffer_from_offset: NOTHING found.");   
847          return NULL;
848 }
849 
850 /*
851  * 
852  * Dr Baker's I2C routines follow
853  *
854  */
855 
856 /********************************************************************/
857 /* 
858  *  sda_scl = set data and clock bits on I2C bus
859  *           to the values given by parameters  sda_high and scl_high
860  */
861 static inline
862 void hrt_sda_scl(hrt_t *dev, 
863                  unsigned long addr, int sda_high, int scl_high)
864 {
865          if (sda_high) dev->i2c_bits |= HRT_I2C_SDA;
866          else                dev->i2c_bits &= ~HRT_I2C_SDA;
867          if (scl_high) dev->i2c_bits |= HRT_I2C_SCL;
868          else                dev->i2c_bits &= ~HRT_I2C_SCL;
869          iowrite8(dev->i2c_bits, (void *) I2C_CONTROL(addr));
870          wmb();
871 }
872            
873 /********************************************************************/
874 /* 
875  *  sda_read = read data bit from I2C control register
876  */
877 static inline
878 int hrt_sda_read(unsigned long addr)
879 { char c = ioread8((void *) I2C_CONTROL(addr));  return (c & HRT_I2C_SDA); }
880 
881 
882 /********************************************************************/
883 /* 
884  *  hrt_i2c_start = start I2C data transmission
885  */
886 static inline
887 void hrt_i2c_start(hrt_t *dev, unsigned long addr) 
888 { 
889          hrt_sda_scl(dev, addr, 0, 0);
890          hrt_i2c_delay();
891          hrt_sda(dev, addr, 1);
892          hrt_i2c_delay();
893          hrt_scl(dev, addr, 1);
894          hrt_i2c_delay();
895          hrt_sda(dev, addr, 0);
896          hrt_i2c_delay();
897          hrt_scl(dev, addr, 0);
898 }
899 
900 /********************************************************************/
901 /* 
902  *  hrt_i2c_stop = end I2C data transmission
903  */
904 static inline
905 void hrt_i2c_stop(hrt_t *dev, unsigned long addr) 
906 { 
907          hrt_sda_scl(dev, addr, 0, 0);
908          hrt_i2c_delay();
909          hrt_scl(dev, addr, 1);
910          hrt_i2c_delay();
911          hrt_sda(dev, addr, 1);
912          hrt_i2c_delay();
913          hrt_scl(dev, addr, 0);
914          hrt_scl(dev, addr, 1);
915 }
916 
917 /********************************************************************/
918 /* 
919  *  hrt_i2c_send_bit
920  */
921 static 
922 int hrt_i2c_send_bit(hrt_t *dev, 
923                      unsigned long addr, unsigned char bit)
924 {
925          unsigned long timeout;
926          if (bit) hrt_sda(dev, addr, 1);
927          else        hrt_sda(dev, addr, 0);
928          hrt_i2c_delay();
929          iowrite8(dev->i2c_bits | 0x04, (void *) I2C_CONTROL(addr));
930          wmb();
931          hrt_i2c_delay();
932          if (I2C_BUSY(addr)) {
933                   timeout = jiffies + HZ/10;
934                   while (I2C_BUSY(addr)) {
935                            if (jiffies > timeout) {
936                                     HRT_ERROR_MSG("i2c bus timeout");
937                                     return -1;
938                            }
939                   }
940          }                        
941          return 0;
942 }
943 
944 /********************************************************************/
945 /* 
946  *  hrt_i2c_send_byte
947  */
948 static
949 int hrt_i2c_send_byte(hrt_t *dev, unsigned long addr, unsigned char data)
950 {
951          char bitpos, bit;
952          for(bitpos = 0; bitpos < 8; bitpos++) {
953                   bit = (data & 0x80) >> 7;
954                   data <<= 1;
955                   if(hrt_i2c_send_bit(dev, addr, bit)) goto failure;
956          }
957          hrt_i2c_delay();
958          hrt_sda_scl(dev, addr, 1, 0);
959          hrt_scl(dev, addr, 1);  /* leave clock high */
960          udelay(10);
961          if (hrt_sda_read(addr)) {
962                   HRT_ERROR_MSG("no i2c ack");
963                   goto failure;
964          }          
965          hrt_sda_scl(dev, addr, 1, 0);
966          return 0;
967  failure:
968          hrt_sda_scl(dev, addr, 1, 0);
969          hrt_i2c_stop(dev, addr);
970          return -1;
971 }
972 
973 /********************************************************************/
974 /* 
975  *  hrt_i2c_init_registers
976  *
977  *  sends a sequence of values to the A/D converter device over the I2C bus.
978  *  For an example of the format of "sequence" see the declaration of 
979  *  saa7110_default_init_regs[] above.  The first byte is the number of
980  *  data bytes that follow. The rest of the sequence is a series of pairs
981  *  of a register number followed by a value. It is better if the values
982  *  are sorted in increasing order of register number, but the sequence may
983  *  have gaps and need not be in order.
984  */
985 int  hrt_i2c_init_registers(hrt_t *dev, const char *sequence)
986 {
987          unsigned long addr;
988          int i, len, cur_reg;
989 
990          len  = (int) (*sequence++);
991          addr = dev->virt_addr;
992 
993          if (len <= 2) {
994                   HRT_ERROR_MSG("invalid register initialization sequence");
995                   return -1;
996          }
997 
998          hrt_i2c_start(dev, addr);
999 
1000          /* here we select the A/D Device on the i2c bus 
1001           * that should pay attention to the following bytes */
1002          if (hrt_i2c_send_byte(dev, dev->virt_addr, HRT_AD_DEVICE_ID)) {
1003                   HRT_ERROR_MSG("send_byte failed");
1004                   return -1;
1005          }
1006 
1007          /* start at the first register and increment along the way */
1008          if (hrt_i2c_send_byte(dev, dev->virt_addr, cur_reg = sequence[0])) {
1009                   HRT_ERROR_MSG("send_byte failed(2)");
1010                   return -1;
1011          }
1012 
1013          for(i = 0; i < len; i += 2, sequence += 2) {
1014                   char reg  = sequence[0];
1015                   char data = sequence[1];
1016                   if (reg > HRT_SAA7110_MAXREG) {
1017                            HRT_ERROR_MSG("register %02X out of range!", reg);
1018                            return -1;
1019                   }
1020                   if (reg != cur_reg) {   
1021 
1022                            /* we're going to an entirely different register */
1023                            hrt_i2c_stop(dev, addr);
1024                            hrt_i2c_start(dev, addr);
1025 
1026                            /* select the chip/device on the bus */
1027                            if (hrt_i2c_send_byte(dev, dev->virt_addr, HRT_AD_DEVICE_ID)) {
1028                                     HRT_ERROR_MSG("send_byte failed(3)");
1029                                     return -1;
1030                            }
1031 
1032                            /* select the register */
1033                            if (hrt_i2c_send_byte(dev, dev->virt_addr, cur_reg = reg)) {
1034                                     HRT_ERROR_MSG("send_byte failed(4)");
1035                                     return -1;
1036                            }
1037                   }
1038 
1039                   if (hrt_i2c_send_byte(dev, dev->virt_addr, data)) {
1040                            HRT_ERROR_MSG("send_byte failed(5)");
1041                            return -1;
1042                   }
1043                   dev->saa7110_registers[cur_reg++] = data;
1044          }
1045          /* free the i2c bus */
1046          hrt_i2c_stop(dev, addr);
1047          return 0;
1048 }
1049 
1050 /********************************************************************/
1051 int hrt_i2c_init_device(hrt_t *dev)
1052 {
1053          int result = 0;
1054          HRT_DEBUG_MSG(2, "hrt_i2c_init_device entered"
1055                        " (virt_addr = %08X, addr = %08X)", 
1056                        (unsigned) dev->virt_addr,
1057                        (unsigned) dev->phys_addr);
1058 
1059          result = hrt_i2c_init_registers(dev, saa7110_default_init_regs);
1060          if (result) {
1061                   HRT_ERROR_MSG("hrt_i2c_init_registers failed %d", result);
1062                   return result;
1063          }
1064          HRT_DEBUG_MSG(2, "hrt_i2c_init_device returning %d", result);
1065          return result;
1066 }
1067 
1068 
1069 /********************************************************************
1070  *
1071  * grab_field
1072  *
1073  * Function that reads one field from the device and copies it to the
1074  * hrtdev->framedata buffer. This grab_field is executed twice to read 
1075  * fields and then we have a complete frame for the user.
1076  
1077  * This function is implemented differantly for color and gray scale devices
1078  * since they are stored differantly inside the device's memory
1079  * the grey scale implementation is straightforward 
1080  * but the color device stores its data in a peculiar fashion.
1081  * Each line has 1664 bytes organised as follows
1082  * 512 bytes - first 512 LSBs
1083  * 512 bytes - first 512 MSBs
1084  * 128 bytes - last 128 LSBs
1085  * 384 bytes - BLANK !!
1086  * 128 bytes - last 128 MSBs
1087  * All this needs to be reorganised the 1280 bytes for one line
1088  * And in case of a smaller subwindow the coordinates of the subwindow 
1089  * need to be taken care of while implementing this 
1090  *
1091  * the 'parity' argument determines the location of this field 
1092  * inside the current frame
1093  * 
1094  * Point to note - 
1095  * GreyScale requires 1 byte per pixel
1096  * Color requires 2 bytes per pixel 
1097  */
1098 void grab_field( hrt_t *hrtdev, unsigned char *framedata,
1099                  int parity)
1100 {
1101          int i,j,k;
1102          /* Length of the line; used here only by the grey scale implementation */
1103          int linelen; 
1104          /* Coordinates of the sub window */     
1105          int win_width, win_height, win_col, win_row;
1106          win_width  = hrtdev->win->width;
1107          win_height = hrtdev->win->height;
1108          win_row    = hrtdev->win->starty;
1109          win_col    = hrtdev->win->startx;
1110 
1111          if( (hrtdev->mode & HRT_COLOR_MODE) ){
1112                   linelen    = hrtdev->win->width;
1113                   /* For the color case we split up work into three cases
1114                    * Case 1 : window completely to the left of the 512 pixel boundary
1115                    * Case 2 : window crossing the 512 pixel boundary
1116                    * Case 3 : window completely to the right of the 512 pixel boundary
1117                    last 128 pixels of the row
1118                   */
1119 
1120                   for (i = (!parity) + win_row; i < win_height; i += 2) {
1121                            /* Write the address of the required line into the register */
1122                            iowrite16(i, (void*)hrtdev->virt_addr + HRT_Y_LOW_REG);
1123                            wmb();
1124                            /* color card - number of bytes required = 2 X win_width */
1125                            memset(hrtdev->localbuf, 0, 2*win_width);
1126 
1127                            /* Case 1 */
1128                            if ( (win_col + win_width) < 512){
1129                                     /* Get the first win_width MSBs */
1130                                     memcpy(hrtdev->localbuf, (void *)hrtdev->virt_addr + win_col, win_width);
1131                                     /* Get the first win_width LSBs */
1132                                     memcpy(hrtdev->localbuf + win_width, (void *)hrtdev->virt_addr + 512 + win_col, win_width);
1133                            }
1134 
1135                            /* Case 2 
1136                             * This one gets messy, but this is correct
1137                             * and works fine !
1138                             * all this for efficiency !
1139                             * */
1140                            else if ( ((win_col +win_width) >= 512) && (win_col < 512) ){
1141                                     /* Get the first (512 - win_col) MSBs */
1142                                     memcpy(hrtdev->localbuf, (void *)hrtdev->virt_addr + win_col ,
1143                                            512 - win_col);
1144                                     /* Get the last (win_width - 512 + win_col) MSBs */
1145                                     memcpy(hrtdev->localbuf+ 512 - win_col, (void *)hrtdev->virt_addr + 1024,
1146                                            win_width -512 +win_col);
1147                                     /* Get the first (512 - win_col) LSBs */
1148                                     memcpy(hrtdev->localbuf + win_width , (void *)hrtdev->virt_addr + 512 + win_col,
1149                                            512 - win_col);
1150                                     /* Get the last (win_width - 512 + win_col) LSBs */
1151                                     memcpy(hrtdev->localbuf + win_width +512 - win_col, (void *)hrtdev->virt_addr + 1536,
1152                                            win_width - 512 + win_col);
1153                            }
1154 
1155                            /* Case 3 */
1156                            else if ( ((win_col +win_width) >= 512) && (win_col >= 512) ){
1157                                     /* Get the first win_width MSBs */
1158                                     memcpy(hrtdev->localbuf, (void *)hrtdev->virt_addr + win_col + 1024, win_width);
1159                                     /* Get the first win_width MSBs */
1160                                     memcpy(hrtdev->localbuf + win_width, (void *)hrtdev->virt_addr + 1536 + win_col, win_width);
1161                            }
1162                            /* At this point for all three cases we have all the bytes
1163                             * stored in the form of all MSBs followed by all LSBs
1164                             * Now copy into the framedata buffer one MSB followed
1165                             * by the corresponding LSB
1166                             *
1167                             * However the destination for the copy is differant for the case of streaming I/O 
1168                             * as compared to the regular reads.
1169                             * For streaming, we want to copy into the buffer that was passed as a parameter to
1170                             * this function
1171                             * But for the read operation we need to copy into the device's frame sized buffer 'framedata'
1172                             *  
1173                             * Neat !!!
1174                             * 
1175                             */  
1176                            if (!hrtdev->streaming) {
1177                                     /* This is for the blocking read based display */
1178                                     for (k = 0; k < win_width; k++) {
1179                                              j = k;
1180                                              if ( !(hrtdev->upside_down) ){
1181                                                      hrtdev->framedata[(i*2*win_width) + 2*k]   = hrtdev->localbuf[j];
1182                                                      hrtdev->framedata[(i*2*win_width) + 2*k+1] = hrtdev->localbuf[j+win_width];
1183                                              }
1184                                              else {
1185                                                      /* If the user wishes to see the image upside down then this code
1186                                                       * makes that happen. In our case we as user wanted to have that functionality
1187                                                       * since our camera was mounted upside down. So implemented this feature !!
1188                                                       */
1189                                                      hrtdev->framedata[((win_height-i+win_row-parity)*2*win_width) + 2*k]   = hrtdev->localbuf[j];
1190                                                      hrtdev->framedata[((win_height-i+win_row-parity)*2*win_width) + 2*k+1] = hrtdev->localbuf[j+win_width];
1191                                             }
1192                                     }
1193                            }
1194                            else {
1195                                     /* This is for the streaming I/O */
1196                                     for (k = 0; k < win_width; k++) {
1197                                              j = k;
1198                                              if ( !(hrtdev->upside_down) ){
1199                                                      framedata[(i*2*win_width) + 2*k]   = hrtdev->localbuf[j];
1200                                                      framedata[(i*2*win_width) + 2*k+1] = hrtdev->localbuf[j+win_width];
1201                                              }
1202                                              else {
1203                                                      /* If the user wishes to see the image upside down then this code
1204                                                       * makes that happen. In our case we as user wanted to have that functionality
1205                                                       * since our camera was mounted upside down. So implemented this feature !!
1206                                                       */
1207                                                      framedata[((win_height-i+win_row-parity)*2*win_width) + 2*k]   = hrtdev->localbuf[j];
1208                                                      framedata[((win_height-i+win_row-parity)*2*win_width) + 2*k+1] = hrtdev->localbuf[j+win_width];
1209                                             }
1210                                     }
1211                            }
1212                   }
1213          }
1214          else { /* Out of the color mode. This one is for gray scale */
1215                   /* Following takes care of the sub window coordinates */
1216                   linelen = hrtdev->win->width - hrtdev->win->startx;
1217                   /* Since this is just a single field that we are writing into the buffer
1218                    * we write each line of this field into an alternate line of the buffer.
1219                    * Interleaving.
1220                    */
1221                   if (hrtdev->upside_down == 1) {
1222 
1223                            for (i = (!parity) + hrtdev->win->starty; i < hrtdev->win->height; i += 2) {
1224                                     iowrite16(i, (void *)hrtdev->virt_addr + HRT_Y_LOW_REG);
1225                                     wmb();
1226                                     /* Copy into the 'framedata' the desired part of the current line,
1227                                      * at the correct location inside the buffer
1228                                      */ 
1229                                     memcpy_fromio(framedata + (hrtdev->win->height - i - parity - hrtdev->win->starty) * linelen,
1230                                                   (void *)hrtdev->virt_addr + hrtdev->win->starty,
1231                                                   linelen);
1232                            }
1233                   }
1234                   else {
1235                            for (i = (!parity) + hrtdev->win->starty; i < hrtdev->win->height; i += 2) {
1236                                     iowrite16(i, (void *)hrtdev->virt_addr + HRT_Y_LOW_REG);
1237                                     wmb();
1238                                     /* Copy into the 'framedata' the desired part of the current line,
1239                                      * at the correct location inside the buffer
1240                                      */ 
1241                                     memcpy_fromio(framedata + (i * linelen),
1242                                                   (void *)hrtdev->virt_addr + hrtdev->win->starty,
1243                                                   linelen);
1244 
1245                            }
1246                   }
1247 
1248          }
1249 
1250 }
1251 
1252 /********************************************************************/
1253 static inline
1254 void hrt_irq_enable(hrt_t *dev)
1255 {
1256          int val;
1257          val = ioread8((void *)(dev->virt_addr + HRT_IRQ_ENABLE));
1258          val |= 0x1;
1259          iowrite8(val, (void *) (dev->virt_addr + HRT_IRQ_ENABLE));
1260 }
1261            
1262 /********************************************************************/
1263 static inline
1264 void hrt_irq_disable(hrt_t *dev)
1265 {
1266          int val;
1267          val = ioread8((void *)(dev->virt_addr + HRT_IRQ_ENABLE));
1268          val &= ~0x1;
1269          iowrite8(val, (void *) (dev->virt_addr + HRT_IRQ_ENABLE));
1270 }
1271 
1272 /********************************************************************
1273  ******** timer/tasklet related functions declared here ***********
1274  */
1275 
1276 void hrt_tasklet(unsigned long);
1277 void hrt_timer_init(hrt_t* dev);
1278 void hrt_timer_cleanup(hrt_t* dev);
1279 int hrt_timer_activate(hrt_t* dev);
1280 void hrt_timer_deactivate(hrt_t* dev);
1281 
1282 
1283 /********************************************************************
1284  * hrt_cleanup
1285  * 
1286  * Cleanup the device - called from the module cleanup routine
1287  */
1288 
1289 void hrt_cleanup(hrt_t* dev)
1290 {
1291          HRT_DEBUG_MSG(1, "shutting down hrt device %d at 0x%lx",
1292                        dev->num, dev->phys_addr);
1293          HRT_MODULE_CHECK (HRT_MODULE_FINALIZING_STATE | 
1294                            HRT_MODULE_INITIALIZING_STATE, "1");
1295          HRT_CHECK (dev, HRT_INITIALIZING_STATE 
1296                     | HRT_CLOSED_STATE | HRT_FINALIZING_STATE, "2");
1297          dev->state = HRT_FINALIZING_STATE;
1298 
1299          /* restore device to an inactive state */
1300          hrt_freeze_next(dev);
1301 
1302          /* deactivate and remove interrupt handler or timer */
1303          hrt_timer_cleanup (dev);
1304 
1305          if (dev->phys_addr) {
1306                   HRT_DEBUG_MSG(2, "release_mem_region 0x%lx, 0x%lx",
1307                                 (unsigned long)dev, (unsigned long) dev->phys_addr);
1308                   release_mem_region(dev->phys_addr, HRT_IO_SIZE);
1309                   dev->phys_addr = 0;
1310          }
1311          if (dev->virt_addr) {
1312                   HRT_DEBUG_MSG(2, "iounmap %lx", (unsigned long) dev->virt_addr);
1313                   iounmap((void *)dev->virt_addr);
1314                   dev->virt_addr = 0;
1315          }
1316 #ifdef CONFIG_PCI
1317          if (dev->pci_dev) {
1318                   pci_disable_device(dev->pci_dev);
1319                   dev->pci_dev = NULL;
1320          }
1321 #endif
1322 
1323          /* De-allocate frame buffer */
1324          if (dev->framedata) {
1325                   vfree(dev->framedata);
1326                   dev->framedata = NULL;
1327          }
1328          /* Deallocate the smaller local buffer */       
1329          if (dev->localbuf) {
1330                   kfree(dev->localbuf);
1331                   dev->localbuf = NULL;
1332          }
1333          
1334          /* Set the device state to uninitialised 
1335           * now that it is all cleaned up
1336           */
1337          dev->state = HRT_UNINITIALIZED_STATE;
1338 
1339 }
1340 
1341 /********************************************************************
1342  * hrt_lock_init
1343  *
1344  * Initialises the spin lock used in the module
1345  */
1346 void hrt_lock_init(hrt_t * dev) {
1347          spin_lock_init(&dev->spinlock);
1348          dev->is_locked = 0;
1349 }
1350 
1351 /********************************************************************
1352  * hrt_trylock
1353  * 
1354  * Does nothing. Just checks the spinlock.
1355  */
1356 int hrt_trylock(hrt_t * dev) {
1357          spin_lock(&dev->spinlock);
1358          if (dev->is_locked) {
1359                   spin_unlock(&dev->spinlock);
1360                   return 1; 
1361          }
1362          dev->is_locked = 1;
1363          spin_unlock(&dev->spinlock);
1364          return 0;
1365 }
1366 
1367 /********************************************************************
1368  * hrt_lock
1369  *
1370  * lock the device
1371  */
1372 void hrt_lock(hrt_t * dev) {
1373          unsigned long flags;
1374          spin_lock_irqsave(&dev->spinlock, flags);
1375          if (dev->is_locked) {
1376                   HRT_ERROR_MSG("locking an already-locked device");
1377          }
1378          dev->is_locked = 1;
1379          spin_unlock_irqrestore(&dev->spinlock, flags);
1380 }
1381 
1382 /********************************************************************
1383  * hrt_unlock
1384  *
1385  * Unlock the device
1386  */
1387 void hrt_unlock(hrt_t * dev) {
1388          spin_lock(&dev->spinlock);
1389          if (!dev->is_locked) {
1390                   HRT_ERROR_MSG("unlocking unlocked device");
1391          }
1392          dev->is_locked = 0;  
1393          spin_unlock(&dev->spinlock);
1394 }
1395 
1396 /********************************************************************
1397  * hrt_init
1398  *
1399  *  Long function..
1400  *  Probes and initialises the device
1401  */
1402 int hrt_init(unsigned long phys_address, struct pci_dev * pci_dev)
1403 {
1404          hrt_t * dev = &hrt_devices[hrt_num_devices];
1405          int i, result;
1406          char *bus, *color, *ported;
1407          unsigned int old_control, old_y_high, old_y_low;
1408          unsigned char val1, val2;
1409          unsigned long virt_address;
1410 
1411          HRT_DEBUG_MSG(1, "probing device at 0x%lx", phys_address);
1412 
1413          memset(dev, 0, sizeof(hrt_t));
1414 
1415          dev        = &hrt_devices[hrt_num_devices];
1416 
1417          dev->state = HRT_INITIALIZING_STATE;
1418          dev->num   = hrt_num_devices;
1419          hrt_lock_init (dev);
1420 
1421          tasklet_init(&dev->tasklet, hrt_tasklet, (unsigned long) dev);
1422          dev->tasklet_active = 1;
1423 
1424          /* reserve the I/O address space for this device */
1425          if (!request_mem_region(phys_address, HRT_IO_SIZE, "hrt")) {
1426                   HRT_ERROR_MSG("I/O memory at %lx already in use",
1427                                 (unsigned long) phys_address);
1428                   // hrt_cleanup(dev);
1429                   return -EBUSY;
1430          }
1431          dev->phys_addr = phys_address;
1432 
1433          /* map the device's I/O space into kernel memory */
1434          virt_address = (unsigned long)
1435                   ioremap_nocache(phys_address, HRT_IO_SIZE);
1436          if (!virt_address) {
1437                   HRT_ERROR_MSG("couldn't remap io memory!!");
1438                   hrt_cleanup(dev);
1439                   return -ENODEV;
1440          }
1441          dev->virt_addr = virt_address;
1442 
1443 #ifdef CONFIG_PCI
1444          /* pci-specific processing */
1445          if (pci_dev) {
1446                   pci_set_drvdata (pci_dev, dev);
1447                   dev->pci_dev = pci_dev;
1448                   dev->irq = -pci_dev->irq;
1449                   dev->mode &= ~HRT_ISA_MODE;
1450                   /* make certain IRQ is disabled before enabling
1451                      device, or else we may get an IRQ we are not
1452                      prepared to handle? */
1453                   hrt_irq_disable(dev);
1454                   if (pci_enable_device(pci_dev)) {
1455                            HRT_ERROR_MSG("pci_enable_device failed");
1456                            hrt_cleanup(dev);
1457                            return -EIO;
1458                   }
1459          }
1460 #endif
1461 
1462          /* find out whether there is an hrt device at this
1463             address, and which type of device it is */
1464 
1465          /* save the values we are about to modify */
1466          old_control = ioread8((void *)(HRT_CONTROL_REG + virt_address));
1467          old_y_low = ioread8((void *)(HRT_Y_LOW_REG + virt_address));
1468          old_y_high = ioread8((void *)(HRT_Y_HIGH_REG + virt_address));
1469 
1470          /* freeze the frame grabbing, immediately */
1471          iowrite8(0x5B, (void *) (HRT_CONTROL_REG + virt_address));
1472          
1473          /* complement pixel (0,0) */
1474          iowrite16(0, (void *) (HRT_Y_LOW_REG + virt_address));
1475          iowrite16(0, (void *) (HRT_Y_HIGH_REG + virt_address));
1476          val1 = ioread8((void *) virt_address);
1477          iowrite8(~val1, (void *) virt_address);
1478            
1479          /* write old value of pixel (0,0) to (1,0) */
1480          iowrite16(1, (void *) (HRT_Y_LOW_REG + virt_address));
1481          iowrite8(val1, (void *) virt_address);
1482            
1483          /* read the value at the previous raster/row */
1484          iowrite16(0, (void *) (HRT_Y_LOW_REG + virt_address));
1485          val2 = ioread8((void *) virt_address);
1486            
1487          if (val2 != (unsigned char)~val1) {
1488                   HRT_DEBUG_MSG(1, "no hrt device at address 0x%lx",
1489                                 virt_address);
1490                   /* restore the old values, and hope we did no
1491                      damage to some other device at this address;
1492                      this is pretty poor, since if there is
1493                      another device at that address the effects
1494                      of these writes could be harmful;
1495                      ideally, there should be a way to 
1496                      identify the devices that only uses read
1497                      operations */
1498                   iowrite8(val1, (void *) virt_address);
1499                   iowrite8(old_y_low, (void *) (HRT_Y_LOW_REG + virt_address));
1500                   iowrite8(old_y_high, (void *) (HRT_Y_HIGH_REG + virt_address));
1501                   iowrite8(old_control, (void *) (HRT_CONTROL_REG + virt_address));
1502 
1503                   hrt_cleanup(dev);
1504                   return -ENODEV;
1505          }
1506 
1507          /* test whether we have a color or greyscale card:
1508             the color frame buffer has line of 2048 = 0x400
1509             pixels; greyscale has only 512 pixels/line, so
1510             the memory mapped row of frame buffer memory
1511             should wrap around at 0x200 and 0x400 on a greyscale card
1512             but should be good through 0x400 on a color card. */
1513 
1514          iowrite8(HRT_FREEZE_IMM_CMD, (void *) (HRT_CONTROL_REG + virt_address));
1515          iowrite16(0, (void *) (HRT_Y_LOW_REG + virt_address));
1516          iowrite16(0, (void *) (HRT_Y_HIGH_REG + virt_address));
1517          val1 = ioread8((void *)(0x400 + virt_address));
1518          iowrite8(~val1, (void *) (0x400 + virt_address));
1519          /* in case greyscale addresses wrap around,
1520             refresh the value at offset zero */
1521          iowrite8(val1, (void *) (virt_address));
1522          val2 = ioread8((void *)(0x400 + virt_address));
1523          if (val2 == (unsigned char) ~val1) {
1524                   dev->mode |= HRT_COLOR_MODE;
1525                   /* infer the frame geometry from the device type */
1526                   HRT_DEBUG_MSG(1, "COLOR device detected");
1527                   dev->rows = 480;
1528                   dev->cols = 640;
1529                   dev->bytes_per_pixel = 2;
1530          } else {
1531                   HRT_DEBUG_MSG(1, "GREYSCALE device detected");
1532                   dev->cols = 512;  /* is for NTSC, 512 for PAL */
1533                   dev->rows = 480;
1534                   dev->bytes_per_pixel = 1;
1535          }
1536 
1537          /* try to initialize the device */
1538          result = hrt_i2c_init_device(dev);
1539          if (result) {
1540                   HRT_ERROR_MSG("hrt_i2c_init_device %d failed",result);
1541                   hrt_cleanup(dev);
1542                   return -ENODEV;
1543          }
1544 
1545          hrt_go_live(dev);  /* delete this once driver is debugged */
1546 
1547          /* find out whether the device has dual-ported memory*/
1548          while (ioread8((void *)(dev->virt_addr + HRT_CONTROL_REG)) & 0x40) {
1549                   hrt_printk( "waiting on dual port check\n");
1550                   schedule();
1551          }
1552 
1553          /* try to overwrite the line with ones */
1554          for (i = 0; i < 512; i++) {
1555                   iowrite8(255, (void *) (dev->virt_addr + i));
1556          }
1557 
1558          /* freeze the image */
1559          hrt_freeze_immediate(dev);
1560 
1561          /* write zeros to horizontal raster line 500,
1562             a line that the A/D unit does not modify */
1563          iowrite16(0, (void *) (dev->virt_addr + HRT_Y_HIGH_REG));
1564          iowrite16(500, (void *) (dev->virt_addr + HRT_Y_LOW_REG));
1565          for (i = 0; i < 512; i++) {
1566                   iowrite8(0, (void *)(dev->virt_addr + i));
1567          }
1568 
1569          /* set capturing mode */
1570          hrt_go_live(dev);
1571 
1572          /* try to overwrite the line with ones */
1573          for (i = 0; i < 512; i++) {
1574                   iowrite8(255, (void *) (dev->virt_addr + i));
1575          }
1576          
1577          /* freeze the image */
1578          hrt_freeze_immediate(dev);
1579 
1580          /* read back the line;
1581             if some of the pixels are still zero the memory is
1582             not dual ported */
1583          result = 1;
1584          for (i = 0; i < 512; i++) {
1585                   if (!ioread8((void *)(dev->virt_addr + i)))  result = 0;
1586          }
1587          if (result) {
1588                   HRT_DEBUG_MSG(1, "seems to be dual ported");
1589                   dev->mode |= HRT_DUAL_PORTED_MODE;
1590          }
1591 
1592          dev->mode |= HRT_ISA_MODE;
1593 
1594 #ifdef CONFIG_PCI
1595          if ((pci_dev->device == HRT_DEVICE_ID_COLOR) !=
1596              ((dev->mode & HRT_COLOR_MODE) == HRT_COLOR_MODE))
1597                   HRT_ERROR_MSG("PCI and probed types don't match");
1598 #endif
1599 
1600          /* discover whether this device supports interrupts */
1601          hrt_timer_init(dev);
1602          if (dev->mode & HRT_IRQ_MODE) {
1603                   /* BASIC IDEA
1604                    * Enable the device for 20 ms
1605                    * and count the number of interrupts generated
1606                    * a non zero value means that this device supports
1607                    * IRQs
1608                    */
1609                   dev->irq_count = 0;
1610                   hrt_irq_enable(dev);
1611                   hrt_go_live(dev);
1612                   mdelay(20);
1613                   hrt_freeze_immediate(dev);
1614                   hrt_irq_disable(dev);
1615                   if (dev->irq_count) {
1616                            HRT_DEBUG_MSG(1, "counted %d irqs in 20 ms",
1617                                          dev->irq_count);
1618                            HRT_ERROR_MSG("devices supports IRQs");
1619                   } else {
1620                            HRT_DEBUG_MSG(1, "no irqs in 20 ms");
1621                            dev->irq = 0;
1622                            dev->mode &= ~HRT_IRQ_MODE;
1623                   }
1624          }
1625 
1626          /* describe this device for the log */
1627          if (dev->mode & HRT_ISA_MODE) bus = "ISA";
1628          else bus = "PCI";
1629          if (dev->mode & HRT_COLOR_MODE) color = "COLOR";
1630          else color = "GREYSCALE";
1631          if (dev->mode & HRT_DUAL_PORTED_MODE) ported = "DUAL";
1632          else ported = "SINGLE";
1633          HRT_ERROR_MSG("found device %d at 0x%lx",
1634                        dev->num, dev->phys_addr);
1635          HRT_ERROR_MSG("%s %s with %s-ported memory",
1636                        bus, color, ported);
1637          if (dev->mode & HRT_IRQ_MODE) 
1638                   HRT_ERROR_MSG("using IRQ %d", dev->irq);
1639 
1640          init_waitqueue_head(&dev->wait_queue);
1641          
1642          /* Read the field bit and assign to the field_id variable */    
1643          dev->field_id = ioread8((void *)dev->virt_addr + HRT_CONTROL_REG) & 1;
1644          /* Initialize the semaphore */
1645          init_MUTEX(&dev->sem); 
1646          
1647          /* set default window size
1648             to cover the entire frame buffer */
1649          HRT_DEBUG_MSG(1, "setting width, cols = %d", dev->cols);
1650          dev->win_row = 0;
1651          dev->win_width = dev->cols;
1652          dev->win_col = 0;
1653          dev->win_height = dev->rows;
1654          dev->field = -1;
1655          hrt_num_devices++;
1656          dev->state = HRT_CLOSED_STATE;
1657 
1658 
1659          /* Make the lists used for streaming empty */
1660          /* Added 2005.06.11 Sean/ Atulya 
1661             begin */
1662          
1663          INIT_LIST_HEAD(&dev->capture_list.head);
1664          INIT_LIST_HEAD(&dev->done_list.head);
1665          
1666          dev->capture_list.length = dev->done_list.length = 0;
1667 
1668          /* Initialize the spinlocks to protect the lists */
1669          dev->capture_list.lock = RW_LOCK_UNLOCKED;
1670          dev->done_list.lock = RW_LOCK_UNLOCKED;
1671         
1672          /* Register with V4L */
1673          dev->video_dev = videodev_template;
1674          /* Register the video driver */
1675          if (video_register_device(&dev->video_dev, VFL_TYPE_GRABBER,
1676                                    video_minor) < 0) {
1677                   hrt_printk(KERN_ERR "Unable to register video device\n");
1678                   /* Failure in the device registration
1679                    * Cleanup before exiting
1680                    */
1681                   hrt_cleanup(dev);
1682                   return -ENODEV;
1683          }
1684 
1685          /* Set private data (to access through struct file) */
1686          dev->video_dev.priv = dev;
1687          
1688          /* Set the constants depending on 
1689           * whether the device supports color
1690           * or grey scale
1691           */
1692          if(dev->mode & HRT_COLOR_MODE){
1693                   dev->bytesperline = HRT_COLOR_BYTES_PER_LINE;
1694                   dev->framesize = HRT_COLOR_FRAMESIZE;
1695          }
1696          else{
1697                   dev->bytesperline = HRT_GRAY_BYTES_PER_LINE;
1698                   dev->framesize = HRT_GRAY_FRAMESIZE;
1699          }
1700 
1701          /* Added 2005.06.11 Sean/ Atulya 
1702             end */
1703 
1704          /* Allocate the frame buffer */
1705          if (dev->mode & HRT_COLOR_MODE) {
1706                   dev->framedata = (unsigned char *) vmalloc(HRT_COLOR_FRAMESIZE);
1707                   dev->localbuf  = (unsigned char *) kmalloc(sizeof(char) * 1664, GFP_KERNEL);
1708                   /* Added 2005.06.11 Sean/ Atulya 
1709                      begin */
1710                   if ((dev->framedata == NULL) || (dev->localbuf == NULL)) {
1711                            hrt_printk(KERN_ERR "Unable to allocate memory\n");
1712                            //video_unregister_device(&dev->video_dev);
1713                            hrt_cleanup(dev);                       
1714                            return -ENOMEM;
1715                   }
1716                   /* Added 2005.06.11 Sean/ Atulya 
1717                      end */
1718          }
1719          else {
1720                   dev->framedata = (unsigned char *) vmalloc(HRT_GRAY_FRAMESIZE);
1721                   dev->localbuf  = NULL;
1722                   /* Added 2005.06.11 Sean/ Atulya 
1723                      begin */
1724                   if (dev->framedata == NULL) {
1725                            hrt_printk(KERN_ERR "Unable to allocate memory\n");
1726                            //video_unregister_device(&dev->video_dev);
1727                            hrt_cleanup(dev);                       
1728                            return -ENOMEM;
1729                   }
1730                   /* Added 2005.06.11 Sean/ Atulya 
1731                      end */
1732          }
1733 
1734          /* The device opens in the non streaming mode by default */
1735          dev->streaming = 0;
1736 
1737          /* Added 13 June 2005 */
1738          dev->streaming_state = 0;
1739 
1740          dev->upside_down = 0;
1741 
1742          /* Read the field bit and assign to the field_id */
1743          dev->field_id = hrt_get_field(dev);
1744         
1745          /* Make the device go-live */
1746          hrt_go_live(dev);
1747          
1748          return 0;
1749 }
1750 
1751 /********************************************************************/
1752 int  hrt_isa_init(void)
1753 {
1754          int i;
1755          for (i = 0; i < ARRAY_SIZE(hrt_addresses); i++)
1756                   hrt_init(hrt_addresses[i], NULL);
1757          hrt_nonpci_devices = hrt_num_devices;
1758          return 0;
1759 }
1760 
1761 /********************************************************************/
1762 void hrt_isa_cleanup(void)
1763 {  
1764          int i;
1765          for (i=0; i<hrt_nonpci_devices; i++) {
1766                   HRT_DEBUG_MSG(2, "cleaning up device %d", i);
1767                   hrt_cleanup(hrt_devices+i);
1768          }
1769 }
1770 
1771 /*************************
1772  * interrupts and timers *
1773  *************************/
1774 
1775 /********************************************************************/
1776 int  hrt_irq_pending(hrt_t *dev)
1777 {
1778          int r = ioread8((void *)(dev->virt_addr + HRT_CONTROL_REG)) & 0x4; 
1779          rmb(); 
1780          return r;
1781 }
1782 
1783 /********************************************************************/
1784 irqreturn_t hrt_irq_handler(int irq, void* dev_id, struct pt_regs* regs)
1785 {
1786          hrt_t* dev = dev_id;
1787          if (!hrt_irq_pending(dev)) goto none;
1788          /* acknowledge the interrupt */
1789 
1790          hrt_irq_disable(dev);
1791          dev->irq_count++;
1792          /* do not try to do any I/O on the device here,
1793             or else risk race with last scheduled tasklet
1794          */
1795          tasklet_schedule(&dev->tasklet);
1796          /* enable the next interrupt */
1797          hrt_irq_enable(dev);
1798 #ifdef IRQ_HANDLED
1799          return IRQ_HANDLED;
1800 #endif
1801  none:
1802 #ifdef IRQ_NONE
1803          return IRQ_NONE;
1804 #endif
1805 }
1806 
1807 
1808 /********************************************************************/
1809 /**
1810  * streaming_fieldchange_color 
1811  *
1812  * Invoked for performing the data reads when streaming 
1813  * is in progress
1814  * Called by the timer handler when it determines that
1815  * a complete frame is available for reading into the buffer
1816  *  
1817  */
1818 static inline void streaming_fieldchange_color(hrt_t *hrtdev)
1819 {
1820          struct stream_buffer *streambuf;
1821 
1822          /* Capture list is empty */
1823          if (!hrtdev->capture_list.length) {
1824                   return;
1825          }
1826 
1827          streambuf = queue_peek_head(&hrtdev->capture_list);
1828 
1829          /* Sanity checks- don't want to do anything bad
1830             in interrupt mode */
1831          if (streambuf == NULL) {
1832                   hrt_printk("streambuf is NULL!\n");
1833                   return;
1834          }
1835          if (streambuf->vaddress == NULL) {
1836                   hrt_printk("vaddress is NULL!\n");
1837                   return;
1838          }
1839          if (hrtdev->framedata == NULL) {
1840                   hrt_printk("framedata is NULL!\n");
1841                   return;
1842          }
1843 
1844          /* Depending on the device being color or grey scale
1845           * the buffer would have differant sizes
1846           * clear the entire buffer before writing into it
1847           *
1848           * But only if it is empty !
1849           */
1850         if (streambuf->fields_grabbed == 0 ){
1851                 if (hrtdev->mode & HRT_COLOR_MODE)
1852                           memset(streambuf->vaddress, 0, HRT_COLOR_FRAMESIZE);
1853                  else
1854                           memset(streambuf->vaddress, 0, HRT_GRAY_FRAMESIZE);
1855         }
1856 
1857          /* Grab the current field and increment the fields_grabbed variable */
1858          grab_field(hrtdev, streambuf->vaddress,hrtdev->field_id);
1859          streambuf->fields_grabbed++;       
1860 
1861         if(streambuf->fields_grabbed > 2){ 
1862                  /* We have a complete frame */
1863                  streambuf->vidbuf.flags |=
1864                           V4L2_BUF_FLAG_DONE |
1865                           V4L2_BUF_FLAG_KEYFRAME;
1866                  /* Move the buffer to the done queue */
1867                  queue_del(streambuf, &hrtdev->capture_list);
1868                  queue_add_tail(streambuf, &hrtdev->done_list);
1869                  hrtdev->field_id = !hrtdev->field_id;
1870                  /* Set streaming_state to 0 to repeat the streaming read cycle */
1871                  hrtdev->streaming_state = 0;
1872                  /* Set fields_grabbed to 0 */
1873                  streambuf->fields_grabbed = 0;
1874                  /* wake up the user to notify abt the data being available */
1875                  wake_up(&hrtdev->wait_queue);
1876         }
1877 }
1878 
1879 /********************************************************************/
1880 /**
1881  * streaming_fieldchange_irq
1882  * 
1883  * This function used for streaming if we have IRQs running
1884  * Assumes that every interrupt we know that the field has changed
1885  * So faster than using the timer based mechanism
1886  */
1887 static inline void streaming_fieldchange_irq(hrt_t *hrtdev)
1888 {
1889          struct stream_buffer *streambuf;
1890 
1891          /* Capture list is empty */
1892          if (!hrtdev->capture_list.length) {
1893                   return;
1894          }
1895 
1896          streambuf = queue_peek_head(&hrtdev->capture_list);
1897 
1898          /* Sanity checks- don't want to do anything bad
1899             in interrupt mode */
1900          if (streambuf == NULL) {
1901                   hrt_printk("streambuf is NULL!\n");
1902                   return;
1903          }
1904 
1905          if (streambuf->vaddress == NULL) {
1906                   hrt_printk("vaddress is NULL!\n");
1907                   return;
1908          }
1909         
1910          if (hrtdev->framedata == NULL) {
1911                   hrt_printk("framedata is NULL!\n");
1912                   return;
1913          }
1914         
1915          /* Now that we have checked everything
1916           * and all buffers seem to be fine
1917           * extract the current field from the device 
1918           * and copy to the buffer
1919           */
1920          grab_field(hrtdev, streambuf->vaddress,
1921                     !hrtdev->field_id);
1922 
1923          streambuf->fields_grabbed++;
1924 
1925          /* We have a complete frame */
1926          if (streambuf->fields_grabbed > 1) {
1927                   streambuf->fields_grabbed = 0;
1928                   streambuf->vidbuf.flags |=
1929                            V4L2_BUF_FLAG_DONE |
1930                            V4L2_BUF_FLAG_KEYFRAME;
1931 
1932                   /* Move the buffer to the done queue */
1933                   queue_del(streambuf, &hrtdev->capture_list);
1934                   queue_add_tail(streambuf, &hrtdev->done_list);
1935                   /* notify the wait queue that a frame is available
1936                    * for display to the user
1937                    */
1938                   wake_up(&hrtdev->wait_queue);
1939          }
1940          hrt_printk("streaming_fieldchange ... complete\n");
1941 }
1942 
1943 
1944 /********************************************************************/
1945 /**
1946  * streaming_fieldchange 
1947  *
1948  *  if streaming is on, this function is called
1949  *  from timer_func when the field_id changes
1950  */
1951 static inline void streaming_fieldchange(hrt_t *hrtdev)
1952 {
1953          struct stream_buffer *streambuf;
1954 
1955          /* Capture list is empty */
1956          if (!hrtdev->capture_list.length) {
1957                   return;
1958          }
1959 
1960          streambuf = queue_peek_head(&hrtdev->capture_list);
1961 
1962          /* Sanity checks- don't want to do anything bad
1963             in interrupt mode */
1964          if (streambuf == NULL) {
1965                   hrt_printk("streambuf is NULL!\n");
1966                   return;
1967          }
1968 
1969          if (streambuf->vaddress == NULL) {
1970                   hrt_printk("vaddress is NULL!\n");
1971                   return;
1972          }
1973         
1974          if (hrtdev->framedata == NULL) {
1975                   hrt_printk("framedata is NULL!\n");
1976                   return;
1977          }
1978         
1979          /* Now that we have checked everything
1980           * and all buffers seem to be fine
1981           * extract the current field from the device 
1982           * and copy to the buffer
1983           */
1984          grab_field(hrtdev, streambuf->vaddress,
1985                     !hrtdev->field_id);
1986 
1987          streambuf->fields_grabbed |= (!hrtdev->field_id) + 1;
1988 
1989          /* We have a complete frame */
1990          if (streambuf->fields_grabbed == 3) {
1991                   streambuf->fields_grabbed = 0;
1992                   streambuf->vidbuf.flags |=
1993                            V4L2_BUF_FLAG_DONE |
1994                            V4L2_BUF_FLAG_KEYFRAME;
1995 
1996                   /* Move the buffer to the done queue */
1997                   queue_del(streambuf, &hrtdev->capture_list);
1998                   queue_add_tail(streambuf, &hrtdev->done_list);
1999                   /* notify the wait queue that a frame is available
2000                    * for display to the user
2001                    */
2002                   wake_up(&hrtdev->wait_queue);
2003          }
2004 }
2005 
2006 
2007 /********************************************************************
2008  * hrt_timer_handler
2009  *
2010  * Runs every HZ/100 jiffies 
2011  * Core of the driver's functionality in the case where 
2012  * we do not have interrupts running on the card.
2013  *
2014  * If we are in the blocking read mode, then this timer
2015  * notifies the reader about field changes, and wakes up 
2016  * the reader when a new frame becomes available
2017  *
2018  * If we are in the streaming I/O mode, then the timer
2019  * performs checks on the device field changes
2020  * and invokes the streaming_fieldchange or the streaming_fieldchange_color
2021  * function based on the device's mode.
2022  */  
2023 void hrt_timer_handler(unsigned long data) 
2024 {
2025          hrt_t* dev = (hrt_t*)data;
2026          if(dev->timer_active){
2027                  tasklet_schedule(&dev->tasklet);
2028                  /* Schedule the timer to go off in another (HZ/100) jiffies */ 
2029                  dev->timer.expires = jiffies + (HZ/100);
2030                  add_timer(&dev->timer);
2031         }
2032 }
2033 
2034 /********************************************************************
2035  * hrt_irq_init
2036  *
2037  * Initialises the IRQs, if the device supports interrupts 
2038  */
2039 void hrt_irq_init(hrt_t* dev)
2040 {
2041          HRT_DEBUG_MSG(2, "hrt_irq_init");
2042          dev->irq_count = 0;
2043          if (dev->irq == 0) return;
2044          if ((dev->irq > 0) || (dev->mode & HRT_IRQ_MODE)) {
2045                   HRT_ERROR_MSG("irq handler already installed");               
2046                   return;
2047          }
2048          hrt_irq_disable(dev); /* insurance */
2049          if (request_irq(-dev->irq, hrt_irq_handler,
2050                          SA_SHIRQ, "hrt", (void*)dev)) {
2051                   HRT_ERROR_MSG("unable to reserve IRQ");
2052                   dev->irq = 0;
2053          } else {
2054                   dev->irq = -dev->irq;
2055                   dev->mode |= HRT_IRQ_MODE;
2056          }
2057 }
2058 
2059 /********************************************************************
2060  * hrt_irq_cleanup
2061  *
2062  * Cleanup the IRQs
2063  */
2064 void hrt_irq_cleanup(hrt_t* dev)
2065 {
2066          HRT_DEBUG_MSG(2, "hrt_irq_cleanup");
2067          hrt_irq_disable(dev); /* insurance */
2068          if (dev->mode & HRT_IRQ_MODE) {
2069                   free_irq(dev->irq, dev);
2070                   dev->mode &= ~HRT_IRQ_MODE;
2071          }
2072 }
2073 
2074 /*******************************************************************
2075  * hrt_timer_init
2076  *
2077  * If the device supports interrupts then initialise IRQs
2078  * else initialise the timer
2079  */
2080 void hrt_timer_init(hrt_t* dev)
2081 {
2082          HRT_DEBUG_MSG(1, "hrt_timer_init");
2083          HRT_CHECK(dev, HRT_INITIALIZING_STATE, "4");
2084          if (dev->timer_active) {
2085                   HRT_ERROR_MSG("irq or timer already active");
2086                   /* Commented by Sean & Atulya 2005.06.15
2087                      debugging irg
2088                   return; 
2089                   */
2090          }
2091          
2092          /* Added 15 june 2005, to add the functionality to use interrupts */
2093          hrt_irq_init(dev);
2094 
2095          if (!(dev->mode & HRT_IRQ_MODE)) {
2096                   if (dev->timer.function) {
2097                            HRT_ERROR_MSG("timer already initialized");
2098                            return;
2099                   }
2100                   HRT_DEBUG_MSG(1, "installing timer\n");
2101                   init_timer(&dev->timer);
2102                   dev->timer.function = hrt_timer_handler;
2103                   dev->timer.data = (unsigned long)dev;
2104          }
2105 }
2106 
2107 /********************************************************************
2108  * hrt_timer_cleanup
2109  *
2110  * Cleanup the timer / IRQ 
2111  */
2112 void hrt_timer_cleanup(hrt_t* dev)
2113 {
2114          HRT_DEBUG_MSG(1, "hrt_timer_cleanup");
2115          HRT_CHECK(dev, HRT_FINALIZING_STATE, "3");
2116          hrt_timer_deactivate (dev);
2117          /* Added by Sean/ Atulya 2005.06.15
2118             --- begin --- */
2119          tasklet_kill(&dev->tasklet);
2120          /* --- end --- */
2121          hrt_irq_cleanup(dev);
2122          dev->timer.function = NULL;
2123 }
2124 
2125 /********************************************************************
2126  * hrt_timer_deactivate
2127  *
2128  * If timer is running then deactivate it else disable the irqs.
2129  * The tasklet runs in both cases. So disable the tasklet
2130  */
2131 void hrt_timer_deactivate(hrt_t* dev)
2132 {
2133          HRT_DEBUG_MSG(1, "hrt_timer_deactivate");
2134          if (dev->timer_active) {
2135                   dev->timer_active = 0;
2136                   if (dev->mode & HRT_IRQ_MODE){
2137                            hrt_irq_disable(dev);
2138                   }
2139                   else 
2140                         del_timer_sync(&dev->timer);
2141                   
2142                   // Added 15 june 2005 
2143                   if (dev->tasklet_active) {
2144                            dev->tasklet_active = 0;
2145                            tasklet_disable(&dev->tasklet);      
2146                   }
2147         }
2148 }
2149 
2150 /********************************************************************/
2151 /* hrt_timer_activate 
2152  * 
2153  * Starts a task to monitor the state of the device.
2154  * This may be driven by a timer or by an interrupt
2155  * from the device.
2156 */
2157 
2158 int hrt_timer_activate(hrt_t* dev)
2159 {    
2160          int result = 0;
2161          HRT_DEBUG_MSG(1, "hrt_timer_activate");
2162 
2163          if (dev->timer_active) {
2164                   HRT_ERROR_MSG("irq or timer already active");
2165                   return 0;
2166          }
2167          dev->timer_active = 1;
2168          if (dev->mode & HRT_IRQ_MODE) {
2169                   HRT_DEBUG_MSG(1, "enabling irq");
2170                   if (!dev->tasklet_active) {
2171                            dev->tasklet_active = 1;
2172                            tasklet_enable(&dev->tasklet);
2173                   }
2174                   hrt_irq_enable(dev);
2175          } else {
2176                   if (!dev->timer.function) {
2177                            HRT_ERROR_MSG("timer not initialized");
2178                            return -1;
2179                   }
2180                   printk("Enabling the tasklet inside the timer_activate\n");  
2181                   if (!dev->tasklet_active) {
2182                           dev->tasklet_active = 1;
2183                             tasklet_enable(&dev->tasklet);
2184                   }
2185                   dev->timer.expires = jiffies + HZ/100;
2186                   add_timer(&dev->timer);       
2187          }
2188          return result;
2189 }
2190 
2191 /********************************************************************
2192  * hrt_tasklet
2193  *
2194  * The tasklet is the core of the module
2195  * In both IRQ and Timer 'mode' finally the tasklet
2196  * performs the required function
2197  *
2198  * For the irq mode we know that every invocation we have 
2199  * a field change
2200  * But for the timer mode, we check every time to see if the
2201  * field_id has changed 
2202  *
2203  */
2204 void hrt_tasklet(unsigned long data)
2205 { 
2206          int new_field;
2207          hrt_t* dev = (hrt_t*)data;
2208 
2209          if (dev->state != HRT_OPEN_STATE)  return;
2210 
2211          if (hrt_trylock (dev)) { /* device is busy */
2212                   return;
2213          }
2214 
2215          /* Get the current value of the field bit */ 
2216          new_field = hrt_get_field (dev);
2217 
2218          if (dev->field_id == -1) {
2219                   /* just started; don't know previous state */
2220                   dev->field_id = new_field;
2221                   goto done;
2222          }
2223 
2224          /* We need to do something only if the field bit has changed from 
2225           * the last value. This would indicate that the field has changed
2226           * from what we read in the last timer execution.
2227           * 
2228           * So now we need to take some action if we detect the field change
2229           */
2230         
2231 
2232          /* CASE 1 - NO IRQs. TIMER RUNNING EVERY HZ/100 JIFFIES */ 
2233          if (!(dev->mode & HRT_IRQ_MODE)) {
2234                   if (dev->streaming) {
2235                            /* If we have streaming running, then call the function
2236                             * responsible for updating the streaming display
2237                             *
2238                             * Differant implementations of streaming 
2239                             * for color and grey scale follow
2240                             */
2241                            if ((dev->mode & HRT_COLOR_MODE) || !(dev->mode & HRT_DUAL_PORTED_MODE)){     
2242                                     /* if we are in the color mode, we follow differant states
2243                                      * 
2244                                      * State 0 
2245                                      *
2246                                      * device goes live
2247                                      * state changes to 1
2248                                      *
2249                                      * State 1 
2250                                      * 
2251                                      * detect 2 field changes
2252                                      * issue freeze_next command
2253                                      * move to state 2
2254                                      *
2255                                      * State 2
2256                                      * 
2257                                      * detect 2 field changes
2258                                      * call the streaming_framechange function
2259                                      * to read the current frame
2260                                      * move back to state 0
2261                                      */
2262                                     if (dev->streaming_state == 0){
2263                                              hrt_printk("State 0\n");
2264                                              if(dev->is_frozen){
2265                                                       hrt_printk("HRT_GO_LIVE\n");
2266                                                       hrt_go_live(dev);
2267                                              }
2268                                              else 
2269                                                       hrt_printk ("THIS IS AN ERROR\n");
2270                                              dev->streaming_state = 1;
2271                                              dev->field_changes = 2;
2272                                     }
2273                                     else if (dev->streaming_state == 1){
2274                                              hrt_printk("State 1 dev->field_changes = %d\n", dev->field_changes);
2275                                              new_field = hrt_get_field(dev);
2276                                              if (new_field != dev->field_id){
2277                                                       dev->field_id = new_field;
2278                                                       if(dev->field_changes > 0) dev->field_changes--;
2279                                                       if (dev->field_changes == 0){
2280                                                                dev->streaming_state = 2;
2281                                                                dev->field_changes = 2;
2282                                                                hrt_printk("HRT_FREEZE_NEXT\n");
2283                                                                hrt_freeze_next(dev);
2284                                                       }
2285                                              }
2286                                     }
2287                                     else if (dev->streaming_state == 2){
2288                                              hrt_printk("State 2 dev->field_changes = %d\n", dev->field_changes);
2289                                              new_field = hrt_get_field(dev);
2290                                              if (new_field != dev->field_id){
2291                                                       dev->field_id = new_field;
2292                                                       if(dev->field_changes > 0) dev->field_changes--;
2293                                                       if (dev->field_changes == 0){
2294                                                                dev->streaming_state = 0;
2295                                                                streaming_fieldchange_color(dev);
2296                                                       }
2297                                              }
2298                                     }
2299                            }
2300                            else  {
2301                                     /* Streaming + Grey scale mode 
2302                                     *
2303                                     * This one not as complicated as the color function
2304                                     * Just read the current available field
2305                                     * whenever there is a field change
2306                                     */ 
2307                                     if (new_field != dev->field_id) {
2308                                              dev->field_id = new_field;
2309                                              streaming_fieldchange(dev);
2310                                     }
2311                            }
2312                   }
2313                   else {
2314                            /* Not streaming. 
2315                             * We are in the read mode
2316                             * update the reader and let them know that another
2317                             * field is available. The reader always waits till we have read
2318                             * two fields. Thus he/she/it(?) needs to be notified 
2319                             * when we read two fields
2320                             */
2321                            if (new_field != dev->field_id) {
2322                                     dev->field_id = new_field;
2323                                     if (dev->field_changes >0) dev->field_changes--; 
2324                                     wake_up_interruptible(&dev->wait_queue);
2325                            }
2326                   }
2327          }
2328          else {
2329          /* CASE 2 - IRQs ENABLES. AN INTERRUPT RAISED WHENEVER THE FIELD BIT CHANGES */
2330                   if (dev->streaming) {
2331                            /* If we have streaming running, then call the function
2332                             * responsible for updating the streaming display
2333                             *
2334                             * Differant implementations of streaming 
2335                             * for color and grey scale follow
2336                             */
2337                            if ((dev->mode & HRT_COLOR_MODE) || !(dev->mode & HRT_DUAL_PORTED_MODE)){     
2338                                     /* if we are in the color mode, we follow differant states
2339                                      * 
2340                                      * State 0 
2341                                      *
2342                                      * device goes live
2343                                      * state changes to 1
2344                                      *
2345                                      * State 1 
2346                                      * 
2347                                      * detect 2 field changes
2348                                      * issue freeze_next command
2349                                      * move to state 2
2350                                      *
2351                                      * State 2
2352                                      * 
2353                                      * detect 2 field changes
2354                                      * call the streaming_framechange function
2355                                      * to read the current frame
2356                                      * move back to state 0
2357                                      */
2358                                     if (dev->streaming_state == 0){
2359                                              hrt_printk("State 0\n");
2360                                              if(dev->is_frozen){
2361                                                       hrt_printk("HRT_GO_LIVE\n");
2362                                                       hrt_go_live(dev);
2363                                              }
2364                                              else 
2365                                                       hrt_printk ("THIS IS AN ERROR\n");
2366                                              dev->streaming_state = 1;
2367                                              dev->field_changes = 2;
2368                                     }
2369                                     else if (dev->streaming_state == 1){
2370                                              hrt_printk("State 1 dev->field_changes = %d\n", dev->field_changes);
2371                                              new_field = hrt_get_field(dev);
2372                                              if (new_field != dev->field_id){
2373                                                       dev->field_id = new_field;
2374                                                       if(dev->field_changes > 0) dev->field_changes--;
2375                                                       if (dev->field_changes == 0){
2376                                                                dev->streaming_state = 2;
2377                                                                dev->field_changes = 2;
2378                                                                hrt_printk("HRT_FREEZE_NEXT\n");
2379                                                                hrt_freeze_next(dev);
2380                                                       }
2381                                              }
2382                                     }
2383                                     else if (dev->streaming_state == 2){
2384                                              hrt_printk("State 2 dev->field_changes = %d\n", dev->field_changes);
2385                                              new_field = hrt_get_field(dev);
2386                                              if (new_field != dev->field_id){
2387                                                         dev->field_id = new_field;
2388                                                         streaming_fieldchange_color(dev);
2389                                              }
2390                                     }
2391                            }
2392                            else  {
2393                                     /* Streaming + Grey scale mode 
2394                                     *
2395                                     * This one not as complicated as the color function
2396                                     * Just read the current available field
2397                                     * whenever there is a field change
2398                                     */  
2399                                     dev->field_id = new_field;
2400                                     streaming_fieldchange_irq(dev);
2401                            }
2402                   }
2403                   else {
2404                            /* Not streaming. 
2405                             * We are in the read mode
2406                             * update the reader and let them know that another
2407                             * field is available. The reader always waits till we have read
2408                             * two fields. Thus he/she/it(?) needs to be notified 
2409                             * when we read two fields
2410                             */
2411                            dev->field_id = new_field;
2412                            if (dev->field_changes > 0) dev->field_changes--; 
2413                            wake_up_interruptible(&dev->wait_queue);
2414                   }
2415          }
2416              
2417 
2418  done:
2419          hrt_unlock(dev);
2420 }
2421 
2422 /********************************************************************
2423  * per_file_init 
2424  *
2425  * allocates and initializes per-file data, which
2426  * is currently just the ROI (region-of-interest) subwindow
2427  * and a pointer back to this hrtdev
2428  */
2429 struct hrt_per_file *per_file_init(hrt_t *hrtdev)
2430 {
2431          struct hrt_per_file *per_file = vmalloc(sizeof(*per_file));
2432 
2433          per_file->hrtdev = hrtdev;
2434          per_file->win.height = HRT_HEIGHT;
2435          if (hrtdev->mode & HRT_COLOR_MODE)
2436                   per_file->win.width = HRT_COLOR_WIDTH;
2437          else
2438                   per_file->win.width = HRT_GRAY_WIDTH;
2439          per_file->win.startx = 0;
2440          per_file->win.starty = 0;
2441 
2442          return per_file;
2443 }
2444 
2445 
2446 /********************************************************************/
2447 /**
2448  * hrt_open
2449  *
2450  * checks minor number range, sets private_data,
2451  * starts timer if necessary, increments users
2452  */
2453 int hrt_open(struct inode *inode, struct file *file)
2454 {
2455          unsigned int minor;
2456          int result;
2457          /* video device structure required to provide video4linux support */ 
2458          struct video_device *vfl = video_devdata(file);
2459          hrt_t *dev = vfl->priv;
2460         
2461          result = 0;
2462          minor = MINOR(inode->i_rdev);
2463          if (minor >= HRT_MAX_DEVICES) return -ENODEV;
2464 
2465          dev = hrt_devices + minor;
2466          HRT_DEBUG_MSG(1, "opening device %d at addr %lX", minor, (unsigned long)dev->phys_addr);
2467 
2468          /* Cannot open if device is not in closed state */
2469          if (dev->state != HRT_CLOSED_STATE) {
2470                   HRT_DEBUG_MSG(2, "already open");
2471                   return -EBUSY;
2472          }
2473          /* Now we set the private data for the device file
2474           * this is in the form of a structure hrt_per_file
2475           * that consists of a hrt_t struct and a subwindow struct
2476           */
2477          HRT_DEBUG_MSG(2, "setting private data");
2478          file->private_data = per_file_init(dev);
2479 
2480          /* Set device state to OPEN */
2481          dev->state = HRT_OPEN_STATE;
2482 
2483          /* The device opens in the non streaming mode by default */
2484          dev->streaming = 0;
2485 
2486          /* Added 13 June 2005 */
2487          dev->streaming_state = 0;
2488 
2489          /* Read the field bit and assign to the field_id */
2490          dev->field_id = hrt_get_field(dev);
2491         
2492          /* Activate the timer */
2493          HRT_DEBUG_MSG(2, "installing timer/irq");
2494          result = hrt_timer_activate(dev); 
2495 
2496          return result;
2497 }
2498 
2499 /********************************************************************/
2500 /* hrt_release
2501  *
2502  * hrt_release should not need any lock, because
2503  it is only called by the system, on last close; at that
2504  point there should be no possibility of more calls that
2505  touch this device, unless they are from a timer
2506  or interrrupt handler 
2507 */
2508 
2509 int hrt_release(struct inode *inode, struct file *file)
2510 {
2511          struct video_device *vfl = video_devdata(file);
2512          hrt_t *dev = vfl->priv;
2513          
2514          hrt_printk( " hrt_release\n");
2515          if (dev->is_locked) {
2516                   hrt_unlock(dev);
2517          }
2518          if (dev->state != HRT_OPEN_STATE) return -ENODEV;
2519          dev->state = HRT_CLOSED_STATE;
2520          hrt_timer_deactivate(dev);
2521  
2522          /* Free our private data */
2523          vfree(file->private_data);
2524          return 0;
2525 }
2526 
2527 /********************************************************************/
2528 /* hrt_poll 
2529  *
2530  * handles poll() and select() on /dev/video<n>
2531  */
2532 unsigned int hrt_poll(struct file *file, poll_table *wait)
2533 {
2534          struct hrt_per_file *per_file = file->private_data;
2535          hrt_t *hrtdev = per_file->hrtdev;
2536 
2537          if (!hrtdev->streaming) {
2538                   poll_wait(file, &hrtdev->wait_queue, wait);
2539          } else {
2540                   /* Go to sleep if the done list is empty */
2541                   while (!hrtdev->done_list.length) {
2542                            up(&hrtdev->sem);
2543                            if (wait_event_interruptible
2544                                (hrtdev->wait_queue, (hrtdev->done_list.length)))
2545                                     return -ERESTARTSYS;
2546 
2547                            if (down_interruptible(&hrtdev->sem))
2548                                     return -ERESTARTSYS;
2549                   }
2550          }
2551 
2552          return POLLIN | POLLRDNORM;
2553 }
2554 
2555 
2556 
2557 /********************************************************************
2558  * hrt_read
2559  *
2560  * Does a blocking read and return count number of bytes back to the user
2561  * Differant implementations for color/grey scale/single ported/dual ported
2562  */
2563 int hrt_read(struct file *file, char *buf, size_t count, loff_t * ppos)
2564 {
2565          int max_count;
2566          
2567          /* atulya/sean - to measure the frame rate
2568           * record the jiffies at this time
2569           * then find the jiffies at the time the function returns
2570           * the differance gives the time taken to read one frame
2571           * and thus the frame rate
2572           */
2573          unsigned int starttime;
2574          
2575          int old_field;
2576          struct video_device *vfl = video_devdata(file);
2577          hrt_t *dev = vfl->priv;
2578 
2579          HRT_DEBUG_MSG(3, "hrt_read count = %d", count);
2580          if (dev->state != HRT_OPEN_STATE)  return -ENODEV;
2581 
2582 
2583          //hrt_printk( "hrt_read: (start) jiffies = %ld\n", jiffies);
2584          starttime = jiffies;
2585 
2586          if (dev->mode & HRT_COLOR_MODE) {
2587                  /* First implementation - COLOR device
2588                   * 
2589                   * These ones are single ported so
2590                   * need to wait till the entire field gets digitized before we can read it
2591                   * This is a conservative approach..and wastes an extra frame just to make 
2592                   * sure that we get the correct frame boundary.
2593                   * Can be tweaked to make it faster
2594                   */
2595                   hrt_lock(dev);
2596                   dev->field_changes = 2;
2597                   if (dev->is_frozen) {
2598                            hrt_go_live (dev);
2599                            hrt_unlock(dev);
2600                            /* Go live 
2601                             * and
2602                             * wait for two field changes
2603                             */
2604                            if (wait_event_interruptible(dev->wait_queue, dev->field_changes == 0)) {
2605                                     return -ERESTARTSYS;
2606                            }
2607                            hrt_lock(dev);
2608                            dev->field_changes = 2;
2609                   }
2610                   hrt_freeze_next(dev);
2611                   hrt_unlock(dev);
2612                   /* Now we know that we are at a frame bondary
2613                    * Wait for 2 field changes
2614                    * and at that time we can read both fields as one frame
2615                    */
2616                   if (wait_event_interruptible(dev->wait_queue, dev->field_changes == 0)) {
2617                            return -ERESTARTSYS;
2618                   }
2619                   /* Cannot return more bytes than what the device sends to us
2620                    * Check for that */
2621                   max_count = dev->win->width * dev->win->height * dev->bytes_per_pixel;
2622                   if (count > max_count) count = max_count;
2623                   
2624                   if (down_interruptible(&dev->sem))
2625                            return -ERESTARTSYS;
2626 
2627                   old_field = dev->field_id;
2628                   
2629                   /* Grab a field */
2630                   grab_field(dev, dev->framedata, old_field);
2631 
2632                   /* Grab the other field */
2633                   grab_field(dev, dev->framedata,(!old_field) );
2634          }
2635          else {
2636                  /* Implementation 2 - GREY SCALE DULA ported device
2637                   *
2638                   * These devices are dual ported so we can
2639                   * read at a faster rate
2640                   * Dont need the extra checking required in the 
2641                   * case of single ported devices.
2642                   * Results in a faster rate
2643                   *
2644                   * Just grab one field,
2645                   * wait for a field change
2646                   * and grab the other field
2647                   */
2648                   if (dev->mode & HRT_DUAL_PORTED_MODE) {
2649                            max_count = dev->win->width * dev->win->height * dev->bytes_per_pixel;
2650                            if (count > max_count) count = max_count;
2651                            down_interruptible(&dev->sem);
2652                            old_field = dev->field_id;
2653                            
2654                            /* Grab a field */
2655                            grab_field(dev, dev->framedata, old_field);
2656                            
2657                            /* Go to sleep until the field bit changes */
2658                            while (old_field == dev->field_id) {
2659                                     up(&dev->sem);
2660                                     if (file->f_flags & O_NONBLOCK)
2661                                              return -EAGAIN;
2662                                     
2663                                     if (wait_event_interruptible
2664                                         (dev->wait_queue, (old_field != dev->field_id)))
2665                                              return -ERESTARTSYS;
2666                                     
2667                                     if (down_interruptible(&dev->sem))
2668                                              return -ERESTARTSYS;
2669                            }
2670                            
2671                            /* Grab the other field */
2672                            grab_field(dev, dev->framedata, dev->field_id);
2673                   }
2674                   else {
2675                           /* Imlementation 3 - GREYSCALE SINGLE ported device
2676                            *
2677                            * Again similar implementation as the color devices 
2678                            */
2679                            hrt_lock(dev);
2680                            dev->field_changes = 2;
2681                            if (dev->is_frozen) {
2682                                     hrt_go_live (dev);
2683                                     hrt_unlock(dev);
2684                                     if (wait_event_interruptible(dev->wait_queue, dev->field_changes == 0)) {
2685                                              return -ERESTARTSYS;
2686                                     }
2687                                     hrt_lock(dev);
2688                                     dev->field_changes = 2;
2689                            }
2690                            hrt_freeze_next(dev);
2691                            hrt_unlock(dev);
2692                            if (wait_event_interruptible(dev->wait_queue, dev->field_changes == 0)) {
2693                                     return -ERESTARTSYS;
2694                            }
2695                            
2696                            max_count = dev->win->width * dev->win->height * dev->bytes_per_pixel;
2697                            if (count > max_count) count = max_count;
2698                            
2699                            if (down_interruptible(&dev->sem))
2700                                     return -ERESTARTSYS;
2701                            
2702                            old_field = dev->field_id;
2703                            
2704                            /* Grab a field */
2705                            grab_field(dev, dev->framedata, old_field);
2706                            
2707                            /* Grab the other field */
2708                            grab_field(dev, dev->framedata,(!old_field) );                          
2709                   }
2710          }
2711          
2712         /* Both returned fields have been stored in their corresponding
2713          * location inside the dev->framedata buffer
2714          * Return to the user
2715          */
2716          if (copy_to_user(buf, dev->framedata, count)) {
2717                   up(&dev->sem);
2718                   return -EFAULT;
2719          }
2720          /* Clear the buffer */
2721          if (dev->mode & HRT_COLOR_MODE)
2722                   memset(dev->framedata, 0, HRT_COLOR_FRAMESIZE);
2723          else
2724                   memset(dev->framedata, 0, HRT_GRAY_FRAMESIZE);
2725 
2726         
2727          up(&dev->sem);
2728          /*  (1/ (time taken to read one frame)) = frame rate */
2729          hrt_printk( " Frame rate = %d\n", (int)( HZ / (jiffies-starttime) ) );
2730          return count;
2731 }
2732 
2733 /********************************************************************
2734  *
2735  * v4l1_ioctls - used for printing out ioctl codes in hrt_do_ioctl
2736  */
2737 static const char *v4l1_ioctls[] = {
2738          "?", "CGAP", "GCHAN", "SCHAN", "GTUNER", "STUNER", "GPICT",
2739          "SPICT", "CCAPTURE", "GWIN", "SWIN", "GFBUF", "SFBUF", "KEY", "GFREQ",
2740          "SFREQ", "GAUDIO", "SAUDIO", "SYNC", "MCAPTURE", "GMBUF", "GUNIT",
2741          "GCAPTURE", "SCAPTURE", "SPLAYMODE", "SWRITEMODE", "GPLAYINFO",
2742          "SMICROCODE", "GVBIFMT", "SVBIFMT"
2743 };
2744 
2745 
2746 /********************************************************************
2747  *
2748  * hrt_do_ioctl - handles ioctl's on /dev/video<n>
2749  */
2750 static int hrt_do_ioctl(struct inode *inode, struct file *file,
2751                         unsigned int cmd, void *arg)
2752 {
2753          struct hrt_per_file *per_file = file->private_data;
2754          hrt_t *hrtdev = per_file->hrtdev;
2755          hrtdev->win = &per_file->win;
2756 
2757          /* This nice code copied from xawtv's libng.
2758             It prints out the ioctl's that are done.
2759          */
2760          switch (_IOC_TYPE(cmd)) {
2761          case 'v':
2762                   dprintk("ioctl 0x%x (v4l1, VIDIOC%s)\n",
2763                           cmd, (_IOC_NR(cmd) < ARRAY_SIZE(v4l1_ioctls)) ?
2764                           v4l1_ioctls[_IOC_NR(cmd)] : "???");
2765                   break;
2766          case 'V':
2767                   dprintk("ioctl 0x%x (v4l2, %s)\n",
2768                           cmd, v4l2_ioctl_names[_IOC_NR(cmd)]);
2769                   break;
2770          default:
2771                   dprintk("ioctl 0x%x (?)\n", cmd);
2772          }
2773 
2774          switch (cmd) {
2775          case IOC_HRT_FREEZE_FRAME:
2776                   HRT_DEBUG_MSG(2, "IOC_HRT_FREEZE_FRAME: called");
2777                   hrt_freeze_next(hrtdev);
2778                   break;
2779 
2780          case IOC_HRT_GO_LIVE:
2781                   HRT_DEBUG_MSG(2, "IOC_HRT_GO_LIVE: called");
2782                   hrt_go_live(hrtdev);
2783                   break;
2784          case IOC_HRT_UPSIDE_DOWN:
2785                   HRT_DEBUG_MSG(2, "IOC_HRT_UPSIDE_DOWN: called");
2786                   if (hrtdev->upside_down)
2787                         hrtdev->upside_down = 0;
2788                   else
2789                         hrtdev->upside_down = 1;
2790                   break;
2791 
2792                   /* Streaming ioctl's */
2793          case VIDIOC_REQBUFS: {
2794                   struct v4l2_requestbuffers *req = arg;
2795 
2796                   if (hrtdev->stream_buffers_mapped) {
2797                            hrt_printk("REQBUFS - Can't request buffers if "
2798                                       " buffers are already mapped\n");
2799                            return -EPERM;
2800                   }
2801                   if (!mmap_request_buffers(hrtdev, req)) {
2802                            hrt_printk("REQBUFS - Request of buffers failed\n");
2803                            return -EINVAL;
2804                   }
2805                   return 0;
2806          }
2807          case VIDIOC_QUERYBUF: {
2808                   struct v4l2_buffer *buf =
2809                            (struct v4l2_buffer *) arg;
2810                   int i;
2811                   i = buf->index;
2812 
2813 
2814                   if (i < 0 || i >= MAX_CAPTURE_BUFFERS ||
2815                       !hrtdev->stream_buf[i].requested ||
2816                       (buf->type & V4L2_BUF_TYPE_VIDEO_CAPTURE) !=
2817                       (hrtdev->stream_buf[i].vidbuf.type & V4L2_BUF_TYPE_VIDEO_CAPTURE)) {
2818                            hrt_printk("QUERYBUF - bad parameter\n");
2819                            return -EINVAL;
2820                   }
2821 
2822                   *buf = hrtdev->stream_buf[i].vidbuf;
2823                   return 0;
2824          }
2825          case VIDIOC_QBUF: {
2826                   struct v4l2_buffer *buf =
2827                            (struct v4l2_buffer *) arg;
2828 
2829                   if (!hrtdev->stream_buffers_mapped) {
2830                            return -EINVAL;
2831                   }
2832 
2833                   if (!hrt_queuebuffer(hrtdev, buf)) {
2834                            return -EINVAL;
2835                   }
2836                   return 0;
2837          }
2838          case VIDIOC_DQBUF: {
2839                   struct v4l2_buffer *buf =
2840                            (struct v4l2_buffer *) arg;
2841 
2842                   if (!hrt_dequeuebuffer(hrtdev, buf)) {
2843                            return -EINVAL;
2844                   }
2845                   return 0;
2846          }
2847          case VIDIOC_STREAMON: {
2848                   __u32 *type = (__u32 *) arg;
2849                   if (!hrt_streamon(hrtdev, *type))
2850                            return -EINVAL;
2851                   return 0;
2852          }
2853          case VIDIOC_STREAMOFF: {
2854                   __u32 *type = (__u32 *) arg;
2855                   hrt_streamoff(hrtdev, *type);
2856                   return 0;
2857          }
2858 
2859                   /* Non-streaming ioctl's */
2860          case VIDIOC_QUERYCAP: {
2861                   struct v4l2_capability *b =
2862                            (struct v4l2_capability *) arg;
2863 
2864                   strcpy(b->driver, "hrt");
2865                   strncpy(b->card, "PS 512-8-PCI", sizeof(b->card));
2866                   sprintf(b->bus_info,"PCI:%s", hrtdev->pci_dev->slot_name);
2867                   b->version = KERNEL_VERSION(0, 0, 2);
2868 
2869                   if (disable_streaming) {
2870                            b->capabilities =
2871                                     V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE;
2872                   } else {
2873 
2874 
2875                            b->capabilities =
2876                                     V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
2877                                     V4L2_CAP_STREAMING;
2878                   }
2879                   return 0;
2880          }
2881          case VIDIOC_ENUM_FMT: {
2882                   struct v4l2_fmtdesc *f = arg;
2883                   enum v4l2_buf_type type = f->type;
2884                   int index = f->index;
2885 
2886                   /* There's only one format */
2887                   if (index > 0)
2888                            return -EINVAL;
2889 
2890                   if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
2891                            memset(f, 0, sizeof(*f));
2892                            f->index = index;
2893                            f->type = type;
2894                            if(hrtdev->mode & HRT_COLOR_MODE){
2895                                     f->pixelformat = V4L2_PIX_FMT_RGB555; //check this one
2896                                     strcpy(f->description, "Color");
2897                            }
2898                            else{
2899                                     f->pixelformat = V4L2_PIX_FMT_GREY;
2900                                     strcpy(f->description, "Grey");
2901                            }
2902 
2903                            return 0;
2904                   } else {
2905                            return -EINVAL;
2906                   }
2907          }
2908          case VIDIOC_TRY_FMT:
2909          case VIDIOC_S_FMT:
2910          case VIDIOC_G_FMT: {
2911                   struct v4l2_format *f = arg;
2912 
2913                   if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
2914                         
2915                            memset(&f->fmt.pix, 0,
2916                                   sizeof(struct v4l2_pix_format));
2917                            f->fmt.pix.width = hrtdev->win->width;
2918                            f->fmt.pix.height = hrtdev->win->height;
2919                         
2920                            if(hrtdev->mode & HRT_COLOR_MODE)
2921                                     f->fmt.pix.pixelformat = V4L2_PIX_FMT_RGB555;
2922                            else
2923                                     f->fmt.pix.pixelformat = V4L2_PIX_FMT_GREY;
2924                         
2925                            f->fmt.pix.bytesperline = hrtdev->bytesperline;
2926                            f->fmt.pix.sizeimage = hrtdev->framesize;
2927                            hrt_printk("pix.width (%d), pic.height (%d)", 
2928                                       f->fmt.pix.width, f->fmt.pix.height);
2929                            hrt_printk("pix.bytesperline (%d), pic.sizeimage (%d)", 
2930                                       f->fmt.pix.bytesperline, f->fmt.pix.sizeimage);
2931                            return 0;
2932                   } else {
2933                            return -EINVAL;
2934                   }
2935          }
2936 
2937          case VIDIOC_G_CROP: {
2938                   struct v4l2_crop * win = arg;
2939                  
2940                   win->c.height = hrtdev->win->height;
2941                   win->c.width  = hrtdev->win->width;
2942                   win->c.top    = hrtdev->win->starty;
2943                   win->c.left   = hrtdev->win->startx;
2944 
2945                   return 0;              
2946          }
2947 
2948          case VIDIOC_S_CROP: {
2949                   struct v4l2_crop *win = arg;
2950                  
2951                   hrtdev->win->height = win->c.height;
2952                   hrtdev->win->width  = win->c.width;
2953                   hrtdev->win->starty = win->c.top;
2954                   hrtdev->win->startx = win->c.left;
2955 
2956                   return 0;              
2957 
2958          }
2959 
2960          case VIDIOC_G_STD: {
2961                   v4l2_std_id *id = arg;
2962 
2963                   *id = V4L2_STD_NTSC;
2964                   return 0;
2965          }
2966          case VIDIOC_S_STD: {
2967                   /* There's only one standard that we support, NTSC */
2968                   return 0;
2969          }
2970          case VIDIOC_QUERYCTRL: {
2971                   struct v4l2_queryctrl *c = arg;
2972                   int i;
2973 
2974                   for (i = 0; i < ARRAY_SIZE(hrt_ctls); i++)
2975                            if (hrt_ctls[i].id == c->id)
2976                                     break;
2977 
2978                   /* Didn't find the id */
2979                   if (i == ARRAY_SIZE(hrt_ctls)) {
2980                            return -EINVAL;
2981                   }
2982 
2983                   *c = hrt_ctls[i];
2984                   return 0;
2985          }
2986          case VIDIOC_G_CTRL: {
2987                   struct v4l2_control *c = arg;
2988                   int i;
2989 
2990                   for (i = 0; i < ARRAY_SIZE(hrt_ctls); i++)
2991                            if (hrt_ctls[i].id == c->id)
2992                                     break;
2993 
2994                   if (i == sizeof(hrt_ctls))
2995                            return -EINVAL;
2996 
2997                   if (c->id == V4L2_CID_BRIGHTNESS) {
2998                            /*
2999                              c->value = hrtdev->regvals[HRT_BRIGHTNESS_REG];
3000                            */
3001                            c->value = hrtdev->saa7110_registers[HRT_BRIGHTNESS_REG];
3002                   } else if (c->id == V4L2_CID_CONTRAST) {
3003                            /*
3004                              c->value = hrtdev->regvals[HRT_CONTRAST_REG];
3005                            */
3006                            c->value = hrtdev->saa7110_registers[HRT_BRIGHTNESS_REG];
3007 
3008                   } else {
3009                            return -EINVAL;
3010                   }
3011 
3012                   return 0;
3013          }
3014          case VIDIOC_S_CTRL: {
3015                   /*
3016                     struct v4l2_control *c = arg;
3017                     int i;
3018 
3019                     for (i = 0; i < sizeof(hrt_ctls); i++)
3020                     if (hrt_ctls[i].id == c->id)
3021                     break;
3022                     if (i == sizeof(hrt_ctls))
3023                     return -EINVAL;
3024 
3025                     if (c->id == V4L2_CID_BRIGHTNESS) {
3026                     if (c->value > 255)
3027                     return -EINVAL;
3028                     c->value = i2c_set_reg(hrtdev, HRT_BRIGHTNESS_REG,
3029                     c->value);
3030                     } else if (c->id == V4L2_CID_CONTRAST) {
3031                     if (c->value > 255)
3032                     return -EINVAL;
3033                     c->value = i2c_set_reg(hrtdev, HRT_CONTRAST_REG,
3034                     c->value);
3035                     } else {
3036                     return -EINVAL;
3037                     }
3038                   */
3039                   return 0;
3040          }
3041          case VIDIOC_ENUMINPUT: {
3042                   struct v4l2_input *i = arg;
3043                   unsigned int n;
3044 
3045                   /* Only one input */
3046                   if (i->index > 0)
3047                            return -EINVAL;
3048 
3049                   n = i->index;
3050                   memset(i, 0, sizeof(*i));
3051                   i->index = n;
3052                   i->type = V4L2_INPUT_TYPE_CAMERA;
3053                   sprintf(i->name, "NTSC Camera");
3054 
3055                   return 0;
3056          }
3057          case VIDIOC_ENUMSTD: {
3058                   struct v4l2_standard *e = arg;
3059                   struct v4l2_fract fract = { 1001, 30000 };
3060                   unsigned int index = e->index;
3061 
3062                   /* One standard (NTSC) */
3063                   if (index > 0)
3064                            return -EINVAL;
3065 
3066                   e->id = V4L2_STD_NTSC_M;
3067                   e->index = index;
3068                   strcpy(e->name, "NTSC");
3069                   e->frameperiod = fract;
3070                   e->framelines = hrtdev->win->height;
3071 
3072                   return 0;
3073          }
3074          case VIDIOC_G_PARM: {
3075                   struct v4l2_streamparm *parm = arg;
3076                   struct v4l2_standard s;
3077 
3078                   if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
3079                            return -EINVAL;
3080                   memset(parm, 0, sizeof(*parm));
3081 
3082                   v4l2_video_std_construct(&s, V4L2_STD_NTSC,
3083                                            "NTSC");
3084                   parm->parm.capture.timeperframe = s.frameperiod;
3085                   return 0;
3086          }
3087          case VIDIOC_G_INPUT: {
3088                   return 0;
3089          }
3090          case VIDIOC_S_INPUT: {
3091                   return 0;
3092          }
3093          default:
3094                   return -ENOIOCTLCMD;
3095          }
3096 
3097          return 0;
3098 }
3099 
3100 /********************************************************************
3101  * hrt_ioctl 
3102  *
3103  * handler for ioctl's on /dev/video<n>. Tries the private
3104  * ioctl's first, via hrt_do_private_ioctl().
3105  */
3106 int hrt_ioctl(struct inode *inode, struct file *file,
3107               unsigned int cmd, unsigned long arg)
3108 {
3109          struct hrt_per_file *per_file = file->private_data;
3110          hrt_t *hrtdev = per_file->hrtdev;
3111          int ret;
3112          hrtdev->win = &per_file->win;
3113 
3114          dprintk("ioctl arg = %lx\n", arg);
3115 
3116          down(&hrtdev->sem);
3117 
3118          ret = hrt_do_private_ioctl(hrtdev, cmd, arg);
3119          if (ret != -EINVAL) {
3120                   up(&hrtdev->sem);
3121                   return ret;
3122          }
3123          ret = video_usercopy(inode, file, cmd, arg, hrt_do_ioctl);
3124          up(&hrtdev->sem);
3125          return ret;
3126 }
3127 
3128 #ifdef CONFIG_PCI
3129 
3130 /***************
3131  * PCI support *
3132  ***************/
3133 
3134 /********************************************************************/
3135 MODULE_DEVICE_TABLE(pci, hrt_pci_tbl);
3136 int  hrt_pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *pci_id);
3137 void hrt_pci_remove (struct pci_dev *pci_dev);
3138 
3139 /********************************************************************/
3140 static struct pci_device_id hrt_pci_tbl[] __devinitdata = {
3141          {PCI_DEVICE(HRT_VENDOR_ID, HRT_DEVICE_ID_GREY)},
3142          {PCI_DEVICE(HRT_VENDOR_ID, HRT_DEVICE_ID_COLOR)},
3143          {0,}
3144 };
3145 
3146 /********************************************************************/
3147 static struct pci_driver hrt_pci_driver = {
3148          .name        = "hrt",
3149          .id_table = hrt_pci_tbl, 
3150          .probe    = hrt_pci_probe,
3151          .remove   = __devexit_p(hrt_pci_remove)
3152 };
3153 
3154 /********************************************************************/
3155 int  hrt_pci_probe(struct pci_dev *pci_dev,
3156                    const struct pci_device_id *pci_id)
3157 {
3158          HRT_DEBUG_MSG(2, "probing pci device");
3159 
3160          /* check that this is a type of device we support */
3161          if ((pci_dev->device != HRT_DEVICE_ID_COLOR) &&
3162              (pci_dev->device != HRT_DEVICE_ID_GREY)) {
3163                   HRT_ERROR_MSG("unknown device type 0x%hx",
3164                                 pci_dev->device);
3165                   return -ENODEV;
3166          }
3167 
3168          if (hrt_num_devices >= HRT_MAX_DEVICES) {
3169                   HRT_ERROR_MSG("need to increase HRT_MAX_DEVICES");
3170                   return -ENOMEM;
3171          }
3172        
3173 
3174          return hrt_init(pci_resource_start(pci_dev, 0), pci_dev);
3175 }
3176 
3177 /********************************************************************/
3178 /* since these cards are not intended to be hot-pluggable,
3179    we do not try to reuse hrt_t objects; we just use the remove
3180    operation for removal of the device driver module */
3181 
3182 void hrt_pci_remove (struct pci_dev *pci_dev)
3183 {
3184          hrt_t *dev;
3185          HRT_DEBUG_MSG(2, "hrt_pci_remove");
3186          dev = (hrt_t *) pci_get_drvdata (pci_dev);
3187          hrt_cleanup(dev);
3188 
3189          /* Added by Sean/ Atulya 2005.06.14
3190           * -- begin -- */
3191          video_unregister_device(&dev->video_dev);
3192          /* -- end -- */
3193 
3194          pci_disable_device(pci_dev);
3195 }
3196 
3197 /********************************************************************/
3198 void hrt_pci_init(void)
3199 { 
3200          HRT_DEBUG_MSG(2, "pci_register_driver");
3201          pci_register_driver(&hrt_pci_driver);
3202 }
3203 
3204 /********************************************************************/
3205 void hrt_pci_cleanup(void)
3206 {
3207          hrt_printk( " hrt_pci_cleanup\n");
3208          HRT_DEBUG_MSG(2, "pci_unregister_driver");
3209          pci_unregister_driver(&hrt_pci_driver);
3210 }
3211 
3212 #else
3213 
3214 /* no PCI support */
3215 
3216 /********************************************************************/
3217 void hrt_pci_init(void)
3218 {
3219 }
3220 
3221 /********************************************************************/
3222 void hrt_pci_cleanup(void)
3223 {
3224          hrt_printk( "  no pci support hrt_pci_cleanup\n");
3225 }
3226 
3227 #endif
3228 
3229 /*************************************
3230  * module initialization and cleanup *
3231  *************************************/
3232 
3233 int hrt_major_number = 0;
3234 
3235 /********************************************************************/
3236 void hrt_cleanup_module(void)
3237 {
3238          hrt_printk( "  initiating hrt_cleanup_module\n");
3239          HRT_MODULE_CHECK (HRT_MODULE_INITIALIZING_STATE |
3240                            HRT_MODULE_INITIALIZED_STATE, "6");
3241          hrt_module_state = HRT_MODULE_FINALIZING_STATE;
3242          HRT_DEBUG_MSG(2, "hrt_cleanup_module");
3243          hrt_printk( " calling hrt_isa_cleanup\n");
3244          hrt_isa_cleanup();
3245          hrt_printk( " calling hrt_pci_cleanup\n");
3246          hrt_pci_cleanup();
3247          hrt_printk( " unregistering the 'hrt' device\n");
3248          if (hrt_major_number) unregister_chrdev(hrt_major_number, "hrt");
3249          hrt_printk( " calling hrt_debug_cleanup\n");
3250          hrt_debug_cleanup();
3251          hrt_module_state = HRT_MODULE_UNINITIALIZED_STATE;
3252          hrt_printk( " cleanup completed\n");
3253 }
3254 
3255 /********************************************************************/
3256 int hrt_init_module(void)
3257 {
3258          int result = 0;
3259 
3260          hrt_module_state = HRT_MODULE_INITIALIZING_STATE;
3261          hrt_debug_init();
3262 
3263          /* Added 2005.06.11 Sean/ Atulya 
3264             begin */
3265          memset(hrt_devices, 0, sizeof(hrt_devices));
3266 
3267          /* use major number returned by system if no
3268             major number is specified by this module */
3269          if (major_number == 0) hrt_major_number = result;
3270          else hrt_major_number = major_number;
3271          HRT_ERROR_MSG("module initializing with major number %d",
3272                        hrt_major_number);
3273 
3274          /* detect ISA/PC104 devices, and PCI devices that are 
3275             jumpered to use the ISA/PC104 I/O address space */
3276          hrt_isa_init();
3277 
3278          hrt_pci_init();
3279 
3280          /* now detect regular PCI devices */
3281          if (hrt_num_devices == 0) {
3282                   HRT_ERROR_MSG("no hrt devices detected");
3283                   hrt_module_state = HRT_MODULE_UNINITIALIZED_STATE;
3284                   return -ENODEV;
3285          } else {
3286                   HRT_ERROR_MSG("found %d hrt devices", hrt_num_devices);
3287          }
3288          hrt_module_state = HRT_MODULE_INITIALIZED_STATE;
3289          return 0;
3290 }
3291 
3292 /********************************************************************/
3293 /**
3294  * hrt_vma_open - increments reference count
3295  */
3296 static void hrt_vma_open(struct vm_area_struct *vma)
3297 {
3298          struct video_device *vdev = video_devdata(vma->vm_file);
3299          hrt_t *hrtdev = vdev->priv;
3300          struct stream_buffer *buf;
3301 
3302          hrt_printk( "hrt_vma_open\n");
3303          if (hrtdev == NULL)
3304                   return;
3305          buf = mmap_stream_buffer_from_offset(hrtdev, vma->vm_pgoff);
3306          if (buf == NULL)
3307                   return;
3308          else {
3309                   hrt_printk("hrt_vma_open : buf allocated at (0x%lx)", (unsigned long)buf);
3310          }
3311          
3312          buf->vma_refcount++;
3313          
3314 }
3315 
3316 /********************************************************************/
3317 /**
3318  * hrt_vma_close - decrements reference count of a stream buffer
3319  */
3320 static void hrt_vma_close(struct vm_area_struct *vma)
3321 {
3322          struct video_device *vdev = video_devdata(vma->vm_file);
3323          hrt_t *hrtdev = vdev->priv;
3324          struct stream_buffer *buf;
3325 
3326          if (hrtdev == NULL)
3327                   return;
3328 
3329          buf = mmap_stream_buffer_from_offset(hrtdev, vma->vm_pgoff);
3330          buf->vma_refcount--;
3331 
3332          if (buf->vma_refcount > 0) {
3333                   return;
3334          }
3335          if (hrtdev->streaming) {
3336                   hrt_printk(KERN_WARNING "munmap() called while streaming\n");
3337                   hrt_streamoff(hrtdev, buf->vidbuf.type);
3338          }
3339          if (buf->vaddress != NULL) {
3340                   vfree(buf->vaddress);
3341                   buf->vaddress = NULL;
3342          }
3343          buf->vidbuf.flags = 0;
3344 
3345          if (hrtdev->stream_buffers_mapped > 0)
3346                   hrtdev->stream_buffers_mapped--;
3347 }
3348 
3349 /********************************************************************/
3350 /**
3351  * hrt_vma_nopage - calls kvirt_to_pa to convert the vaddress in the
3352  * stream buffer (indexed via the offset parameter to mmap()) to
3353  * a page number for access from userspace
3354  */
3355 struct page *hrt_vma_nopage(struct vm_area_struct *vma,
3356                             unsigned long address, int * type)
3357 {
3358          struct video_device *vdev = video_devdata(vma->vm_file);
3359          hrt_t *hrtdev = vdev->priv;
3360 
3361          struct stream_buffer *buf;
3362          unsigned long offset_into_buf;
3363          struct page *page;
3364 
3365          buf = mmap_stream_buffer_from_offset(hrtdev, vma->vm_pgoff);
3366          if (buf == NULL)
3367                   return 0;
3368          offset_into_buf = address - vma->vm_start;
3369          if (offset_into_buf >= buf->vidbuf.length) {
3370                   hrt_printk("Attempt to read past end of mmap() buffer\n");
3371                   return 0;
3372          }
3373          page = vmalloc_to_page(buf->vaddress + offset_into_buf);
3374          if (page != NULL)
3375                   atomic_inc(&page->_count);
3376          return page;
3377 }
3378 
3379 
3380 /********************************************************************/
3381 /**
3382  * hrt_vm_ops - vm operations on /dev/video<n>
3383  */
3384 struct vm_operations_struct hrt_vm_ops = {
3385          .open = hrt_vma_open,
3386          .close = hrt_vma_close,
3387          .nopage = hrt_vma_nopage,
3388 };
3389 
3390 
3391 /********************************************************************/
3392 int hrt_queuebuffer( hrt_t *hrtdev,
3393                      struct v4l2_buffer *vidbuf)
3394 {
3395          int i = vidbuf->index;
3396          struct stream_buffer *buf = NULL;
3397 
3398          if ( !(hrtdev->stream_buffers_mapped) ) {
3399                   return 0;
3400          }
3401          if (vidbuf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
3402                   hrt_printk("QBUF - wrong type (type = %x)\n", vidbuf->type);
3403                   return 0;
3404          }
3405          if (i < 0 || i >= MAX_CAPTURE_BUFFERS
3406              || !hrtdev->stream_buf[i].requested) {
3407                   hrt_printk("QBUF - buffer index %d is out of range\n", i);
3408                   return 0;
3409          }
3410          buf = &hrtdev->stream_buf[i];
3411 
3412          hrt_printk("hrt_queuebuffer : buf (0x%lx)", (unsigned long)buf);
3413 
3414          if (!(buf->vidbuf.flags & V4L2_BUF_FLAG_MAPPED)) {
3415                   hrt_printk("QBUF - buffer %d is not mapped\n", i);
3416                   return 0;
3417          }
3418          if ((buf->vidbuf.flags & V4L2_BUF_FLAG_QUEUED)) {
3419                   hrt_printk("QBUF - buffer %d is already queued\n", i);
3420                   return 0;
3421          }
3422          buf->vidbuf.flags &= ~V4L2_BUF_FLAG_DONE;
3423          queue_add_tail(buf, &hrtdev->capture_list);
3424          buf->vidbuf.flags |= V4L2_BUF_FLAG_QUEUED;
3425          return 1;
3426 }
3427 
3428 
3429 /********************************************************************/
3430 /**
3431  * hrt_dequeuebuffer - called by the DQBUF ioctl.
3432  * Returns a buffer from the done queue.
3433  */
3434 int hrt_dequeuebuffer(hrt_t *hrtdev,
3435                       struct v4l2_buffer *buf)
3436 {
3437          struct stream_buffer *newbuf;
3438          if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
3439                   hrt_printk("DQBUF - Wrong buffer type\n");
3440                   return 0;
3441          }
3442          newbuf = queue_del_head(&hrtdev->done_list);
3443          if (newbuf == NULL) {
3444                   hrt_printk("DQBUF - No buffers on done queue\n");
3445                   return 0;
3446          }
3447          newbuf->vidbuf.flags &= ~V4L2_BUF_FLAG_QUEUED;
3448          *buf = newbuf->vidbuf;
3449          
3450          return 1;
3451 }
3452 
3453 
3454 /********************************************************************/
3455 /**
3456  * mmap_request_buffers - called by the ioctl REQBUF to request buffers
3457  */
3458 int mmap_request_buffers(hrt_t *dev, struct v4l2_requestbuffers *req)
3459 {
3460          int i;
3461          u32 buflen;
3462          u32 type;
3463 
3464          if (req->count < 1)
3465                   req->count = 1;
3466          if (req->count > MAX_CAPTURE_BUFFERS)
3467                   req->count = MAX_CAPTURE_BUFFERS;
3468          type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
3469 
3470          /*  The buffer length needs to be a multiple of the page size  */
3471          buflen = (dev->framesize + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
3472          hrt_printk("Granting %d buffers, buflen (%d)\n", req->count, buflen);
3473 
3474          /* Now initialize the buffer structures. Don't allocate the
3475             buffers until they're mapped. */
3476          for (i = 0; i < req->count; i++) {
3477                   dev->stream_buf[i].requested = 1;
3478                   dev->stream_buf[i].vidbuf.index = i;
3479                   dev->stream_buf[i].vidbuf.type = type;
3480                   /* offset must be unique for each buffer, and a multiple
3481                      of PAGE_SIZE on 2.4.x  */
3482                   dev->stream_buf[i].vidbuf.m.offset = PAGE_SIZE * (i + 1);
3483                   dev->stream_buf[i].vidbuf.length = buflen;
3484                   dev->stream_buf[i].vidbuf.bytesused = 0;
3485                   dev->stream_buf[i].vidbuf.flags = 0;
3486                   /* XXX: should set timestamp? */
3487                   dev->stream_buf[i].vidbuf.sequence = 0;
3488                   dev->stream_buf[i].vma_refcount = 0;
3489                   dev->stream_buf[i].vaddress = NULL;
3490                   memset(&dev->stream_buf[i].vidbuf.timecode, 0,
3491                          sizeof(struct v4l2_timecode));
3492          }
3493          for (i = req->count; i < MAX_CAPTURE_BUFFERS; i++)
3494                   dev->stream_buf[i].requested = 0;
3495          dev->stream_buffers_requested = req->count;
3496 
3497          return 1;
3498 }
3499 
3500 /********************************************************************/
3501 /**
3502  * hrt_mmap - called by the mmap() system call on /dev/video<n>
3503  */
3504 int hrt_mmap(struct file *file, struct vm_area_struct *vma)
3505 {
3506          struct video_device *dev = video_devdata(file);
3507          hrt_t *hrtdev = dev->priv;
3508          struct stream_buffer *buf = NULL;
3509 
3510          down(&hrtdev->sem);
3511 
3512          hrt_printk("hrt_mmap\n");
3513 
3514          if (next_mmap_is_direct) {
3515                   int ret;
3516                   next_mmap_is_direct = 0;
3517                   ret = hrt_direct_mmap(file, vma);
3518                   up(&hrtdev->sem);
3519                   return ret;
3520          }
3521 
3522          buf = mmap_stream_buffer_from_offset(hrtdev, vma->vm_pgoff);
3523 
3524          if (buf == NULL) {
3525                   hrt_printk("mmap() - Invalid offset parameter\n");
3526                   up(&hrtdev->sem);
3527                   return -EINVAL;
3528          }
3529          if (buf->vidbuf.length != vma->vm_end - vma->vm_start) {
3530                   hrt_printk("mmap() - Bad length parameter\n");
3531                   up(&hrtdev->sem);
3532                   return -EINVAL;
3533          }
3534          if (!buf->requested) {
3535                   hrt_printk("mmap() - Buffer is not available for mapping\n");
3536                   up(&hrtdev->sem);
3537                   return -EINVAL;
3538          }
3539          if (buf->vidbuf.flags & V4L2_BUF_FLAG_MAPPED) {
3540                   hrt_printk("mmap() - Buffer is already mapped\n");
3541                   up(&hrtdev->sem);
3542                   return -EINVAL;
3543          }
3544          if (buf->vaddress != NULL)
3545                   vfree(buf->vaddress);
3546          /*
3547           * Allocate virtual memory. This memory is mapped to the
3548           * buffer in user space.
3549           */
3550          buf->vaddress = vmalloc(buf->vidbuf.length);
3551          if (buf->vaddress == NULL) {
3552                   hrt_printk("Could not allocate mmap() buffer\n");
3553                   up(&hrtdev->sem);
3554                   return -ENODEV;
3555          }
3556          else {
3557                   hrt_printk("Successfully allocated mmap() buffer\n");
3558          }
3559 
3560          buf->vidbuf.flags |= V4L2_BUF_FLAG_MAPPED;
3561          hrtdev->stream_buffers_mapped++;
3562          vma->vm_ops = &hrt_vm_ops;
3563          if (vma->vm_ops->open)
3564                   vma->vm_ops->open(vma);
3565          
3566          up(&hrtdev->sem);
3567          return 0;
3568 }
3569 
3570 /********************************************************************/
3571 /**
3572  * hrt_streamon - called by the STREAMON ioctl.
3573  */
3574 int hrt_streamon(hrt_t *hrtdev, __u32 type)
3575 {
3576          struct stream_buffer *buf;
3577 
3578          if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
3579                   printk("STREAMON - Wrong buffer type\n");
3580                   return 0;
3581          }
3582 
3583          /* Move any leftover done buffers to the free pool */
3584          while ((buf = queue_del_head(&hrtdev->done_list)))
3585                   buf->vidbuf.flags &= ~V4L2_BUF_FLAG_QUEUED;
3586 
3587          hrtdev->streaming = 1;
3588          hrt_printk("Streaming is turned on\n");
3589 
3590          return 1;
3591 }
3592 
3593 /********************************************************************/
3594 
3595 module_init(hrt_init_module);
3596 module_exit(hrt_cleanup_module);
3597 
3598 MODULE_LICENSE("GPL");
3599 
  This page was automatically generated by the LXR engine.