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_dev.c
  3  *
  4 
  5    WARNING:
  6    -------
  7    The current version of this code is incomplete.  Only the device
  8    probing and initialization code is believed to be correct.
  9 
 10    This is a bare-bones device driver for the PixelSmart512-8 (greyscale)
 11    and Video Gala (color) framegrabbers.  For more information on these
 12    devices, see http://www.pixelsmart.com.
 13 
 14    Unlike earlier drivers for these cards from FSU, this driver does *not*
 15    attempt to support the Video4Linux (V4L) API, nor does it use the generic
 16    Linux I2C support code.
 17 
 18    We have intentionally removed all dependencies of V4L, because:
 19 
 20    (1) This board is so basic that most of the V4L API (e.g.,
 21           tuning, audio) is not applicable..
 22    (2) At this time, the V4L API seems sufficiently unstable to cause
 23           us worries about backward and forward compatibility.
 24           That is, we don't want to have to worry about differences in V4L
 25           headers and kernel modules breaking this driver.
 26    (3) Users of this card for embedded applications do not want to
 27           waste kernel memory for the V4L code if they are not using it.
 28    (4) We don't know of any demand for using these cards with
 29           existing V4L applications.
 30 
 31    We have intentionally removed all dependecies on the Linux generic I2C
 32    core (i2c.h and i2c-dev.h) because:
 33 
 34    (1) The Linux generic i2c support code added both logical
 35           complexity and code size, and did not work reliably for this card.
 36    (2) The Linux I2C core has changed enough over time, and we expect it
 37           will change further.  We don't want to have to worry about such
 38           differences between versions breking this driver.
 39    (3) this card has enough idiosyncracies that there is very little potential
 40           reuse of code between this I2C bus and other I2C applications.
 41    (4) Users of this card for embedded applications do not want to
 42           waste kernel memory for the extra code.
 43 
 44                   -----------------------------------------
 45 
 46    This version does only supports blocking reads.
 47    I deleted the support for streaming, because it needs to be done
 48    differently for single-ported and dual-ported cards,
 49    and I did not have time to work out the best way to allow for
 50    both cases within one framework.
 51 
 52    Blocking read operation:
 53 
 54    1. Initiate digitization, and start the timer/handler if necessary.
 55    2. Wait for a frame to become available and frozen.
 56    3. Copy frame to user memory.
 57 
 58    Timer handler/Frame Interrupt Handler:
 59 
 60    Keep track of fields, and when a full frame is captured,
 61    freeze the card and unblock the reader at step (2) above.
 62 
 63    Locking rules for direct I/O access to the device:
 64 
 65    We cannot allow concurrent access to the device, lest
 66    it be confused by sequences of commands that are interleaved.
 67    Mutual exclusion is guaranteed as follows:
 68    
 69    (1) The holder of dev->spinlock can do I/O on the device.
 70    (2) The IRQ/timer handler uses spin_lock/unlock, and normally
 71        scheduled code uses spin_lock/unlock_irqsave/restore.
 72    (3) Since we don't want to keep interrupts disabled the whole
 73        time we copy data from the device, we use an additional
 74        variable, dev->is_locked, to keep the timer handler from
 75        touching the device while copying is going on from a
 76        process context.
 77 
 78 */
 79 
 80 #ifndef __KERNEL__
 81 #define __KERNEL__
 82 #endif
 83 
 84 #include <linux/config.h>
 85 #include <linux/delay.h>           /* udelay */
 86 #include <linux/errno.h>           /* error codes */
 87 #include <linux/file.h>
 88 #include <linux/fs.h>
 89 #include <linux/interrupt.h>
 90 #include <linux/ioport.h>
 91 #include <linux/kernel.h>
 92 #include <linux/mm.h>
 93 #include <linux/module.h>
 94 #include <linux/pci.h>
 95 #include <linux/proc_fs.h>
 96 #include <linux/sched.h>
 97 #include <linux/slab.h>
 98 #include <linux/spinlock.h>
 99 #include <linux/version.h>
100 #include <linux/config.h>
101 #include <linux/moduleparam.h>
102 #include <linux/interrupt.h>
103 #include <asm/io.h>
104 #include <asm/segment.h>
105 #include <asm/uaccess.h>
106 
107 #include "hrt.h"
108 
109 #define HRT_DEBUG
110 
111 #define HRT_ERROR_MSG(args...) do{printk("<1>hrt:  "); printk(args);\
112  printk("\n");}while(0)
113 
114 /*********************
115  * Module Parameters *
116  *********************/
117 
118 #ifndef module_param
119 #define hrt_parm(name, pstr, type, perm) MODULE_PARM(name, pstr)
120 #else
121 #define hrt_parm(name, pstr, type, perm) module_param(name, type, perm)
122 #endif
123 
124 static
125 int  major_number = 82;
126 hrt_parm(major_number, "i", int, 0);
127 
128 #ifndef HRT_MAX_DEVICES
129 #define HRT_MAX_DEVICES 4
130 #endif
131 
132 #ifndef HRT_IO_SIZE            
133 #define HRT_IO_SIZE            0x4000
134 #endif
135 
136 /**
137  * hrt_addresses - a list of possible jumper-selected addresses
138  *  jumper A on  = plug and play address (above one MB address)
139  *  jumper A off = hardwired to 0xdc000 or 0xd4000
140  *  jumper B on  = address 0xd4000 (ignored if jumper A is on) 
141  *  jumper B off = address 0xdc000 (ignored if jumper A is on) 
142  */
143 const unsigned long hrt_addresses[] = { 0xd4000, 0xdc000 };
144 
145 /***************************
146  * Card-specific constants *
147  ***************************/
148 
149 #define HRT_VENDOR_ID         0x0004
150 #define HRT_DEVICE_ID_GREY    0x0404
151 #define HRT_DEVICE_ID_COLOR   0x0408
152 
153 /* Number of registers on the board- checked in i2c_init() */
154 #define HRT_SAA7110_MAXREG 0x34
155 
156 /**
157  * HRT device descriptor
158  */
159 typedef struct {
160            int                     num;
161            int                     state;
162            /* minor device number, index in hrt_devices[] */
163            unsigned long           virt_addr;
164            unsigned long           phys_addr;
165            /* cannot be opened again until released */
166 
167            /* spinlock and is_locked control access to the device */
168            spinlock_t              spinlock;
169            int                     is_locked;
170            wait_queue_head_t       wait_queue;
171            struct timer_list       timer;
172            struct tasklet_struct   tasklet;
173            int                     timer_active;
174            /* timer_active != 0 iff timer or irq is active */
175            int                     irq;
176            /* irq != 0 if board supports interrupts
177                    = -irq if handler not installed
178                    = irq if handler is installed */
179            volatile
180            int                     irq_count;
181            volatile
182            int                     i2c_bits;
183            /* last values written to i2c */
184            char                    saa7110_registers[HRT_SAA7110_MAXREG+1];
185            /* video data format, and dependent values */
186            int                     mode;
187            int                     rows, cols, bytes_per_pixel;
188            int                     win_row, win_col, win_width, win_height;
189            /* current field being digitized */
190            int                     field;
191            /* how many field changes we are waiting for */
192            int                     field_changes;
193            /* the device is either frozen or being frozen */
194            int                     is_frozen;
195 #ifdef CONFIG_PCI
196            struct pci_dev          *pci_dev;
197 #endif
198 } hrt_t;
199 
200 /* values for field hrt_t->state */
201 #define HRT_UNINITIALIZED_STATE 1
202 #define HRT_INITIALIZING_STATE 2
203 #define HRT_CLOSED_STATE 4
204 #define HRT_OPEN_STATE 8
205 #define HRT_FINALIZING_STATE 16
206 
207 /* values for field hrt_t->mode */
208 #define HRT_DUAL_PORTED_MODE 1
209 #define HRT_COLOR_MODE 2
210 #define HRT_STREAMING_MODE 4
211 #define HRT_IRQ_MODE 8
212 #define HRT_ISA_MODE 16
213 
214 /* values for global hrt_module_state */
215 
216 #define HRT_MODULE_UNINITIALIZED_STATE 1
217 #define HRT_MODULE_INITIALIZING_STATE 2
218 #define HRT_MODULE_INITIALIZED_STATE 4
219 #define HRT_MODULE_FINALIZING_STATE 8
220 
221 int hrt_module_state = HRT_MODULE_UNINITIALIZED_STATE;
222 
223 int  hrt_nonpci_devices = 0;  /* number of non-pci devices detected */
224                               /* non-pci devices have lower numbers */
225 int  hrt_num_devices = 0;     /* total number of devices detected */
226 
227 #define HRT_IS_PCI(X) ((X) >= hrt_nonpci_devices)
228 
229 /* ??? consider dynamically allocating the device
230    objects as they are probed and detectg, and
231    using a linked list here instead of an array */
232 
233 hrt_t hrt_devices[HRT_MAX_DEVICES];
234 
235 
236 #ifdef HRT_DEBUG
237 /******************************
238  * optional debugging support *
239  ******************************/
240 
241 #define HRT_DEBUG_LEVEL 3
242 
243 #define HRT_CHECK(dev,states,msg) \
244   {if (dev->state & ~(states))\
245   {HRT_DEBUG_MSG(1, "* unexpected state 0x%2x (%s)", dev->state, msg);}}
246 
247 #define HRT_MODULE_CHECK(states,msg) \
248   {if (hrt_module_state & ~(states))\
249   {HRT_DEBUG_MSG(1, "* unexpected state 0x%2x (%s)", hrt_module_state, msg);}}
250 
251 #define HRT_DEBUG_MSG(level,args...) {if (level <= HRT_DEBUG_LEVEL)\
252  {printk("<1>hrt * "); printk(args); printk("\n");}}
253 
254 struct proc_dir_entry *hrt_proc_read_entry = NULL;
255 
256 #define write_buf(args...)         \
257            do { \
258            n = snprintf(buf, count, args); \
259            buf += n; \
260            count -= n; \
261            } while(0)
262 
263 int hrt_read_proc(char *buf, char **start, off_t offset,
264                            int count, int *eof, void *data)
265 {
266            int n, i;
267            int ips, tps, rps;
268            char *org_buf = buf;
269 
270            ips = 0;
271            tps = 0;
272            rps = 0;
273 
274            /* dont excede count bytes when writing to buf */
275            /* just write to buf as a normal ptr to a file */
276 
277            write_buf("dev  HZ/10    int   timer   read   int/s   timer/s   read/s\n");
278            for (i=0; i<HRT_MAX_DEVICES; i++) {
279              write_buf("%6i %6i %7i %9i %8i\n", i,
280                        hrt_devices[i].irq_count,
281                        ips, tps, rps);
282            }
283            *eof = 1;
284            return buf - org_buf;
285 }
286 
287 #define hrt_debug_init()\
288 { hrt_proc_read_entry = create_proc_read_entry("hrt0", 0, 0, hrt_read_proc, 0);}
289 
290 #define hrt_debug_cleanup()\
291 {if (hrt_proc_read_entry) remove_proc_entry("hrt", 0);}
292 
293 #else
294 /* hrt debugging is off */
295 
296 #define HRT_CHECK(dev,states,msg) do{}while(0)
297 #define HRT_MODULE_CHECK(states,msg) do{}while(0)
298 #define HRT_DEBUG_MSG(args...) do{}while(0)
299 #define hrt_debug_init() do{}while(0)
300 #define hrt_debug_cleanup() do{}while(0)
301 #endif
302 
303 /****************************
304  * low-level device control *
305  ****************************/
306 
307 /* I2C bits */
308 #define HRT_I2C_SCL   0x01
309 #define HRT_I2C_SDA   0x02
310 
311 #define HRT_CONTROL(addr) (addr + HRT_CONTROL_REG)
312 #define I2C_CONTROL(addr) (addr + HRT_I2C_REG)
313 #define I2C_BUSY(addr) (!(ioread8((void *) HRT_CONTROL(addr)) & 0x80))
314 
315 /* Bit 7 at 0x2000 (the HRT512-8 control register) tells whether
316  * the CPU is sending data across the I2C bus */
317 
318 #define hrt_freeze_next(dev) \
319         dev->is_frozen = 1;\
320         iowrite8(HRT_FREEZE_NEXT_CMD, (void *) (dev->virt_addr + HRT_CONTROL_REG))
321 #define hrt_freeze_immediate(dev) \
322         dev->is_frozen = 1;\
323         iowrite8(HRT_FREEZE_IMM_CMD, (void *) (dev->virt_addr + HRT_CONTROL_REG))
324 #define hrt_go_live(dev) \
325         dev->is_frozen = 0;\
326         iowrite8(HRT_LIVE_CMD, (void *) (dev->virt_addr + HRT_CONTROL_REG))
327 #define hrt_get_field(dev) \
328         ioread8((void *) (dev->virt_addr + HRT_CONTROL_REG)) & 0x1
329 #define hrt_i2c_delay() udelay(5)
330 
331 /* Unique I2C bus address of the SAA7110 (A/D) device */
332 #define HRT_AD_DEVICE_ID (128+16+8+4)
333 
334 const unsigned char saa7110_default_init_regs[] = {
335            94,                                 /* there are 94 bytes that follow */
336            0x00, 0x4c,                   /* increment delay (IDEL) */
337            0x01, 0x3c,                   /* HSY begin 50 Hz */
338            0x02, 0x0d,                   /* HSY stop 50 Hz */
339            0x03, 0xef,                   /* HCL begin 50 Hz */
340            0x04, 0xbd,                   /* HCL stop 50 Hz */
341            0x05, 0xf0,                   /* HSY after PHI1 50 Hz */
342            0x06, 0x00,                   /* luminance control */
343            0x07, 0x00,                   /* hue control */
344            0x08, 0xf8,                   /* colour killer threshold QUAM (PAL/NTSC) */
345            0x09, 0xf8,                   /* colour killer threshold SECAM */
346            0x0A, 0x60,                   /* PAL switch sensitivity */
347            0x0B, 0x50,                   /* SECAM switch sensitivity */
348            0x0C, 0x00,                   /* gain control chrominance */
349            0x0D, 0x86,                   /* standard/mode control */
350            /* 7 VTRC = 1  (VCR mode, not TV)
351                  6 XXX
352                  5 XXX
353                  4 XXX
354                  3 RTSE = 0  (PLIN switched to output)
355                  2 HRMV = 1  (HREF normal position)
356                  1 SSTB = 1  (status byte = 1)
357                  0 SECS = 0  (other standards, not SECAM) */
358            0x0E, 0x18,                   /* I/O and clock control */
359            0x0F, 0x90,                   /* control #1 */
360            0x10, 0x00,                   /* control #2 */
361            0x11, 0x2c,                   /* chrominance gain reference */
362            0x12, 0x7f,                   /* chrominance saturation */
363            0x13, 0x5e,                   /* luminance contrast */
364            0x14, 0x42,                   /* HSY begin 60 Hz */
365            0x15, 0x1a,                   /* HSY stop 60 Hz */
366            0x16, 0xff,                   /* HCL begin 60 Hz */
367            0x17, 0xda,                   /* HCL stop 60 Hz */
368            0x18, 0xf0,                   /* HSY after PHI1 60 Hz */
369            0x19, 0x9b,                   /* luminance brightness */
370            /*
371                  0x1A - not used
372                  0x1B - not used
373                  0x1C - not used
374                  0x1D - not used
375                  0x1E - not used
376                  0x1F - not used
377             */
378            0x20, 0x7c,                   /* analog control #1 */
379            0x21, 0x03,                   /* analog control #2 */
380            0x22, 0xd2,                   /* mixer control #1 */
381            0x23, 0x41,                   /* clamping level control 21 */
382            0x24, 0x80,                   /* clamping level control 22 */
383            0x25, 0x41,                   /* clamping level control 31 */
384            0x26, 0x80,                   /* clamping level control 32 */
385            0x27, 0x4f,                   /* gain control #1 */
386            0x28, 0xfe,                   /* white peak control */
387            0x29, 0x01,                   /* sync bottom control */
388            0x2A, 0xcf,                   /* gain control analog #2 */
389            0x2B, 0x0f,                   /* gain control analog #3 */
390            0x2C, 0x83,                   /* mixer control #2 */
391            0x2D, 0x01,                   /* integration value gain */
392            0x2E, 0x81,                   /* vertical blanking pulse set */
393            0x2F, 0x03,                   /* vertical blanking pulse reset */
394            0x30, 0x60,                   /* ADCs gain control */
395            0x31, 0x71,                   /* mixer control #3 */
396            0x32, 0x02,                   /* integration value white peak */
397            0x33, 0x8c,                   /* mixer control #4 */
398            0x34, 0x03,                   /* gain update level */
399 };
400 
401 /* 
402  *  sda = set data bit on I2C bus
403  *        to the value given by parameter high
404  */
405 static inline
406 void hrt_sda(hrt_t *dev, unsigned long addr, int high)
407 {
408            if (high) dev->i2c_bits |= HRT_I2C_SDA;
409            else         dev->i2c_bits &= ~HRT_I2C_SDA;
410            iowrite8(dev->i2c_bits, (void *) I2C_CONTROL(addr));
411            wmb();
412 }
413 
414 /* 
415  *  scl = set clock bit on I2C bus
416  *        to the value given by parameter high
417  */
418 static inline
419 void hrt_scl(hrt_t *dev, unsigned long addr, int high)
420 {
421            if (high) dev->i2c_bits |= HRT_I2C_SCL;
422            else         dev->i2c_bits &= ~HRT_I2C_SCL;
423            iowrite8(dev->i2c_bits, (void *) I2C_CONTROL(addr));
424            wmb();
425 }
426 
427 /* 
428  *  sda_scl = set data and clock bits on I2C bus
429  *            to the values given by parameters sda_high and scl_high
430  */
431 static inline
432 void hrt_sda_scl(hrt_t *dev, 
433                           unsigned long addr, int sda_high, int scl_high)
434 {
435            if (sda_high) dev->i2c_bits |= HRT_I2C_SDA;
436            else                dev->i2c_bits &= ~HRT_I2C_SDA;
437            if (scl_high) dev->i2c_bits |= HRT_I2C_SCL;
438            else                dev->i2c_bits &= ~HRT_I2C_SCL;
439            iowrite8(dev->i2c_bits, (void *) I2C_CONTROL(addr));
440            wmb();
441 }
442            
443 /* 
444  *  sda_read = read data bit from I2C control register
445  */
446 static inline
447 int hrt_sda_read(unsigned long addr)
448 { char c = ioread8((void *) I2C_CONTROL(addr));  return (c & HRT_I2C_SDA); }
449 
450 /* 
451  *  hrt_i2c_start = start I2C data transmission
452  */
453 static inline
454 void hrt_i2c_start(hrt_t *dev, unsigned long addr) 
455 { 
456            hrt_sda_scl(dev, addr, 0, 0);
457            hrt_i2c_delay();
458            hrt_sda(dev, addr, 1);
459            hrt_i2c_delay();
460            hrt_scl(dev, addr, 1);
461            hrt_i2c_delay();
462            hrt_sda(dev, addr, 0);
463            hrt_i2c_delay();
464            hrt_scl(dev, addr, 0);
465 }
466 
467 /* 
468  *  hrt_i2c_stop = end I2C data transmission
469  */
470 static inline
471 void hrt_i2c_stop(hrt_t *dev, unsigned long addr) 
472 { 
473            hrt_sda_scl(dev, addr, 0, 0);
474            hrt_i2c_delay();
475            hrt_scl(dev, addr, 1);
476            hrt_i2c_delay();
477            hrt_sda(dev, addr, 1);
478            hrt_i2c_delay();
479            hrt_scl(dev, addr, 0);
480            hrt_scl(dev, addr, 1);
481 }
482 
483 /* 
484  *  hrt_i2c_send_bit
485  */
486 static 
487 int hrt_i2c_send_bit(hrt_t *dev, 
488                      unsigned long addr, unsigned char bit)
489 {
490         unsigned long timeout;
491         if (bit) hrt_sda(dev, addr, 1);
492         else        hrt_sda(dev, addr, 0);
493         hrt_i2c_delay();
494         iowrite8(dev->i2c_bits | 0x04, (void *) I2C_CONTROL(addr));
495         wmb();
496         hrt_i2c_delay();
497         if (I2C_BUSY(addr)) {
498                 timeout = jiffies + HZ/10;
499                 while (I2C_BUSY(addr)) {
500                         if (jiffies > timeout) {
501                                 HRT_ERROR_MSG("i2c bus timeout");
502                                 return -1;
503                         }
504                 }
505         }                        
506         return 0;
507 }
508 
509 /* 
510  *  hrt_i2c_send_byte
511  */
512 static
513 int hrt_i2c_send_byte(hrt_t *dev, unsigned long addr, unsigned char data)
514 {
515            char bitpos, bit;
516            for(bitpos = 0; bitpos < 8; bitpos++) {
517                          bit = (data & 0x80) >> 7;
518                          data <<= 1;
519                          if(hrt_i2c_send_bit(dev, addr, bit)) goto failure;
520            }
521            hrt_i2c_delay();
522            hrt_sda_scl(dev, addr, 1, 0);
523            hrt_scl(dev, addr, 1);  /* leave clock high */
524            udelay(10);
525            if (hrt_sda_read(addr)) {
526                          HRT_ERROR_MSG("no i2c ack");
527                          goto failure;
528            }          
529            hrt_sda_scl(dev, addr, 1, 0);
530            return 0;
531 failure:
532            hrt_sda_scl(dev, addr, 1, 0);
533            hrt_i2c_stop(dev, addr);
534            return -1;
535 }
536 
537 /* 
538  *  hrt_i2c_init_registers
539  *
540  *  sends a sequence of values to the A/D converter device over the I2C bus.
541  *  For an example of the format of "sequence" see the declaration of 
542  *  saa7110_default_init_regs[] above.  The first byte is the number of
543  *  data bytes that follow. The rest of the sequence is a series of pairs
544  *  of a register number followed by a value. It is better if the values
545  *  are sorted in increasing order of register number, but the sequence may
546  *  have gaps and need not be in order.
547  */
548 int  hrt_i2c_init_registers(hrt_t *dev, const char *sequence)
549 {
550         unsigned long addr;
551         int i, len, cur_reg;
552 
553         len  = (int) (*sequence++);
554         addr = dev->virt_addr;
555 
556         if (len <= 2) {
557                 HRT_ERROR_MSG("invalid register initialization sequence");
558                 return -1;
559         }
560 
561         hrt_i2c_start(dev, addr);
562 
563         /* here we select the A/D Device on the i2c bus 
564          * that should pay attention to the following bytes */
565         if (hrt_i2c_send_byte(dev, dev->virt_addr, HRT_AD_DEVICE_ID)) {
566                 HRT_ERROR_MSG("send_byte failed");
567                 return -1;
568         }
569 
570         /* start at the first register and increment along the way */
571         if (hrt_i2c_send_byte(dev, dev->virt_addr, cur_reg = sequence[0])) {
572                 HRT_ERROR_MSG("send_byte failed(2)");
573                 return -1;
574         }
575 
576         for(i = 0; i < len; i += 2, sequence += 2) {
577                 char reg  = sequence[0];
578                 char data = sequence[1];
579                 if (reg > HRT_SAA7110_MAXREG) {
580                         HRT_ERROR_MSG("register %02X out of range!", reg);
581                         return -1;
582                 }
583                 if (reg != cur_reg) {   
584 
585                         /* we're going to an entirely different register */
586                         hrt_i2c_stop(dev, addr);
587                         hrt_i2c_start(dev, addr);
588 
589                         /* select the chip/device on the bus */
590                         if (hrt_i2c_send_byte(dev, dev->virt_addr, HRT_AD_DEVICE_ID)) {
591                                 HRT_ERROR_MSG("send_byte failed(3)");
592                                 return -1;
593                         }
594 
595                         /* select the register */
596                         if (hrt_i2c_send_byte(dev, dev->virt_addr, cur_reg = reg)) {
597                                 HRT_ERROR_MSG("send_byte failed(4)");
598                                 return -1;
599                         }
600                 }
601 
602                 if (hrt_i2c_send_byte(dev, dev->virt_addr, data)) {
603                         HRT_ERROR_MSG("send_byte failed(5)");
604                         return -1;
605                 }
606                 dev->saa7110_registers[cur_reg++] = data;
607         }
608         /* free the i2c bus */
609         hrt_i2c_stop(dev, addr);
610         return 0;
611 }
612 
613 int hrt_i2c_init_device(hrt_t *dev)
614 {
615            int result = 0;
616            HRT_DEBUG_MSG(2, "hrt_i2c_init_device entered"
617                          " (virt_addr = %08X, addr = %08X)", 
618                          (unsigned) dev->virt_addr,
619                          (unsigned) dev->phys_addr);
620 
621            result = hrt_i2c_init_registers(dev, saa7110_default_init_regs);
622            if (result) {
623                          HRT_ERROR_MSG("hrt_i2c_init_registers failed %d", result);
624                          return result;
625            }
626            HRT_DEBUG_MSG(2, "hrt_i2c_init_device returning %d", result);
627            return result;
628 }
629 
630 /***************************
631  * buffering, data copying *
632  ***************************/
633 
634 /*
635  * hrt_copy_window
636  *
637  * copy entire window from video device to buffer
638  * assume frame is frozen
639  */
640 
641 int hrt_copy_window(hrt_t *dev, char * buf)
642 {
643         unsigned long y_addr;
644         unsigned long in_addr;
645         int win_width, win_height, win_end, win_col, win_row;
646         int i, j, y;
647         int dev_line_length;
648 
649         y_addr = dev->virt_addr + HRT_Y_LOW_REG;
650         win_width = dev->win_width;
651         win_height = dev->win_height;
652         win_row = dev->win_row;
653         win_col = dev->win_col;
654         in_addr = dev->virt_addr + win_col;
655 
656         if (~(dev->mode & HRT_COLOR_MODE)) {
657                 dev_line_length = 512;
658                 win_end = dev->win_row + dev->win_height;
659                 for (y = win_row * dev_line_length; y < win_end; y++) {
660                         iowrite16(y, (void *) y_addr);
661                         wmb();
662                         if (copy_to_user(buf, (void *) in_addr, win_width)) {
663                                HRT_ERROR_MSG("copy_to_user failed %lx %lx %d %d (1)",
664                                (unsigned long) in_addr, (unsigned long) buf,
665                                 win_width, y); 
666                                return -EFAULT;
667                         } 
668                         buf += win_width;
669                 }
670         } else if (dev->mode & HRT_COLOR_MODE) {
671                 dev_line_length = 2048;
672                 win_end = dev->win_row + dev->win_height;
673                 for (y = win_row * dev_line_length; y < win_end; y++) {
674                         iowrite16(y, (void *) y_addr);
675                         wmb();
676                         if (copy_to_user(buf, (void *) in_addr, win_width)) {
677                                HRT_ERROR_MSG("copy_to_user failed (2)");
678                                return -EFAULT;
679                         }  
680                         /* rearrange pixels into logical order */
681                         for (i = 0; i < win_width; i++) {
682                                 j = i + win_col;
683                                 if (j < 512) {
684                                         buf[i] = buf[j];
685                                         buf[i+1] = buf[j+512];
686                                 } else {
687                                         buf[i] = buf[j+512];
688                                         buf[i+1] = buf[j+1024];
689                                 }
690                         }
691                         buf += win_width;
692                 }
693         } else {
694                 HRT_ERROR_MSG("unsupported format %x", dev->mode);
695         }
696         return 0;
697 }
698 
699 /*************************************
700  * device initialization and cleanup *
701  *************************************/
702 
703 static inline
704 void hrt_irq_enable(hrt_t *dev)
705 {
706            int val;
707            val = ioread8((void *)(dev->virt_addr + HRT_IRQ_ENABLE));
708            val |= 0x1;
709            iowrite8(val, (void *) (dev->virt_addr + HRT_IRQ_ENABLE));
710 }
711            
712 static inline
713 void hrt_irq_disable(hrt_t *dev)
714 {
715            int val;
716            val = ioread8((void *)(dev->virt_addr + HRT_IRQ_ENABLE));
717            val &= ~0x1;
718            iowrite8(val, (void *) (dev->virt_addr + HRT_IRQ_ENABLE));
719 }
720 
721 void hrt_tasklet(unsigned long);
722 void hrt_timer_init(hrt_t* dev);
723 void hrt_timer_cleanup(hrt_t* dev);
724 int hrt_timer_activate(hrt_t* dev);
725 void hrt_timer_deactivate(hrt_t* dev);
726 
727 void hrt_cleanup(hrt_t* dev)
728 {
729         HRT_DEBUG_MSG(1, "shutting down hrt device %d at 0x%lx",
730           dev->num, dev->phys_addr);
731         HRT_MODULE_CHECK (HRT_MODULE_FINALIZING_STATE | 
732           HRT_MODULE_INITIALIZING_STATE, "1");
733         HRT_CHECK (dev, HRT_INITIALIZING_STATE 
734            | HRT_CLOSED_STATE | HRT_FINALIZING_STATE, "2");
735         dev->state = HRT_FINALIZING_STATE;
736 
737         /* restore device to an inactive state */
738         hrt_freeze_next(dev);
739 
740         /* deactivate and remove interrupt handler or timer */
741         hrt_timer_cleanup (dev);
742 
743         if (dev->phys_addr) {
744                 HRT_DEBUG_MSG(2, "release_mem_region 0x%lx, 0x%lx",
745                 (unsigned long)dev, (unsigned long) dev->phys_addr);
746                 release_mem_region(dev->phys_addr, HRT_IO_SIZE);
747                 dev->phys_addr = 0;
748         }
749         if (dev->virt_addr) {
750                 HRT_DEBUG_MSG(2, "iounmap %lx", (unsigned long) dev->virt_addr);
751                 iounmap((void *)dev->virt_addr);
752                 dev->virt_addr = 0;
753         }
754 #ifdef CONFIG_PCI
755         if (dev->pci_dev) {
756                 pci_disable_device(dev->pci_dev);
757                 dev->pci_dev = NULL;
758         }
759 #endif
760         dev->state = HRT_UNINITIALIZED_STATE;
761 }
762 
763 void hrt_lock_init(hrt_t * dev) {
764         spin_lock_init(&dev->spinlock);
765         dev->is_locked = 0;
766 }
767 
768 int hrt_trylock(hrt_t * dev) {
769         spin_lock(&dev->spinlock);
770         if (dev->is_locked) {
771                 spin_unlock(&dev->spinlock);
772                 return 1; 
773         }
774         dev->is_locked = 1;
775         spin_unlock(&dev->spinlock);
776         return 0;
777 }
778 
779 void hrt_lock(hrt_t * dev) {
780         unsigned long flags;
781         spin_lock_irqsave(&dev->spinlock, flags);
782         if (dev->is_locked) {
783            HRT_ERROR_MSG("locking an already-locked device");
784         }
785         dev->is_locked = 1;
786         spin_unlock_irqrestore(&dev->spinlock, flags);
787 }
788 
789 void hrt_unlock(hrt_t * dev) {
790         spin_lock(&dev->spinlock);
791         if (!dev->is_locked) {
792                 HRT_ERROR_MSG("unlocking unlocked device");
793         }
794         dev->is_locked = 0;  
795         spin_unlock(&dev->spinlock);
796 }
797 
798 int hrt_init(unsigned long phys_address, struct pci_dev * pci_dev)
799 {
800         hrt_t * dev = &hrt_devices[hrt_num_devices];
801         int i, result;
802         char *bus, *color, *ported;
803         unsigned int old_control, old_y_high, old_y_low;
804         unsigned char val1, val2;
805         unsigned long virt_address;
806 
807         HRT_DEBUG_MSG(1, "probing device at 0x%lx", phys_address);
808 
809         dev = &hrt_devices[hrt_num_devices];
810 
811         memset(dev, 0, sizeof(hrt_t));
812         dev->state = HRT_INITIALIZING_STATE;
813         dev->num = hrt_num_devices;
814         hrt_lock_init (dev);
815 
816         tasklet_init(&dev->tasklet, hrt_tasklet, (unsigned long) dev);
817 
818         /* reserve the I/O address space for this device */
819         if (!request_mem_region(phys_address, HRT_IO_SIZE, "hrt")) {
820                 HRT_ERROR_MSG("I/O memory at %lx already in use",
821                    (unsigned long) phys_address);
822                 return -EBUSY;
823         }
824         dev->phys_addr = phys_address;
825 
826         /* map the device's I/O space into kernel memory */
827         virt_address = (unsigned long)
828            ioremap_nocache(phys_address, HRT_IO_SIZE);
829         if (!virt_address) {
830                 HRT_ERROR_MSG("couldn't remap io memory!!");
831                 hrt_cleanup(dev);
832                 return -ENODEV;
833         }
834         dev->virt_addr = virt_address;
835 
836 #ifdef CONFIG_PCI
837         /* pci-specific processing */
838         if (pci_dev) {
839                 pci_set_drvdata (pci_dev, dev);
840                 dev->pci_dev = pci_dev;
841                 dev->irq = -pci_dev->irq;
842                 dev->mode &= ~HRT_ISA_MODE;
843                 /* make certain IRQ is disabled before enabling
844                    device, or else we may get an IRQ we are not
845                    prepared to handle? */
846                 hrt_irq_disable(dev);
847                 if (pci_enable_device(pci_dev)) {
848                         HRT_ERROR_MSG("pci_enable_device failed");
849                         hrt_cleanup(dev);
850                         return -EIO;
851                 }
852         }
853 #endif
854 
855         /* find out whether there is an hrt device at this
856            address, and which type of device it is */
857 
858         /* save the values we are about to modify */
859         old_control = ioread8((void *)(HRT_CONTROL_REG + virt_address));
860         old_y_low = ioread8((void *)(HRT_Y_LOW_REG + virt_address));
861         old_y_high = ioread8((void *)(HRT_Y_HIGH_REG + virt_address));
862 
863         /* freeze the frame grabbing, immediately */
864         iowrite8(0x5B, (void *) (HRT_CONTROL_REG + virt_address));
865          
866         /* complement pixel (0,0) */
867         iowrite16(0, (void *) (HRT_Y_LOW_REG + virt_address));
868         iowrite16(0, (void *) (HRT_Y_HIGH_REG + virt_address));
869         val1 = ioread8((void *) virt_address);
870         iowrite8(~val1, (void *) virt_address);
871            
872         /* write old value of pixel (0,0) to (1,0) */
873         iowrite16(1, (void *) (HRT_Y_LOW_REG + virt_address));
874         iowrite8(val1, (void *) virt_address);
875            
876         /* read the value at the previous raster/row */
877         iowrite16(0, (void *) (HRT_Y_LOW_REG + virt_address));
878         val2 = ioread8((void *) virt_address);
879            
880         if (val2 != (unsigned char)~val1) {
881                 HRT_DEBUG_MSG(1, "no hrt device at address 0x%lx",
882                               virt_address);
883                 /* restore the old values, and hope we did no
884                    damage to some other device at this address;
885                    this is pretty poor, since if there is
886                    another device at that address the effects
887                    of these writes could be harmful;
888                    ideally, there should be a way to 
889                    identify the devices that only uses read
890                    operations */
891                 iowrite8(val1, (void *) virt_address);
892                 iowrite8(old_y_low, (void *) (HRT_Y_LOW_REG + virt_address));
893                 iowrite8(old_y_high, (void *) (HRT_Y_HIGH_REG + virt_address));
894                 iowrite8(old_control, (void *) (HRT_CONTROL_REG + virt_address));
895 
896                 hrt_cleanup(dev);
897                 return -ENODEV;
898         }
899 
900         /* test whether we have a color or greyscale card:
901            the color frame buffer has line of 2048 = 0x400
902            pixels; greyscale has only 512 pixels/line, so
903            the memory mapped row of frame buffer memory
904            should wrap around at 0x200 and 0x400 on a greyscale card
905            but should be good through 0x400 on a color card. */
906 
907         iowrite8(HRT_FREEZE_IMM_CMD, (void *) (HRT_CONTROL_REG + virt_address));
908         iowrite16(0, (void *) (HRT_Y_LOW_REG + virt_address));
909         iowrite16(0, (void *) (HRT_Y_HIGH_REG + virt_address));
910         val1 = ioread8((void *)(0x400 + virt_address));
911         iowrite8(~val1, (void *) (0x400 + virt_address));
912         /* in case greyscale addresses wrap around,
913            refresh the value at offset zero */
914         iowrite8(val1, (void *) (virt_address));
915         val2 = ioread8((void *)(0x400 + virt_address));
916         if (val2 == (unsigned char) ~val1) {
917                 dev->mode |= HRT_COLOR_MODE;
918                 /* infer the frame geometry from the device type */
919                 HRT_DEBUG_MSG(1, "COLOR device detected");
920                 dev->rows = 480;
921                 dev->cols = 640;
922                 dev->bytes_per_pixel = 2;
923         } else {
924                 HRT_DEBUG_MSG(1, "GREYSCALE device detected");
925                 dev->cols = 512;  /* is for NTSC, 512 for PAL */
926                 dev->rows = 480;
927                 dev->bytes_per_pixel = 1;
928         }
929 
930         /* try to initialize the device */
931         result = hrt_i2c_init_device(dev);
932         if (result) {
933                 HRT_ERROR_MSG("hrt_i2c_init_device %d failed",result);
934                 hrt_cleanup(dev);
935                 return -ENODEV;
936         }
937 
938         hrt_go_live(dev);  /* delete this once driver is debugged */
939 
940         /* find out whether the device has dual-ported memory*/
941 
942         /* freeze the image */
943         hrt_freeze_immediate(dev);
944 
945         /* write zeros to horizontal raster line 500,
946            a line that the A/D unit does not modify */
947         iowrite16(0, (void *) (dev->virt_addr + HRT_Y_HIGH_REG));
948         iowrite16(500, (void *) (dev->virt_addr + HRT_Y_LOW_REG));
949         for (i = 0; i < 512; i++) {
950           iowrite8(0, (void *)(dev->virt_addr + i));
951         }
952 
953         /* set capturing mode */
954         hrt_go_live(dev);
955 
956         /* try to overwrite the line with ones */
957         for (i = 0; i < 512; i++) {
958           iowrite8(255, (void *) (dev->virt_addr + i));
959         }
960 
961         /* freeze the image */
962         hrt_freeze_immediate(dev);
963 
964         /* read back the line;
965            if some of the pixels are still zero the memory is
966            not dual ported */
967         result = 1;
968         for (i = 0; i < 512; i++) {
969                 if (!ioread8((void *)(dev->virt_addr + i)))  result = 0;
970         }
971         if (result) {
972                 HRT_DEBUG_MSG(1, "seems to be dual ported");
973                 dev->mode |= HRT_DUAL_PORTED_MODE;
974         }
975 
976         dev->mode |= HRT_ISA_MODE;
977 
978 #ifdef CONFIG_PCI
979         if ((pci_dev->device == HRT_DEVICE_ID_COLOR) !=
980            ((dev->mode & HRT_COLOR_MODE) == HRT_COLOR_MODE))
981           HRT_ERROR_MSG("PCI and probed types don't match");
982 #endif
983 
984         /* discover whether this device supports interrupts */
985         hrt_timer_init(dev);
986         if (dev->mode & HRT_IRQ_MODE) {
987                 dev->irq_count = 0;
988                 hrt_irq_enable(dev);
989                 hrt_go_live(dev);
990                 mdelay(20);
991                 hrt_freeze_immediate(dev);
992                 hrt_irq_disable(dev);
993                 if (dev->irq_count) {
994                         HRT_DEBUG_MSG(1, "counted %d irqs in 20 ms",
995                                       dev->irq_count);
996                         HRT_ERROR_MSG("devices supports IRQs");
997                 } else {
998                         HRT_DEBUG_MSG(1, "no irqs in 10 ms");
999                         dev->irq = 0;
1000                         dev->mode &= ~HRT_IRQ_MODE;
1001                 }
1002         }
1003 
1004         /* describe this device for the log */
1005         if (dev->mode & HRT_ISA_MODE) bus = "ISA";
1006         else bus = "PCI";
1007         if (dev->mode & HRT_COLOR_MODE) color = "COLOR";
1008         else color = "GREYSCALE";
1009         if (dev->mode & HRT_DUAL_PORTED_MODE) ported = "DUAL";
1010         else ported = "SINGLE";
1011         HRT_ERROR_MSG("found device %d at 0x%lx",
1012                dev->num, dev->phys_addr);
1013         HRT_ERROR_MSG("%s %s with %s-ported memory",
1014                bus, color, ported);
1015         if (dev->mode & HRT_IRQ_MODE) 
1016           HRT_ERROR_MSG("using IRQ %d", dev->irq);
1017 
1018         init_waitqueue_head(&dev->wait_queue);
1019 
1020         /* set default window size
1021            to cover the entire frame buffer */
1022         HRT_DEBUG_MSG(1, "setting width, cols = %d", dev->cols);
1023         dev->win_row = 0;
1024         dev->win_width = dev->cols;
1025         dev->win_col = 0;
1026         dev->win_height = dev->rows;
1027         dev->field = -1;
1028         hrt_num_devices++;
1029         dev->state = HRT_CLOSED_STATE;
1030 
1031         return 0;
1032 }
1033 
1034 int  hrt_isa_init(void)
1035 {
1036         int i;
1037         for (i = 0; i < ARRAY_SIZE(hrt_addresses); i++)
1038                 hrt_init(hrt_addresses[i], NULL);
1039         hrt_nonpci_devices = hrt_num_devices;
1040         return 0;
1041 }
1042 
1043 void hrt_isa_cleanup(void)
1044 {    int i;
1045         for (i=0; i<hrt_nonpci_devices; i++) {
1046             HRT_DEBUG_MSG(2, "cleaning up device %d", i);
1047             hrt_cleanup(hrt_devices+i);
1048         }
1049 }
1050 
1051 /*************************
1052  * interrupts and timers *
1053  *************************/
1054 
1055 int  hrt_irq_pending(hrt_t *dev)
1056 {
1057            int r = ioread8((void *)(dev->virt_addr + HRT_CONTROL_REG)) & 0x4; 
1058            rmb(); 
1059            return r;
1060 }
1061 
1062 irqreturn_t hrt_irq_handler(int irq, void* dev_id, struct pt_regs* regs)
1063 {
1064         hrt_t* dev = dev_id;
1065         if (!hrt_irq_pending(dev)) goto none;
1066         /* acknowledge the interrupt */
1067         hrt_irq_disable(dev);
1068         dev->irq_count++;
1069         /* do not try to do any I/O on the device here,
1070            or else risk race with last scheduled tasklet
1071          */
1072         tasklet_schedule(&dev->tasklet);
1073         /* enable the next interrupt */
1074         hrt_irq_enable(dev);
1075 #ifdef IRQ_HANDLED
1076         return IRQ_HANDLED;
1077 #endif
1078  none:
1079 #ifdef IRQ_NONE
1080         return IRQ_NONE;
1081 #endif
1082 }
1083 
1084 void hrt_timer_handler(unsigned long data)
1085 {
1086         hrt_t* dev = (hrt_t*)data;
1087            
1088         if (dev->timer_active) {
1089                 tasklet_schedule(&dev->tasklet);
1090                 dev->timer.expires = jiffies + HZ/100;
1091                 add_timer(&dev->timer);
1092         }
1093 }
1094 
1095 void hrt_irq_init(hrt_t* dev)
1096 {
1097        HRT_DEBUG_MSG(2, "hrt_irq_init");
1098        dev->irq_count = 0;
1099        if (dev->irq == 0) return;
1100        if ((dev->irq > 0) || (dev->mode & HRT_IRQ_MODE)) {
1101                HRT_ERROR_MSG("irq handler already installed");               
1102                return;
1103        }
1104        hrt_irq_disable(dev); /* insurance */
1105        if (request_irq(-dev->irq, hrt_irq_handler,
1106            SA_SHIRQ, "hrt", (void*)dev)) {
1107                HRT_ERROR_MSG("unable to reserve IRQ");
1108                dev->irq = 0;
1109        } else {
1110                dev->irq = -dev->irq;
1111                dev->mode |= HRT_IRQ_MODE;
1112        }
1113 }
1114 
1115 void hrt_irq_cleanup(hrt_t* dev)
1116 {
1117         HRT_DEBUG_MSG(2, "hrt_irq_cleanup");
1118         if (dev->mode & HRT_IRQ_MODE) {
1119                 free_irq(dev->irq, dev);
1120                 dev->mode &= ~HRT_IRQ_MODE;
1121         }
1122 }
1123 
1124 void hrt_timer_init(hrt_t* dev)
1125 {
1126         HRT_DEBUG_MSG(1, "hrt_timer_init");
1127         HRT_CHECK(dev, HRT_INITIALIZING_STATE, "4");
1128         if (dev->timer_active) {
1129                 HRT_ERROR_MSG("irq or timer already active");
1130         }
1131         hrt_irq_init(dev);
1132         if (!(dev->mode & HRT_IRQ_MODE)) {
1133                 if (dev->timer.function) {
1134                         HRT_ERROR_MSG("timer already initialized");
1135                         return;
1136                 }
1137                 HRT_DEBUG_MSG(1, "installing timer");
1138                 init_timer(&dev->timer);
1139                 dev->timer.function = hrt_timer_handler;
1140                 dev->timer.data = (unsigned long)dev;
1141         }
1142 }
1143 
1144 void hrt_timer_cleanup(hrt_t* dev)
1145 {
1146         HRT_DEBUG_MSG(1, "hrt_timer_cleanup");
1147         HRT_CHECK(dev, HRT_FINALIZING_STATE, "3");
1148         hrt_timer_deactivate (dev);
1149         hrt_irq_cleanup(dev);
1150         dev->timer.function = NULL;
1151 }
1152 
1153 void hrt_timer_deactivate(hrt_t* dev)
1154 {
1155         HRT_DEBUG_MSG(1, "hrt_timer_deactivate");
1156         if (dev->timer_active) {
1157                 dev->timer_active = 0;
1158                 if (dev->mode & HRT_IRQ_MODE) hrt_irq_disable(dev);
1159                 else del_timer_sync(&dev->timer);
1160                 tasklet_disable(&dev->tasklet);
1161         }
1162 }
1163 
1164 /* hrt_time_activate 
1165    -----------------
1166 
1167    starts a task to monitor the state of the device.
1168    This may be driven by a timer or by an interrupt
1169    from the device.
1170 */
1171 
1172 int hrt_timer_activate(hrt_t* dev)
1173 {    
1174         int result = 0;
1175         HRT_DEBUG_MSG(1, "hrt_timer_activate");
1176         if (dev->timer_active) {
1177                 HRT_ERROR_MSG("irq or timer already active");
1178                 return 0;
1179         }
1180         dev->timer_active = 1;
1181         if (dev->mode & HRT_IRQ_MODE) {
1182                 HRT_DEBUG_MSG(1, "enabling irq");
1183                 hrt_irq_enable(dev);
1184         } else {
1185                 if (!dev->timer.function) {
1186                         HRT_ERROR_MSG("timer not initialized");
1187                         return -1;
1188                 }
1189                 dev->timer.expires = jiffies + HZ/100;
1190                 add_timer(&dev->timer);            
1191         }
1192         return result;
1193 }
1194 
1195 /* hrt_tasklet
1196    -----------
1197 
1198    is called in response to either a timer interrupt
1199    or an interrupt generated by the device
1200 
1201 */
1202 
1203 void hrt_tasklet(unsigned long data)
1204 {       int field;
1205         hrt_t *dev = (hrt_t *) data;
1206         if (hrt_trylock (dev)) { /* device is busy */
1207           /* could add a wakeup mechanism here */
1208           return;
1209         }
1210         field = hrt_get_field (dev);
1211         if (dev->field == -1) {
1212                 /* just started; don't know previous state */
1213                 dev->field = field;
1214                 goto done;
1215         }
1216         if (field != dev->field) {
1217                 /* field has changed */
1218                 if (dev->field_changes == 1) {
1219                    HRT_DEBUG_MSG(1, "field changes going to 0 %d", dev->num);
1220                    wake_up_interruptible (&dev->wait_queue);
1221                 } 
1222                 if (dev->field_changes) dev->field_changes--;
1223         }
1224         /* .... this code is incomplete
1225            Eventually, there should be code here to 
1226            keep track of how many fields have been digitized,
1227            and arrange for buffering the data */
1228  done:
1229         hrt_unlock(dev);
1230 }
1231 
1232 /********************************
1233  * basic file operations (fops) *
1234  ********************************/
1235 
1236 int  hrt_open   (struct inode *inode, struct file *file);
1237 int  hrt_release(struct inode *inode, struct file *file);
1238 int  hrt_read   (struct file *file, char *buf, size_t count, loff_t * ppos);
1239 int  hrt_ioctl  (struct inode *inode, struct file *filp,
1240                  unsigned int cmd, unsigned long arg);
1241 int  hrt_mmap   (struct file *file, struct vm_area_struct *vma);
1242 
1243 static struct file_operations hrt_fops = {
1244            .owner                = THIS_MODULE,
1245            .open                 = hrt_open,
1246            .release              = hrt_release,
1247            .read                 = hrt_read,
1248            .ioctl                = hrt_ioctl,
1249            .mmap                 = hrt_mmap,
1250 };
1251 
1252 /**
1253  * hrt_open
1254  *
1255  * checks minor number range, sets private_data,
1256  * starts timer if necessary, increments users
1257  */
1258 int hrt_open(struct inode *inode, struct file *file)
1259 {
1260         hrt_t* dev;
1261         unsigned int minor;
1262         int result = 0;
1263 
1264         minor = MINOR(inode->i_rdev);
1265         if (minor >= HRT_MAX_DEVICES) return -ENODEV;
1266 
1267         dev = hrt_devices + minor;
1268         HRT_DEBUG_MSG(1, "opening device %d at addr %lX", minor, (unsigned long)dev);
1269 
1270         if (dev->state != HRT_CLOSED_STATE) {
1271                 HRT_DEBUG_MSG(2, "already open");
1272                 return -EBUSY;
1273         }
1274         HRT_DEBUG_MSG(2, "setting private data");
1275         file->private_data = (void*)dev;
1276         dev->state = HRT_OPEN_STATE;
1277         hrt_go_live(dev);
1278 
1279         /* FIXME: shift responsibility for buffer allocation
1280            to open (here) and deallocation to the release operation;
1281            only do this later, when everything else is working. */
1282 
1283         HRT_DEBUG_MSG(2, "installing timer/irq");
1284         result = hrt_timer_activate(dev); 
1285 
1286         return result;
1287 }
1288 
1289 /* hrt_release should not need any lock, because
1290    it is only called by the system, on last close; at that
1291    point there should be no possibility of more calls that
1292    touch this device, unless they are from a timer
1293    or interrrupt handler */
1294 
1295 int hrt_release(struct inode *inode, struct file *file)
1296 {
1297         hrt_t* dev = file->private_data;
1298         if (dev->state != HRT_OPEN_STATE) return -ENODEV;
1299         dev->state = HRT_CLOSED_STATE;
1300         hrt_timer_deactivate(dev);
1301         /* above should wait for active tasklet to finish */
1302         return 0;
1303 }
1304 
1305 int hrt_read(struct file *file, char *buf, size_t count, loff_t * ppos)
1306 {
1307         hrt_t* dev = file->private_data;
1308         int max_count, result;
1309 
1310         HRT_DEBUG_MSG(3, "hrt_read_proc (1) count = %d", count);
1311         if (dev->state != HRT_OPEN_STATE) return -ENODEV;
1312 
1313         hrt_lock(dev);
1314         dev->field_changes = 2;
1315         if (dev->is_frozen) {
1316            hrt_go_live (dev);
1317            hrt_unlock(dev);
1318            if (wait_event_interruptible(dev->wait_queue, dev->field_changes == 0)) {
1319                 return -ERESTARTSYS;
1320            }
1321            hrt_lock(dev);
1322            dev->field_changes = 2;
1323         }
1324          
1325         hrt_freeze_next(dev);
1326         hrt_unlock(dev);
1327         if (wait_event_interruptible(dev->wait_queue, dev->field_changes == 0)) {
1328                 return -ERESTARTSYS;
1329         }
1330 
1331         HRT_DEBUG_MSG(3, "hrt_read_proc (3) bpp = %d width = %d height = %d",
1332              dev->bytes_per_pixel, dev->win_width, dev->win_height);
1333         max_count = dev->win_width * dev->win_height * dev->bytes_per_pixel;
1334         if (count > max_count) count = max_count;
1335         hrt_lock(dev);
1336         HRT_DEBUG_MSG(3, "hrt_read_proc (4) count = %d", count);
1337         if ((result = hrt_copy_window(dev, buf))) {
1338                 HRT_DEBUG_MSG(3, "hrt_copy_window failed %d", result);
1339                 hrt_unlock(dev);
1340                 return -EFAULT;
1341         }
1342         hrt_unlock(dev);
1343         HRT_DEBUG_MSG(3, "hrt_read_proc (5)");
1344         return count;
1345 }
1346 
1347 /*
1348  * ioctl operations
1349  */
1350 
1351 int hrt_ioctl(struct inode *inode, struct file *file,
1352                     unsigned int cmd, unsigned long arg)
1353 {
1354            int result = 0, iarg = *((int*)arg);
1355            hrt_t* dev = file->private_data;
1356          
1357 
1358            switch (cmd)
1359            {
1360            case IOC_HRT_FREEZE_FRAME:
1361                          HRT_DEBUG_MSG(2, "IOC_HRT_FREEZE_FRAME: called");
1362                          hrt_freeze_next(dev);
1363                          break;
1364 
1365            case IOC_HRT_GO_LIVE:
1366                          HRT_DEBUG_MSG(2, "IOC_HRT_GO_LIVE: called");
1367                          hrt_go_live(dev);
1368                          break;
1369 
1370            case IOC_HRT_WIN_SET_WIDTH:
1371                          HRT_DEBUG_MSG(2, "IOC_HRT_WIN_SET_WIDTH: called with arg %d", iarg);
1372                          dev->win_width = iarg;
1373                          break;
1374            case IOC_HRT_WIN_SET_HEIGHT:
1375                          HRT_DEBUG_MSG(2, "IOC_HRT_WIN_SET_HEIGHT: called with arg %d", iarg);
1376                          dev->win_height = iarg;
1377                          break;
1378            case IOC_HRT_WIN_SET_X:
1379                          HRT_DEBUG_MSG(2, "IOC_HRT_WIN_SET_X: called with arg %d", iarg);
1380                          dev->win_col = iarg;
1381                          break;
1382            case IOC_HRT_WIN_SET_Y:
1383                          HRT_DEBUG_MSG(2, "IOC_HRT_WIN_SET_Y: called with arg %d", iarg);
1384                          dev->win_row = iarg;
1385                          break;
1386 
1387            default:
1388                          result = -ENOSYS;
1389                          break;
1390            }
1391 
1392            return result;
1393 }
1394 
1395 int  hrt_mmap   (struct file *file, struct vm_area_struct *vma)
1396 {
1397         return -ENOSYS;
1398 }
1399 
1400 #ifdef CONFIG_PCI
1401 
1402 /***************
1403  * PCI support *
1404  ***************/
1405 
1406 MODULE_DEVICE_TABLE(pci, hrt_pci_tbl);
1407 int  hrt_pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *pci_id);
1408 void hrt_pci_remove (struct pci_dev *pci_dev);
1409 
1410 static struct pci_device_id hrt_pci_tbl[] __devinitdata = {
1411            {PCI_DEVICE(HRT_VENDOR_ID, HRT_DEVICE_ID_GREY)},
1412            {PCI_DEVICE(HRT_VENDOR_ID, HRT_DEVICE_ID_COLOR)},
1413            {0,}
1414 };
1415 
1416 static struct pci_driver hrt_pci_driver = {
1417            .name        = "hrt",
1418            .id_table = hrt_pci_tbl, 
1419            .probe    = hrt_pci_probe,
1420            .remove   = __devexit_p(hrt_pci_remove)
1421 };
1422 
1423 int  hrt_pci_probe(struct pci_dev *pci_dev,
1424                    const struct pci_device_id *pci_id)
1425 {
1426         HRT_DEBUG_MSG(2, "probing pci device");
1427 
1428         /* check that this is a type of device we support */
1429         if ((pci_dev->device != HRT_DEVICE_ID_COLOR) &&
1430                 (pci_dev->device != HRT_DEVICE_ID_GREY)) {
1431                 HRT_ERROR_MSG("unknown device type 0x%hx",
1432                               pci_dev->device);
1433                 return -ENODEV;
1434         }
1435 
1436         if (hrt_num_devices >= HRT_MAX_DEVICES) {
1437                 HRT_ERROR_MSG("need to increase HRT_MAX_DEVICES");
1438                 return -ENOMEM;
1439         }
1440        
1441         return hrt_init(pci_resource_start(pci_dev, 0), pci_dev);
1442 }
1443 
1444 /* since these cards are not intended to be hot-pluggable,
1445    we do not try to reuse hrt_t objects; we just use the remove
1446    operation for removal of the device driver module */
1447 
1448 void hrt_pci_remove (struct pci_dev *pci_dev)
1449 {
1450         hrt_t *dev;
1451         HRT_DEBUG_MSG(2, "hrt_pci_remove");
1452         dev = (hrt_t *) pci_get_drvdata (pci_dev);
1453         hrt_cleanup(dev);
1454         pci_disable_device(pci_dev);
1455 }
1456 
1457 void hrt_pci_init(void)
1458 { 
1459         HRT_DEBUG_MSG(2, "pci_register_driver");
1460         pci_register_driver(&hrt_pci_driver);
1461 }
1462 
1463 void hrt_pci_cleanup(void)
1464 {
1465         HRT_DEBUG_MSG(2, "pci_unregister_driver");
1466         pci_unregister_driver(&hrt_pci_driver);
1467 }
1468 
1469 #else
1470 
1471 /* no PCI support */
1472 
1473 void hrt_pci_init(void)
1474 {
1475 }
1476 
1477 void hrt_pci_cleanup(void)
1478 {
1479 }
1480 
1481 #endif
1482 
1483 /*************************************
1484  * module initialization and cleanup *
1485  *************************************/
1486 
1487 int hrt_major_number = 0;
1488 
1489 void hrt_cleanup_module(void)
1490 {
1491         HRT_MODULE_CHECK (HRT_MODULE_INITIALIZING_STATE |
1492           HRT_MODULE_INITIALIZED_STATE, "6");
1493         hrt_module_state = HRT_MODULE_FINALIZING_STATE;
1494         HRT_DEBUG_MSG(2, "hrt_cleanup_module");
1495         hrt_isa_cleanup();
1496         hrt_pci_cleanup();
1497         if (hrt_major_number) unregister_chrdev(hrt_major_number, "hrt");
1498         hrt_debug_cleanup();
1499         hrt_module_state = HRT_MODULE_UNINITIALIZED_STATE;
1500 }
1501 
1502 int hrt_init_module(void)
1503 {
1504        int result = 0;
1505        hrt_module_state = HRT_MODULE_INITIALIZING_STATE;
1506        hrt_debug_init();
1507        result = register_chrdev(major_number, "hrt", &hrt_fops);
1508        if (result < 0) {
1509                HRT_ERROR_MSG("failed to register char device %d", 
1510                              major_number);
1511                goto failed;
1512        }
1513 
1514        /* use major number returned by system if no
1515           major number is specified by this module */
1516        if (major_number == 0) hrt_major_number = result;
1517        else hrt_major_number = major_number;
1518        HRT_ERROR_MSG("module initializing with major number %d",
1519                      hrt_major_number);
1520 
1521        memset(hrt_devices, 0, sizeof(hrt_devices));
1522 
1523        /* detect ISA/PC104 devices, and PCI devices that are 
1524           jumpered to use the ISA/PC104 I/O address space */
1525        hrt_isa_init();
1526 
1527        /* now detect regular PCI devices */
1528        hrt_pci_init();
1529 
1530        if (hrt_num_devices == 0) {
1531                HRT_ERROR_MSG("no hrt devices detected");
1532                hrt_module_state = HRT_MODULE_UNINITIALIZED_STATE;
1533                return -ENODEV;
1534        } else {
1535                HRT_ERROR_MSG("found %d hrt devices", hrt_num_devices);
1536        }
1537        hrt_module_state = HRT_MODULE_INITIALIZED_STATE;
1538        return 0;
1539 failed:
1540        hrt_cleanup_module();
1541        HRT_DEBUG_MSG(2, "returning from failed init_module() with result %d",
1542                      result);
1543        hrt_module_state = HRT_MODULE_UNINITIALIZED_STATE;
1544        return result;
1545 }
1546 
1547 module_init(hrt_init_module);
1548 module_exit(hrt_cleanup_module);
1549 
1550 MODULE_LICENSE("GPL");
1551 
  This page was automatically generated by the LXR engine.