a475f13b64cff5fcc3d0a884fab455de87e61ec5
[dragonfly.git] / sys / dev / video / meteor / meteor.c
1 /*
2  * Copyright (c) 1995 Mark Tinguely and Jim Lowe
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      This product includes software developed by Mark Tinguely and Jim Lowe
16  * 4. The name of the author may not be used to endorse or promote products 
17  *    derived from this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
23  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
28  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  *
31  * $FreeBSD: src/sys/pci/meteor.c,v 1.49 1999/09/25 18:24:41 phk Exp $
32  * $DragonFly: src/sys/dev/video/meteor/meteor.c,v 1.22 2007/05/13 18:33:58 swildner Exp $
33  */
34
35 /*              Change History:
36         8/21/95         Release
37         8/23/95         On advice from Stefan Esser, added volatile to PCI
38                         memory pointers to remove PCI caching .
39         8/29/95         Fixes suggested by Bruce Evans.
40                         meteor_mmap should return -1 on error rather than 0.
41                         unit # > NMETEOR should be unit # >= NMETEOR.
42         10/24/95        Turn 50 Hz processing for SECAM and 60 Hz processing
43                         off for AUTOMODE.
44         11/11/95        Change UV from always begin signed to ioctl selected
45                         to either signed or unsigned.
46         12/07/95        Changed 7196 startup codes for 50 Hz as recommended
47                         by Luigi Rizzo (luigi@iet.unipi.it)
48         12/08/95        Clear SECAM bit in PAL/NTSC and set input field count
49                         bits for 50 Hz mode (PAL/SECAM) before I was setting the
50                         output count bits. by Luigi Rizzo (luigi@iet.unipi.it)
51         12/18/95        Correct odd DMA field (never exceed, but good for safety
52                         Changed 7196 startup codes for 50 Hz as recommended
53                         by Luigi Rizzo (luigi@iet.unipi.it)
54         12/19/95        Changed field toggle mode to enable (offset 0x3c)
55                         recommended by luigi@iet.unipi.it
56                         Added in prototyping, include file, staticizing,
57                         and DEVFS changes from FreeBSD team.
58                         Changed the default allocated pages from 151 (NTSC)
59                         to 217 (PAL).
60                         Cleaned up some old comments in iic_write().
61                         Added a Field (even or odd) only capture mode to 
62                         eliminate the high frequency problems with compression
63                         algorithms.  Recommended by luigi@iet.unipi.it.
64                         Changed geometry ioctl so if it couldn't allocated a
65                         large enough contiguous space, it wouldn't free the
66                         stuff it already had.
67                         Added new mode called YUV_422 which delivers the
68                         data in planer Y followed by U followed by V. This
69                         differs from the standard YUV_PACKED mode in that
70                         the chrominance (UV) data is in the correct (different)
71                         order. This is for programs like vic and mpeg_encode
72                         so they don't have to reorder the chrominance data.
73                         Added field count to stats.
74                         Increment frame count stat if capturing continuous on
75                         even frame grabs.
76                         Added my email address to these comments
77                         (james@cs.uwm.edu) suggested by (luigi@iet.unipt.it :-).
78                         Changed the user mode signal mechanism to allow the
79                         user program to be interrupted at the end of a frame
80                         in any one of the modes.  Added SSIGNAL ioctl.
81                         Added a SFPS/GFPS ioctl so one may set the frames per
82                         second that the card catpures.  This code needs to be
83                         completed.
84                         Changed the interrupt routine so synchronous capture
85                         will work on fields or frames and the starting frame
86                         can be either even or odd.
87                         Added HALT_N_FRAMES and CONT_N_FRAMES so one could
88                         stop and continue synchronous capture mode.
89                         Change the tsleep/wakeup function to wait on mtr
90                         rather than &read_intr_wait.
91         1/22/96         Add option (METEOR_FreeBSD_210) for FreeBSD 2.1
92                         to compile.
93                         Changed intr so it only printed errors every 50 times.
94                         Added unit number to error messages.
95                         Added get_meteor_mem and enabled range checking.
96         1/30/96         Added prelim test stuff for direct video dma transfers
97                         from Amancio Hasty (hasty@rah.star-gate.com).  Until
98                         we get some stuff sorted out, this will be ifdef'ed
99                         with METEOR_DIRECT_VIDEO.  This is very dangerous to
100                         use at present since we don't check the address that
101                         is passed by the user!!!!!
102         2/26/96         Added special SVIDEO input device type.
103         2/27/96         Added meteor_reg.h file and associate types Converted
104                         meteor.c over to using meteor.h file.  Prompted by
105                         Lars Jonas Olsson <ljo@po.cwru.edu>.
106         2/28/96         Added meteor RGB code from Lars Jonas Olsson
107                         <ljo@po.cwru.edu>.  I make some mods to this code, so
108                         I hope it still works as I don't have an rgb card to
109                         test with.
110         2/29/96         <ljo@po.cwru.edu> tested the meteor RGB and supplied
111                         me with diffs.  Thanks, we now have a working RGB
112                         version of the driver.  Still need to clean up this
113                         code.
114         3/1/96          Fixed a nasty little bug that was clearing the VTR
115                         mode bit when the 7196 status was requested.
116         3/15/96         Fixed bug introduced in previous version that
117                         stopped the only fields mode from working.
118                         Added METEOR{GS}TS ioctl, still needs work.
119         3/25/96         Added YUV_9 and YUV_12 modes.  Cleaned up some of the
120                         code and converted variables to use the new register
121                         types.
122         4/8/96          Fixed the a bug in with the range enable.  Pointed
123                         out by Jim Bray.
124         5/13/96         Fix the FPS ioctl so it actually sets the frames
125                         per second.  Code supplied by ian@robots.ox.ac.uk.
126                         The new code implements a new define:
127                         METEOR_SYSTEM_DEFAULT  which should be defined as
128                         METEOR_PAL, METEOR_SECAM, or METEOR_NTSC in your system
129                         configuration file.  If METEOR_SYSTEM_DEFAULT isn't
130                         defined, and there is not a signal when set_fps is
131                         called, then the call has no effect.
132                         Changed the spelling of PLANER to PLANAR as pointed
133                         out by Paco Hope <paco@cs.virigina.edu> and define
134                         PLANER to be PLANAR for backward compatibility.
135         5/28/95         METEOR_INPUT_DEV_RCA -> METEOR_INPUT_DEV0, not
136                         METEOR_GEO_DEV0.  Pointed out by Ian Reid,
137                         <ian@robots.ox.ac.uk>.
138                         METEOR_DEV_MASK should be 0x0000f000 and not 
139                         0x2000f000, otherwise METEOR_RGB gets masked
140                         out.  Pointed out by Ian Reid.
141                         Changed the fps code to give even distribution for
142                         low frame rates.  Code supplied by Ian Reid.
143                         Fix some problems with the RGB version.  Patch supplied
144                         by <ljo@po.cwru.edu>.
145                         Added METEOR_FIELD_MODE to include files for a 
146                         future version of this driver.
147 */
148
149 #include "use_meteor.h"
150 #include "opt_meteor.h"
151
152 #include <sys/param.h>
153 #include <sys/systm.h>
154 #include <sys/conf.h>
155 #include <sys/device.h>
156 #include <sys/kernel.h>
157 #include <sys/signalvar.h>
158 #include <sys/mman.h>
159 #include <sys/uio.h>
160
161 #if defined(METEOR_FreeBSD_210)
162 #include <machine/cpu.h>        /* bootverbose */
163 #endif
164
165 #include <vm/vm.h>
166 #include <vm/vm_kern.h>
167 #include <vm/pmap.h>
168 #include <vm/vm_extern.h>
169
170 #include <bus/pci/pcivar.h>
171 #include <bus/pci/pcireg.h>
172 #include <dev/video/meteor/ioctl_meteor.h>
173 #include <dev/video/meteor/meteor_reg.h>
174
175
176 static void meteor_intr (void *arg);
177
178 /* 
179  * Allocate enough memory for:
180  *      768x576 RGB 16 or YUV (16 storage bits/pixel) = 884736 = 216 pages
181  *
182  * You may override this using the options "METEOR_ALLOC_PAGES=value" in your
183  * kernel configuration file.
184  */
185 #ifndef METEOR_ALLOC_PAGES
186 #define METEOR_ALLOC_PAGES 217
187 #endif
188 #define METEOR_ALLOC (METEOR_ALLOC_PAGES * PAGE_SIZE)
189
190 static meteor_reg_t meteor[NMETEOR];
191 #define METEOR_NUM(mtr) ((mtr - &meteor[0])/sizeof(meteor_reg_t))
192
193 #define METPRI  PCATCH
194
195 static  const char*     met_probe (pcici_t tag, pcidi_t type);
196 static  void    met_attach(pcici_t tag, int unit);
197 static  u_long  met_count;
198
199 static struct   pci_device met_device = {
200         "meteor",
201         met_probe,
202         met_attach,
203         &met_count
204 };
205
206 COMPAT_PCI_DRIVER (meteor, met_device);
207
208 #if defined(METEOR_FreeBSD_210) /* XXX */
209 d_open_t        meteor_open;
210 d_close_t       meteor_close;
211 d_read_t        meteor_read;
212 d_write_t       meteor_write;
213 d_ioctl_t       meteor_ioctl;
214 d_mmap_t        meteor_mmap;
215 #else
216 static  d_open_t        meteor_open;
217 static  d_close_t       meteor_close;
218 static  d_read_t        meteor_read;
219 static  d_write_t       meteor_write;
220 static  d_ioctl_t       meteor_ioctl;
221 static  d_mmap_t        meteor_mmap;
222
223 #define CDEV_MAJOR 67
224 static struct dev_ops meteor_ops = {
225         { "meteor", CDEV_MAJOR, 0 },
226         .d_open =       meteor_open,
227         .d_close =      meteor_close,
228         .d_read =       meteor_read,
229         .d_write =      meteor_write,
230         .d_ioctl =      meteor_ioctl,
231         .d_mmap =       meteor_mmap,
232 };
233 #endif
234
235 static mreg_t saa7116_pci_default[sizeof(struct saa7116_regs)/sizeof(mreg_t)]={
236                                 /* PCI Memory registers         */
237                                 /* BITS   Type  Description     */
238 /* 0x00 */      0x00000000,     /* 31:1   e*RW  DMA 1 (Even)
239                                       0   RO    0x0             */
240 /* 0x04 */      0x00000000,     /* 31:2   e*RW  DMA 2 (Even)
241                                     1:0   RO    0x0             */
242 /* 0x08 */      0x00000000,     /* 31:2   e*RW  DMA 3 (Even)
243                                     1:0   RO    0x0             */
244 /* 0x0c */      0x00000000,     /* 31:1   o*RW  DMA 1 (Odd)
245                                       0   RO    0x0             */
246 /* 0x10 */      0x00000000,     /* 31:2   o*RW  DMA 2 (Odd)
247                                     1:0   RO    0x0             */
248 /* 0x14 */      0x00000000,     /* 31:2   o*RW  DMA 3 (Odd)
249                                     1:0   RO    0x0             */
250 /* 0x18 */      0x00000500,     /* 15:2   e*RW  Stride 1 (Even)
251                                     1:0   RO    0x0             */
252 /* 0x1c */      0x00000000,     /* 15:2   e*RW  Stride 2 (Even)
253                                     1:0   RO    0x0             */
254 /* 0x20 */      0x00000000,     /* 15:2   e*RW  Stride 3 (Even)
255                                     1:0   RO    0x0             */
256 /* 0x24 */      0x00000500,     /* 15:2   o*RW  Stride 1 (Odd)
257                                     1:0   RO    0x0             */
258 /* 0x28 */      0x00000000,     /* 15:2   o*RW  Stride 2 (Odd)
259                                     1:0   RO    0x0             */
260 /* 0x2c */      0x00000000,     /* 15:2   o*RW  Stride 3 (Odd)
261                                     1:0   RO    0x0             */
262 /* 0x30 */      0xeeeeee01,     /* 31:8   *RW   Route (Even)
263                                     7:0   *RW   Mode (Even)     */
264 /* 0x34 */      0xeeeeee01,     /* 31:8   *RW   Route (Odd)
265                                     7:0   *RW   Mode (Odd)      */
266 /* 0x38 */      0x00200020,     /* 22:16  *RW   FIFO Trigger Planer Mode,
267                                     6:0   *RW   FIFO Trigger Packed Mode */
268 /* 0x3c */      0x00000107,     /*  9:8   *RW   Reserved (0x0)
269                                       2   *RW   Field Toggle
270                                       1   *RW   Reserved (0x1)
271                                       0   *RW   Reserved (0x1)          */
272 /* 0x40 */      0x000000c0,     /*    15  *RW   Range Enable
273                                       14  *RW   Corrupt Disable
274                                       11  *RR   Address Error (Odd)
275                                       10  *RR   Address Error (Even)
276                                       9   *RR   Field Corrupt (Odd)
277                                       8   *RR   Field Corrupt (Even)
278                                       7   *RW   Fifo Enable
279                                       6   *RW   VRSTN#
280                                       5   *RR   Field Done (Odd)
281                                       4   *RR   Field Done (Even)
282                                       3   *RS   Single Field Capture (Odd)
283                                       2   *RS   Single Field Capture (Even)
284                                       1   *RW   Capture (ODD) Continous
285                                       0   *RW   Capture (Even) Continous */
286 /* 0x44 */      0x00000000,     /*  7:0   *RW   Retry Wait Counter */
287 /* 0x48 */      0x00000307,     /*    10  *RW   Interrupt mask, start of field
288                                       9   *RW   Interrupt mask, end odd field
289                                       8   *RW   Interrupt mask, end even field
290                                       2   *RR   Interrupt status, start of field
291                                       1   *RR   Interrupt status, end of odd
292                                       0   *RR   Interrupt status, end of even */
293 /* 0x4c */      0x00000001,     /* 31:0   *RW   Field Mask (Even) continous */
294 /* 0x50 */      0x00000001,     /* 31:0   *RW   Field Mask (Odd) continous */
295 /* 0x54 */      0x00000000,     /* 20:16  *RW   Mask Length (Odd)
296                                     4:0   *RW   Mask Length (Even)      */
297 /* 0x58 */      0x0005007c,     /* 22:16  *RW   FIFO almost empty
298                                     6:0   *RW   FIFO almost full        */
299 /* 0x5c */      0x461e1e0f,     /* 31:24  *RW   I2C Phase 4
300                                    23:16  *RW   I2C Phase 3
301                                    15:8   *RW   I2C Phase 2
302                                     7:0   *RW   I2C Phase 1     */
303 /* 0x60 */      0x00000300,     /* 31:24  *RO   I2C Read Data
304                                    23:16  **RW  I2C Auto Address
305                                       11  RO    I2C SCL Input
306                                       10  RO    I2C SDA Input
307                                       9   RR    I2C Direct Abort
308                                       8   RR    I2C Auto Abort
309                                       3   RW    I2C SCL Output
310                                       2   RW    I2C SDA Output
311                                       1   RW    I2C Bypass
312                                       0   RW    I2C Auto Enable */
313 /* 0x64 */      0x00000000,     /*    24  RS    I2C New Cycle
314                                    23:16  **RW  I2C Direct Address
315                                    15:8   **RW  I2C Direct Sub-address
316                                     7:0   **RW  I2C Direct Write Address */
317 /* 0x68 */      0x00000000,     /* 31:24  **RW  I2C Auto Sub-address 1 (Even)
318                                    23:16  **RW  I2C Auto Data 1 (Even)
319                                    15:8   **RW  I2C Auto Sub-address 0 (Even)
320                                     7:0   **RW  I2C Auto Data 0 (Even) */
321 /* 0x6c */      0x00000000,     /* 31:24  **RW  I2C Auto Sub-address 3 (Even)
322                                    23:16  **RW  I2C Auto Data 3 (Even)
323                                    15:8   **RW  I2C Auto Sub-address 2 (Even)
324                                     7:0   **RW  I2C Auto Data 2 (Even) */
325 /* 0x70 */      0x00000000,     /* 31:24  **RW  I2C Auto Sub-address 5 (Even)
326                                    23:16  **RW  I2C Auto Data 5 (Even)
327                                    15:8   **RW  I2C Auto Sub-address 4 (Even)
328                                     7:0   **RW  I2C Auto Data 4 (Even) */
329 /* 0x74 */      0x00000000,     /* 31:24  **RW  I2C Auto Sub-address 7 (Even)
330                                    23:16  **RW  I2C Auto Data 7 (Even)
331                                    15:8   **RW  I2C Auto Sub-address 6 (Even)
332                                     7:0   **RW  I2C Auto Data 6 (Even) */
333 /* 0x78 */      0x00000000,     /* 31:24  **RW  I2C Auto Sub-address 1 (Odd)
334                                    23:16  **RW  I2C Auto Data 1 (Odd)
335                                    15:8   **RW  I2C Auto Sub-address 0 (Odd)
336                                     7:0   **RW  I2C Auto Data 0 (Odd) */
337 /* 0x7c */      0x00000000,     /* 31:24  **RW  I2C Auto Sub-address 3 (Odd)
338                                    23:16  **RW  I2C Auto Data 3 (Odd)
339                                    15:8   **RW  I2C Auto Sub-address 2 (Odd)
340                                     7:0   **RW  I2C Auto Data 2 (Odd) */
341 /* 0x80 */      0x00000000,     /* 31:24  **RW  I2C Auto Sub-address 5 (Odd)
342                                    23:16  **RW  I2C Auto Data 5 (Odd)
343                                    15:8   **RW  I2C Auto Sub-address 4 (Odd)
344                                     7:0   **RW  I2C Auto Data 4 (Odd) */
345 /* 0x84 */      0x00000000,     /* 31:24  **RW  I2C Auto Sub-address 7 (Odd)
346                                    23:16  **RW  I2C Auto Data 7 (Odd)
347                                    15:8   **RW  I2C Auto Sub-address 6 (Odd)
348                                     7:0   **RW  I2C Auto Data 6 (Odd) */
349 /* 0x88 */      0x00000000,     /* 23:16  **RW  I2C Register Enable (Odd)
350                                     7:0   **RW  I2C Register Enable (Even) */
351 /* 0x8c */      0x00000000,     /* 23:2   e*RW  DMA End (Even)
352                                     1:0   RO    0x0     */
353 /* 0x90 */      0x00000000      /* 23:2   e*RW  DMA End (Odd)
354                                     1:0   RO    0x0     */
355 };
356
357 static u_char saa7196_i2c_default[NUM_SAA7196_I2C_REGS] = {
358                         /* SAA7196 I2C bus control                      */
359                         /* BITS Function                                */
360 /* 00 */        0x50,   /* 7:0  Increment Delay                         */
361 /* 01 */        0x30,   /* 7:0  Horizontal Sync Begin for 50hz          */
362 /* 02 */        0x00,   /* 7:0  Horizontal Sync Stop for 50hz           */
363 /* 03 */        0xe8,   /* 7:0  Horizontal Sync Clamp Start for 50hz    */
364 /* 04 */        0xb6,   /* 7:0  Horizontal Sync Clamp Stop for 50hz     */
365 /* 05 */        0xf4,   /* 7:0  Horizontal Sync Start after PH1 for 50hz */
366 /* 06 */        0x46,   /*   7  Input mode =0 CVBS, =1 S-Video 
367                              6  Pre filter
368                            5:4  Aperture Bandpass characteristics
369                            3:2  Coring range for high freq
370                            1:0  Aperture bandpass filter weights        */
371 /* 07 */        0x00,   /* 7:0  Hue                                     */
372 /* 08 */        0x7f,   /* 7:3  Colour-killer threshold QAM (PAL, NTSC) */
373 /* 09 */        0x7f,   /* 7:3  Colour-killer threshold SECAM           */
374 /* 0a */        0x7f,   /* 7:0  PAL switch sensitivity                  */
375 /* 0b */        0x7f,   /* 7:0  SECAM switch sensitivity                */
376 /* 0c */        0x40,   /*   7  Colour-on bit
377                            6:5  AGC filter                              */
378 /* 0d */        0x84,   /*   7  VTR/TV mode bit = 1->VTR mode
379                              3  Realtime output mode select bit
380                              2  HREF position select
381                              1  Status byte select
382                              0  SECAM mode bit                          */
383 /* 0e */        0x38,   /*   7  Horizontal clock PLL
384                              5  Select interal/external clock source
385                              4  Output enable of Horizontal/Vertical sync
386                              3  Data output YUV enable
387                              2  S-VHS bit
388                              1  GPSW2
389                              0  GPSW1                                   */
390 /* 0f */        0x50,   /*   7  Automatic Field detection
391                              6  Field Select 0 = 50hz, 1=60hz
392                              5  SECAM cross-colour reduction
393                              4  Enable sync and clamping pulse
394                            3:1  Luminance delay compensation            */
395 /* 10 */        0x00,   /*   2  Select HREF Position
396                            1:0  Vertical noise reduction                */
397 /* 11 */        0x2c,   /* 7:0  Chrominance gain conrtol for QAM        */
398 /* 12 */        0x40,   /* 7:0  Chrominance saturation control for VRAM port */
399 /* 13 */        0x40,   /* 7:0  Luminance contract control for VRAM port */
400 /* 14 */        0x34,   /* 7:0  Horizontal sync begin for 60hz          */
401 #ifdef notdef
402 /* 15 */        0x0c,   /* 7:0  Horizontal sync stop for 60hz           */
403 /* 16 */        0xfb,   /* 7:0  Horizontal clamp begin for 60hz         */
404 /* 17 */        0xd4,   /* 7:0  Horizontal clamp stop for 60hz          */
405 /* 18 */        0xec,   /* 7:0  Horizontal sync start after PH1 for 60hz */
406 #else
407                 0x0a, 0xf4, 0xce, 0xf4,
408 #endif
409 /* 19 */        0x80,   /* 7:0  Luminance brightness control for VRAM port */
410 /* 1a */        0x00,
411 /* 1b */        0x00,
412 /* 1c */        0x00,
413 /* 1d */        0x00,
414 /* 1e */        0x00,
415 /* 1f */        0x00,
416 /* 20 */        0x90,   /*   7  ROM table bypass switch
417                            6:5  Set output field mode
418                              4  VRAM port outputs enable
419                            3:2  First pixel position in VRO data
420                            1:0  FIFO output register select             */
421 /* 21 */        0x80,   /* 7:0  [7:0] Pixel number per line on output   */
422 /* 22 */        0x80,   /* 7:0  [7:0] Pixel number per line on input    */
423 /* 23 */        0x03,   /* 7:0  [7:0] Horizontal start position of scaling win*/
424 /* 24 */        0x8a,   /* 7:5  Horizontal decimation filter
425                              4  [8] Horizontal start position of scaling win
426                            3:2  [9:8] Pixel number per line on input
427                            1:0  [9:8] Pixel number per line on output   */
428 /* 25 */        0xf0,   /* 7:0  [7:0] Line number per output field      */
429 /* 26 */        0xf0,   /* 7:0  [7:0] Line number per input field       */
430 /* 27 */        0x0f,   /* 7:0  [7:0] Vertical start of scaling window  */
431 /* 28 */        0x80,   /*   7  Adaptive filter switch
432                            6:5  Vertical luminance data processing
433                              4  [8] Vertical start of scaling window 
434                            3:2  [9:8] Line number per input field
435                            1:0  [9:8] Line number per output field      */
436 /* 29 */        0x16,   /* 7:0  [7:0] Vertical bypass start             */
437 /* 2a */        0x00,   /* 7:0  [7:0] Vertical bypass count             */
438 /* 2b */        0x00,   /*   4  [8] Vertical bypass start
439                              2  [8] Vertical bypass count
440                              0  Polarity, internally detected odd even flag */
441 /* 2c */        0x80,   /* 7:0  Set lower limit V for colour-keying     */
442 /* 2d */        0x7f,   /* 7:0  Set upper limit V for colour-keying     */
443 /* 2e */        0x80,   /* 7:0  Set lower limit U for colour-keying     */
444 /* 2f */        0x7f,   /* 7:0  Set upper limit U for colour-keying     */
445 /* 30 */        0xbf    /*   7  VRAM bus output format
446                              6  Adaptive geometrical filter
447                              5  Luminance limiting value
448                              4  Monochrome and two's complement output data sel
449                              3  Line quailifier flag
450                              2  Pixel qualifier flag
451                              1  Transparent data transfer
452                              0  Extended formats enable bit             */
453 };
454
455 static u_char bt254_default[NUM_BT254_REGS] = {
456         0x00,   /* 24 bpp */
457         0xa0,
458         0xa0,
459         0xa0,
460         0x50,
461         0x50,
462         0x50,
463 } ;
464
465 /*
466  * i2c_write:
467  * Returns      0       Succesful completion.
468  * Returns      1       If transfer aborted or timeout occured.
469  *
470  */
471 static int i2c_print_err = 1;
472 static int
473 i2c_write(meteor_reg_t * mtr, u_char slave, u_char rw, u_char reg, u_char data)
474 {
475 unsigned long   wait_counter = 0x0001ffff;
476 mreg_t *        iic_write_loc = &mtr->base->i2c_write;
477 int             err = 0;
478
479
480         /* Write the data the the i2c write register */
481         *iic_write_loc = SAA7116_IIC_NEW_CYCLE |
482                 (((u_long)slave|(u_long)rw) << 16) |
483                 ((u_long)reg << 8) | (u_long)data;
484
485         /* Wait until the i2c cycle is compeleted */
486         while((*iic_write_loc & SAA7116_IIC_NEW_CYCLE)) {
487                 if(!wait_counter) break;
488                 wait_counter--;
489         }
490
491         /* 1ffff should be enough delay time for the i2c cycle to complete */
492         if(!wait_counter) {
493                 if(i2c_print_err)
494                         kprintf("meteor%d: %d i2c %s transfer timeout 0x%x",
495                                 METEOR_NUM(mtr), slave, 
496                                 rw ? "read" : "write", *iic_write_loc);
497                         
498                 err=1;
499         } 
500
501         /* Check for error on direct write, clear if any */
502         if(mtr->base->i2c_read & SAA7116_IIC_DIRECT_TRANSFER_ABORTED){
503                 mtr->base->i2c_read |= SAA7116_IIC_DIRECT_TRANSFER_ABORTED;
504                 if(i2c_print_err)
505                         kprintf("meteor%d: 0x%x i2c %s transfer aborted",
506                                 METEOR_NUM(mtr), slave,
507                                 rw ? "read" : "write" );
508                 err= 1;
509         }
510
511         if(err) {
512                 if(i2c_print_err)
513                         kprintf(" - reg=0x%x, value=0x%x.\n", reg, data);
514         }
515                 
516         return err;
517 }
518 #undef i2c_print
519
520 static  const char *
521 met_probe (pcici_t tag, pcidi_t type)
522 {
523         switch (type) {
524         case SAA7116_PHILIPS_ID:        /* meteor */
525                 return("Philips SAA 7116");
526         };
527         return (NULL);
528 }
529
530         /* interrupt handling routine 
531            complete meteor_read() if using interrupts
532         */
533 static void
534 meteor_intr(void *arg)
535 {
536         meteor_reg_t    *mtr       = (meteor_reg_t *) arg;
537         mreg_t          *cap       = &mtr->base->cap_cntl,
538                         *base      = &mtr->base->dma1e,
539                         *stat      = &mtr->base->irq_stat;
540         u_long          status     = *stat,
541                         cap_err    = *cap & 0x00000f00,
542 #ifdef METEOR_CHECK_PCI_BUS
543                         pci_err    = pci_conf_read(mtr->tag,
544                                                 PCI_COMMAND_STATUS_REG),
545 #endif
546                         next_base  = (u_long)(vtophys(mtr->bigbuf));
547
548         /*
549          * Disable future interrupts if a capture mode is not selected.
550          * This can happen when we are in the process of closing or 
551          * changing capture modes, otherwise it shouldn't happen.
552          */
553         if(!(mtr->flags & METEOR_CAP_MASK)) {
554                 *cap &= 0x8ff0; /* disable future interrupts */
555         }
556 #ifdef METEOR_CHECK_PCI_BUS
557         /*
558          * Check for pci bus errors.
559          */
560 #define METEOR_MASTER_ABORT     0x20000000
561 #define METEOR_TARGET_ABORT     0x10000000
562         if(pci_err & METEOR_MASTER_ABORT) {
563                 kprintf("meteor%d: intr: pci bus master dma abort: 0x%x 0x%x.\n",
564                         METEOR_NUM(mtr), *base, *(base+3));
565                 pci_conf_write(mtr->tag, PCI_COMMAND_STATUS_REG, pci_err);
566         }
567         if(pci_err & METEOR_TARGET_ABORT) {
568                 kprintf("meteor%d: intr: pci bus target dma abort: 0x%x 0x%x.\n",
569                         METEOR_NUM(mtr), *base, *(base+3));
570                 pci_conf_write(mtr->tag, PCI_COMMAND_STATUS_REG, pci_err);
571         }
572 #endif
573         /*
574          * Check for errors.
575          */
576         if (cap_err) {
577            if (cap_err & 0x300) {
578                 if(mtr->fifo_errors % 50 == 0) {
579                         kprintf("meteor%d: capture error", METEOR_NUM(mtr));
580                         kprintf(": %s FIFO overflow.\n",
581                                 cap_err&0x0100? "even" : "odd");
582                 }
583                 mtr->fifo_errors++ ;    /* increment fifo capture errors cnt */
584            }
585            if (cap_err & 0xc00) {
586                 if(mtr->dma_errors % 50 == 0) {
587                         kprintf("meteor%d: capture error", METEOR_NUM(mtr));
588                         kprintf(": %s DMA address.\n",
589                                 cap_err&0x0400? "even" : "odd");
590                 }
591                 mtr->dma_errors++ ;     /* increment DMA capture errors cnt */
592            }
593         }
594         *cap |= 0x0f30;         /* clear error and field done */
595
596         /*
597          * In synchronous capture mode we need to know what the address
598          * offset for the next field/frame will be.  next_base holds the
599          * value for the even dma buffers (for odd, one must add stride).
600          */
601         if((mtr->flags & METEOR_SYNCAP) && !mtr->synch_wait &&
602            (mtr->current < mtr->frames)) { /* could be !=, but < is safer */
603                 /* next_base is initialized to mtr->bigbuf */
604                 next_base += mtr->frame_size * mtr->current;
605                 if(mtr->flags & METEOR_WANT_TS)
606                         next_base += sizeof(struct timeval) * mtr->current;
607         }
608
609         /*
610          * Count the field and clear the field flag.
611          *
612          * In single mode capture, clear the continuous capture mode.
613          *
614          * In synchronous capture mode, if we have room for another field,
615          * adjust DMA buffer pointers.
616          * When we are above the hi water mark (hiwat), mtr->synch_wait will
617          * be set and we will not bump the DMA buffer pointers.  Thus, once
618          * we reach the hi water mark,  the driver acts like a continuous mode
619          * capture on the mtr->current frame until we hit the low water
620          * mark (lowat).  The user had the option of stopping or halting
621          * the capture if this is not the desired effect.
622          */
623         if (status & 0x1) {             /* even field */
624                 mtr->even_fields_captured++;
625                 mtr->flags &= ~METEOR_WANT_EVEN;
626                 if((mtr->flags & METEOR_SYNCAP) && !mtr->synch_wait) {
627                         *base = next_base;
628                         /* XXX should add adjustments for YUV_422 & PLANAR */
629                 }
630                 /*
631                  * If the user requested to be notified via signal,
632                  * let them know the field is complete.
633                  */
634                 if(mtr->proc && (mtr->signal & METEOR_SIG_MODE_MASK))
635                         ksignal(mtr->proc, mtr->signal&(~METEOR_SIG_MODE_MASK));
636         }
637         if (status & 0x2) {             /* odd field */
638                 mtr->odd_fields_captured++;
639                 mtr->flags &= ~METEOR_WANT_ODD;
640                 if((mtr->flags & METEOR_SYNCAP) && !mtr->synch_wait) {
641                         *(base+3) = next_base + *(base+6);
642                         /* XXX should add adjustments for YUV_422 & PLANAR */
643                 }
644                 /*
645                  * If the user requested to be notified via signal,
646                  * let them know the field is complete.
647                  */
648                 if(mtr->proc && (mtr->signal & METEOR_SIG_MODE_MASK))
649                         ksignal(mtr->proc, mtr->signal&(~METEOR_SIG_MODE_MASK));
650         }
651
652         /*
653          * If we have a complete frame.
654          */
655         if(!(mtr->flags & METEOR_WANT_MASK)) {
656                 mtr->frames_captured++;
657                 /*
658                  * post the completion time. 
659                  */
660                 if(mtr->flags & METEOR_WANT_TS) {
661                         struct timeval *ts;
662                         
663                         if(mtr->alloc_pages * PAGE_SIZE <= (mtr->frame_size +
664                                         sizeof(struct timeval))) {
665                                 ts =(struct timeval *)mtr->bigbuf +
666                                                         mtr->frame_size;
667                         /* doesn't work in synch mode except for first frame */
668                         /* XXX */
669                                 microtime(ts);
670                         }
671                 }
672                 /*
673                  * Wake up the user in single capture mode.
674                  */
675                 if(mtr->flags & METEOR_SINGLE)
676                         wakeup((caddr_t)mtr);
677                 /*
678                  * If the user requested to be notified via signal,
679                  * let them know the frame is complete.
680                  */
681                 if(mtr->proc && !(mtr->signal & METEOR_SIG_MODE_MASK))
682                         ksignal(mtr->proc, mtr->signal&(~METEOR_SIG_MODE_MASK));
683                 /*
684                  * Reset the want flags if in continuous or
685                  * synchronous capture mode.
686                  */
687                 if(mtr->flags & (METEOR_CONTIN|METEOR_SYNCAP)) {
688                         switch(mtr->flags & METEOR_ONLY_FIELDS_MASK) {
689                         case METEOR_ONLY_ODD_FIELDS:
690                                 mtr->flags |= METEOR_WANT_ODD;
691                                 break;
692                         case METEOR_ONLY_EVEN_FIELDS:
693                                 mtr->flags |= METEOR_WANT_EVEN;
694                                 break;
695                         default:
696                                 mtr->flags |= METEOR_WANT_MASK;
697                                 break;
698                         }
699                 }
700                 /*
701                  * Special handling for synchronous capture mode.
702                  */
703                 if(mtr->flags & METEOR_SYNCAP) {
704                         struct meteor_mem *mm = mtr->mem;
705                         /*
706                          * Mark the current frame as active.  It is up to
707                          * the user to clear this, but we will clear it
708                          * for the user for the current frame being captured
709                          * if we are within the water marks (see below).
710                          */
711                         mm->active |= 1 << (mtr->current - 1);
712
713                         /*
714                          * Since the user can muck with these values, we need
715                          * to check and see if they are sane. If they don't
716                          * pass the sanity check, disable the capture mode.
717                          * This is rather rude, but then so was the user.
718                          *
719                          * Do we really need all of this or should we just
720                          * eliminate the possiblity of allowing the
721                          * user to change hi and lo water marks while it
722                          * is running? XXX
723                          */
724                         if(mm->num_active_bufs < 0 ||
725                            mm->num_active_bufs > mtr->frames ||
726                            mm->lowat < 1 || mm->lowat >= mtr->frames ||
727                            mm->hiwat < 1 || mm->hiwat >= mtr->frames ||
728                            mm->lowat > mm->hiwat ) {
729                                 *cap &= 0x8ff0;
730                                 mtr->flags &= ~(METEOR_SYNCAP|METEOR_WANT_MASK);
731                         } else {
732                                 /*
733                                  * Ok, they are sane, now we want to
734                                  * check the water marks.
735                                  */
736                                 if(mm->num_active_bufs <= mm->lowat)
737                                         mtr->synch_wait = 0;
738                                 if(mm->num_active_bufs >= mm->hiwat)
739                                         mtr->synch_wait = 1;
740                                 /*
741                                  * Clear the active frame bit for this frame
742                                  * and advance the counters if we are within
743                                  * the banks of the water marks. 
744                                  */
745                                 if(!mtr->synch_wait) {
746                                         mm->active &= ~(1 << mtr->current);
747                                         mtr->current++;
748                                         if(mtr->current > mtr->frames)
749                                                 mtr->current = 1;
750                                         mm->num_active_bufs++;
751                                 }
752                         }
753                 }
754         }
755
756         *stat |=  0x7;          /* clear interrupt status */
757         return;
758 }
759
760 static void
761 set_fps(meteor_reg_t *mtr, u_short fps)
762 {
763         struct saa7116_regs *s7116 = mtr->base;
764         unsigned status;
765         unsigned maxfps, mask = 0x1, length = 0;
766
767         SAA7196_WRITE(mtr, SAA7196_STDC, SAA7196_REG(mtr, SAA7196_STDC) | 0x02);
768         SAA7196_READ(mtr);
769         status = (s7116->i2c_read & 0xff000000L) >> 24;
770
771         /*
772          * Determine if there is an input signal.  Depending on the
773          * frequency we either have a max of 25 fps (50 hz) or 30 fps (60 hz).
774          * If there is no input signal, then we need some defaults.  If the
775          * user neglected to specify any defaults, just set to the fps to max.
776          */
777         if((status & 0x40) == 0) {      /* Is there a signal ? */
778                 if(status & 0x20) {
779                         maxfps = 30;    /* 60 hz system */
780                 } else {
781                         maxfps = 25;    /* 50 hz system */
782                 }
783         } else {                        /* We have no signal, check defaults */
784 #if METEOR_SYSTEM_DEFAULT == METEOR_PAL || METEOR_SYSTEM_DEFAULT == METEOR_SECAM
785                 maxfps = 25;
786 #elif METEOR_SYSTEM_DEFAULT == METEOR_NTSC
787                 maxfps = 30;
788 #else
789                 /* Don't really know what to do, just set max */
790                 maxfps = 30;
791                 fps = 30;
792 #endif
793         }
794
795         /*
796          * A little sanity checking...
797          */
798         if(fps <  1)      fps = 1;
799         if(fps > maxfps) fps = maxfps;
800
801         /*
802          * Compute the mask/length using the fps.
803          */
804         if(fps == maxfps) {
805                 mask = 0x1;
806                 length = 0x0;
807         } else if ((float)fps == maxfps/2.0) {  
808                 mask = 0x1;
809                 length = 0x1;
810         } else if (fps > maxfps/2) {
811                 float step, b;
812
813                 mask = (1<<maxfps) - 1;
814                 length = maxfps - 1;
815                 step = (float)(maxfps - 1)/(float)(maxfps - fps);
816                 for(b=step; b < maxfps; b += step) {
817                         mask &= ~(1<<((int)b)); /* mask out the bth frame */
818                 }
819         } else {        /* fps < maxfps/2 */
820                 float step, b;
821
822                 mask = 0x1;
823                 length = maxfps - 1;
824                 step = (float)(maxfps -1)/(float)(fps);
825                 for(b = step + 1; b < maxfps - 1; b += step) {
826                         mask |= (1<<((int)b));  /* mask in the bth frame */
827                 }
828         }
829
830         /*
831          * Set the fps.
832          */
833         s7116->fme = s7116->fmo = mask;
834         s7116->fml = (length << 16) | length;
835
836         mtr->fps = fps;
837
838         return;
839
840 }
841
842 /*
843  * There is also a problem with range checking on the 7116.
844  * It seems to only work for 22 bits, so the max size we can allocate
845  * is 22 bits long or 4194304 bytes assuming that we put the beginning
846  * of the buffer on a 2^24 bit boundary.  The range registers will use
847  * the top 8 bits of the dma start registers along with the bottom 22
848  * bits of the range register to determine if we go out of range.
849  * This makes getting memory a real kludge.
850  *
851  */
852 #define RANGE_BOUNDARY  (1<<22)
853 static vm_offset_t
854 get_meteor_mem(int unit, unsigned size)
855 {
856 vm_offset_t     addr = 0;
857
858         addr = vm_page_alloc_contig(size, 0, 0xffffffff, 1<<24);
859         if(addr == 0)
860                 addr = vm_page_alloc_contig(size, 0, 0xffffffff, PAGE_SIZE);
861         if(addr == 0) {
862                 kprintf("meteor%d: Unable to allocate %d bytes of memory.\n",
863                         unit, size);
864         }
865
866         return addr;
867 }
868
869 static void
870 bt254_write(meteor_reg_t *mtr, u_char addr, u_char data)
871 {
872         addr &= 0x7;                                            /* sanity? */
873         mtr->bt254_reg[addr] = data;
874         PCF8574_DATA_WRITE(mtr, data);                          /* set data */
875         PCF8574_CTRL_WRITE(mtr, (PCF8574_CTRL_REG(mtr) & ~0x7) | addr);
876         PCF8574_CTRL_WRITE(mtr, PCF8574_CTRL_REG(mtr) & ~0x10); /* WR/ to 0 */
877         PCF8574_CTRL_WRITE(mtr, PCF8574_CTRL_REG(mtr) | 0x10);  /* WR to 1 */
878         PCF8574_DATA_WRITE(mtr, 0xff);                          /* clr data */
879
880 }
881
882 static void
883 bt254_init(meteor_reg_t *mtr)
884 {
885 int     i;
886
887         PCF8574_CTRL_WRITE(mtr, 0x7f);
888         PCF8574_DATA_WRITE(mtr, 0xff);  /* data port must be 0xff */
889         PCF8574_CTRL_WRITE(mtr, 0x7f);
890
891         /* init RGB module for 24bpp, composite input */
892         for(i=0; i<NUM_BT254_REGS; i++)
893                 bt254_write(mtr, i, bt254_default[i]);
894
895         bt254_write(mtr, BT254_COMMAND, 0x00);  /* 24 bpp */
896 }
897
898 static void
899 bt254_ntsc(meteor_reg_t *mtr, int arg)
900 {
901         if (arg){
902           /* Set NTSC bit */
903           PCF8574_CTRL_WRITE(mtr, PCF8574_CTRL_REG(mtr) | 0x20);
904         }
905         else {
906           /* reset NTSC bit */
907           PCF8574_CTRL_WRITE(mtr, PCF8574_CTRL_REG(mtr) &= ~0x20);
908         }
909 }
910
911 static void
912 select_bt254(meteor_reg_t *mtr)
913 {
914         /* disable saa7196, saaen = 1 */
915         PCF8574_CTRL_WRITE(mtr, PCF8574_CTRL_REG(mtr) | 0x80);
916         /* enable Bt254, bten = 0 */
917         PCF8574_CTRL_WRITE(mtr, PCF8574_CTRL_REG(mtr) & ~0x40);
918 }
919
920 static void
921 select_saa7196(meteor_reg_t *mtr)
922 {
923         /* disable Bt254, bten = 1 */
924         PCF8574_CTRL_WRITE(mtr, PCF8574_CTRL_REG(mtr) | 0x40);
925         /* enable saa7196, saaen = 0 */
926         PCF8574_CTRL_WRITE(mtr, PCF8574_CTRL_REG(mtr) & ~0x80);
927 }
928
929 /*
930  * Initialize the 7116, 7196 and the RGB module.
931  */
932 static void
933 meteor_init ( meteor_reg_t *mtr )
934 {
935         mreg_t  *vbase_addr;
936         int     i;
937
938         /*
939          * Initialize the Philips SAA7116
940          */
941         mtr->base->cap_cntl = 0x00000040L;
942         vbase_addr = &mtr->base->dma1e;
943         for (i = 0 ; i < (sizeof(struct saa7116_regs)/sizeof(mreg_t)); i++)
944                 *vbase_addr++ = saa7116_pci_default[i];
945
946         /*
947          * Check for the Philips SAA7196
948          */
949         i2c_print_err = 0;
950         if(i2c_write(mtr, SAA7196_I2C_ADDR, SAA7116_I2C_WRITE, 0, 0xff) == 0) {
951                 i2c_print_err = 1;
952                 /*
953                  * Initialize 7196
954                  */
955                 for (i = 0; i < NUM_SAA7196_I2C_REGS; i++) 
956                         SAA7196_WRITE(mtr, i, saa7196_i2c_default[i]);
957                 /*
958                  * Get version number.
959                  */
960                 SAA7196_WRITE(mtr, SAA7196_STDC,
961                         SAA7196_REG(mtr, SAA7196_STDC) & ~0x02);
962                 SAA7196_READ(mtr);
963                 kprintf("meteor%d: <Philips SAA 7196> rev 0x%x\n",
964                         METEOR_NUM(mtr),
965                         (unsigned)((mtr->base->i2c_read & 0xff000000L) >> 28));
966         } else {
967                 i2c_print_err = 1;
968                 kprintf("meteor%d: <Philips SAA 7196 NOT FOUND>\n",
969                         METEOR_NUM(mtr));
970         }
971         /*
972          * Check for RGB module, initialized if found.
973          */
974         i2c_print_err = 0;
975         if(i2c_write(mtr,PCF8574_DATA_I2C_ADDR,SAA7116_I2C_WRITE,0,0xff) == 0) {
976                 i2c_print_err = 1;
977                 kprintf("meteor%d: <Booktree 254 (RGB module)>\n",
978                         METEOR_NUM(mtr));       /* does this have a rev #? */
979                 bt254_init(mtr);        /* Set up RGB module */
980                 mtr->flags = METEOR_RGB;
981         } else {
982                 i2c_print_err = 1;
983                 mtr->flags = 0;
984         }
985
986         set_fps(mtr, 30);
987
988 }
989
990 static  void
991 met_attach(pcici_t tag, int unit)
992 {
993 #ifdef METEOR_IRQ
994         u_long old_irq, new_irq;
995 #endif /* METEOR_IRQ */
996         meteor_reg_t *mtr;
997         vm_offset_t buf;
998         u_long latency;
999
1000         if (unit >= NMETEOR) {
1001                 kprintf("meteor%d: attach: only %d units configured.\n",
1002                                 unit, NMETEOR);
1003                 kprintf("meteor%d: attach: invalid unit number.\n", unit);
1004                 return ;
1005         }
1006
1007         /*
1008          * Check for Meteor/PPB (PCI-PCI Bridge)
1009          * Reprogram IBM Bridge if detected.
1010          * New Meteor cards have an IBM PCI-PCI bridge, creating a secondary
1011          * PCI bus. The SAA chip is connected to this secondary bus.
1012          */
1013
1014         /* If we are not on PCI Bus 0, check for the Bridge */
1015         if ( pci_get_bus_from_tag( tag ) != 0) {
1016                 pcici_t bridge_tag;
1017
1018                 /* get tag of parent bridge */
1019                 bridge_tag = pci_get_parent_from_tag( tag );
1020
1021                 /* Look for IBM 82351, 82352 or 82353 */
1022                 if (pci_conf_read(bridge_tag, PCI_ID_REG) == 0x00221014) {
1023
1024                         if ( bootverbose)
1025                                 kprintf("meteor%d: PPB device detected, reprogramming IBM bridge.\n", unit);
1026
1027                         /* disable SERR */
1028                         pci_cfgwrite(bridge_tag, 0x05, 0x00, 1);
1029                         /* set LATENCY */
1030                         pci_cfgwrite(bridge_tag, 0x0d, 0x20, 1);
1031                         /* write posting enable, prefetch enabled --> GRAB direction */
1032                         pci_cfgwrite(bridge_tag, 0x42, 0x14, 1);
1033                         /* set PRTR Primary retry timer register */
1034                         pci_cfgwrite(bridge_tag, 0x4c, 0x10, 1);
1035                 }
1036         }
1037
1038         mtr = &meteor[unit];
1039         mtr->tag = tag;
1040         pci_map_mem(tag, PCI_MAP_REG_START, (vm_offset_t *)&mtr->base,
1041                                 &mtr->phys_base);
1042
1043 #ifdef METEOR_IRQ               /* from the configuration file */
1044         old_irq = pci_conf_read(tag, PCI_INTERRUPT_REG);
1045         pci_conf_write(tag, PCI_INTERRUPT_REG, METEOR_IRQ);
1046         new_irq = pci_conf_read(tag, PCI_INTERRUPT_REG);
1047         kprintf("meteor%d: attach: irq changed from %d to %d\n",
1048                 unit, (old_irq & 0xff), (new_irq & 0xff));
1049 #endif /* METEOR_IRQ */
1050                                 /* setup the interrupt handling routine */
1051         pci_map_int(tag, meteor_intr, (void*) mtr); 
1052
1053 /*
1054  * PCI latency timer.  32 is a good value for 4 bus mastering slots, if
1055  * you have more than for, then 16 would probably be a better value.
1056  *
1057  */
1058 #ifndef METEOR_DEF_LATENCY_VALUE
1059 #define METEOR_DEF_LATENCY_VALUE        32      
1060 #endif
1061         latency = pci_conf_read(tag, PCI_LATENCY_TIMER);
1062         latency = (latency >> 8) & 0xff;
1063         if(bootverbose) {
1064                 if(latency)
1065                         kprintf("meteor%d: PCI bus latency is", unit);
1066                 else
1067                         kprintf("meteor%d: PCI bus latency was 0 changing to",
1068                                 unit);
1069         }
1070         if(!latency) {
1071                 latency = METEOR_DEF_LATENCY_VALUE;
1072                 pci_conf_write(tag, PCI_LATENCY_TIMER,  latency<<8);
1073         }
1074         if(bootverbose) {
1075                 kprintf(" %lu.\n", latency);
1076         }
1077
1078         meteor_init(mtr);       /* set up saa7116, saa7196, and rgb module */
1079
1080         if(METEOR_ALLOC)
1081                 buf = get_meteor_mem(unit, METEOR_ALLOC);
1082         else
1083                 buf = 0;
1084         if(bootverbose) {
1085                 kprintf("meteor%d: buffer size %d, addr 0x%llx\n",
1086                         unit, METEOR_ALLOC, vtophys(buf));
1087         }
1088
1089         mtr->bigbuf = buf;
1090         mtr->alloc_pages = METEOR_ALLOC_PAGES;
1091         if(buf != 0) {
1092                 bzero((caddr_t) buf, METEOR_ALLOC);
1093                 buf = vtophys(buf);
1094                                         /* 640x480 RGB 16 */
1095                 mtr->base->dma1e = buf;
1096                 mtr->base->dma1o = buf + 0x500;
1097                 mtr->base->dma_end_e = 
1098                 mtr->base->dma_end_o = buf + METEOR_ALLOC;
1099         }
1100         /* 1 frame of 640x480 RGB 16 */
1101         mtr->cols = 640;
1102         mtr->rows = 480;
1103         mtr->depth = 2;         /* two bytes per pixel */
1104         mtr->frames = 1;        /* one frame */
1105
1106         mtr->flags |= METEOR_INITALIZED | METEOR_AUTOMODE | METEOR_DEV0 |
1107                    METEOR_RGB16;
1108         dev_ops_add(&meteor_ops, -1, unit);
1109         make_dev(&meteor_ops, unit, 0, 0, 0644, "meteor");
1110 }
1111
1112 #define UNIT(x) ((x) & 0x07)
1113
1114 #ifdef unused
1115 static int
1116 meteor_reset(cdev_t dev)
1117 {
1118 int                     unit = UNIT(minor(dev));
1119 struct  saa7116_regs    *m;
1120
1121         if(unit >= NMETEOR)
1122                 return ENXIO;
1123
1124         m = meteor[unit].base;
1125
1126         m->cap_cntl = 0x0;
1127         tsleep((caddr_t)m, METPRI, "Mreset", hz/50);
1128
1129         m->cap_cntl = 0x8ff0;
1130         m->cap_cntl = 0x80c0;
1131         m->cap_cntl = 0x8040;
1132         tsleep((caddr_t)m, METPRI, "Mreset", hz/10);
1133         m->cap_cntl = 0x80c0;
1134
1135         return 0;
1136
1137 }
1138 #endif
1139
1140 /*---------------------------------------------------------
1141 **
1142 **      Meteor character device driver routines
1143 **
1144 **---------------------------------------------------------
1145 */
1146
1147 int
1148 meteor_open(struct dev_open_args *ap)
1149 {
1150         cdev_t dev = ap->a_head.a_dev;
1151         meteor_reg_t *mtr;
1152         int     unit; 
1153         int     i;
1154
1155         unit = UNIT(minor(dev));
1156         if (unit >= NMETEOR)    /* unit out of range */
1157                 return(ENXIO);
1158
1159         mtr = &(meteor[unit]);
1160
1161         if (!(mtr->flags & METEOR_INITALIZED))  /* device not found */
1162                 return(ENXIO);
1163
1164         if (mtr->flags & METEOR_OPEN)           /* device is busy */
1165                 return(EBUSY);
1166
1167         mtr->flags |= METEOR_OPEN;
1168         /*
1169          * Make sure that the i2c regs are set the same for each open.
1170          */
1171         for(i=0; i< NUM_SAA7196_I2C_REGS; i++) {
1172                 SAA7196_WRITE(mtr, i, saa7196_i2c_default[i]);
1173         }
1174
1175         mtr->fifo_errors = 0;
1176         mtr->dma_errors = 0;
1177         mtr->frames_captured = 0;
1178         mtr->even_fields_captured = 0;
1179         mtr->odd_fields_captured = 0;
1180         mtr->proc = NULL;
1181         set_fps(mtr, 30);
1182 #ifdef METEOR_TEST_VIDEO
1183         mtr->video.addr = 0;
1184         mtr->video.width = 0;
1185         mtr->video.banksize = 0;
1186         mtr->video.ramsize = 0;
1187 #endif
1188
1189         return(0);
1190 }
1191
1192 int
1193 meteor_close(struct dev_close_args *ap)
1194 {
1195         cdev_t dev = ap->a_head.a_dev;
1196         meteor_reg_t *mtr;
1197         int     unit; 
1198 #ifdef METEOR_DEALLOC_ABOVE
1199         int     temp;
1200 #endif
1201
1202         unit = UNIT(minor(dev));
1203         if (unit >= NMETEOR)    /* unit out of range */
1204                 return(ENXIO);
1205
1206         mtr = &(meteor[unit]);
1207         mtr->flags &= ~METEOR_OPEN;
1208
1209         if(mtr->flags & METEOR_SINGLE)
1210                                 /* this should not happen, the read capture 
1211                                   should have completed or in the very least
1212                                   recieved a signal before close is called. */
1213                 wakeup((caddr_t)mtr);   /* continue read */
1214         /*
1215          * Turn off capture mode.
1216          */
1217         mtr->base->cap_cntl = 0x8ff0;
1218         mtr->flags &= ~(METEOR_CAP_MASK|METEOR_WANT_MASK);
1219         mtr->proc = NULL;
1220
1221 #ifdef METEOR_DEALLOC_PAGES
1222         if (mtr->bigbuf != NULL) {
1223                 kmem_free(&kernel_map, mtr->bigbuf,
1224                           (mtr->alloc_pages * PAGE_SIZE));
1225                 mtr->bigbuf = NULL;
1226                 mtr->alloc_pages = 0;
1227         }
1228 #else
1229 #ifdef METEOR_DEALLOC_ABOVE
1230         if (mtr->bigbuf != NULL && mtr->alloc_pages > METEOR_DEALLOC_ABOVE) {
1231                 temp = METEOR_DEALLOC_ABOVE - mtr->alloc_pages;
1232                 kmem_free(&kernel_map,
1233                           mtr->bigbuf+((mtr->alloc_pages - temp) * PAGE_SIZE),
1234                           (temp * PAGE_SIZE));
1235                 mtr->alloc_pages = METEOR_DEALLOC_ABOVE;
1236         }
1237 #endif
1238 #endif
1239
1240         return(0);
1241 }
1242
1243 static void
1244 start_capture(meteor_reg_t *mtr, unsigned type)
1245 {
1246 mreg_t *cap = &mtr->base->cap_cntl;
1247
1248         mtr->flags |= type;
1249         switch(mtr->flags & METEOR_ONLY_FIELDS_MASK) {
1250         case METEOR_ONLY_EVEN_FIELDS:
1251                 mtr->flags |= METEOR_WANT_EVEN;
1252                 if(type == METEOR_SINGLE)
1253                         *cap = 0x0ff4 | mtr->range_enable;
1254                 else
1255                         *cap = 0x0ff1 | mtr->range_enable;
1256                 break;
1257         case METEOR_ONLY_ODD_FIELDS:
1258                 mtr->flags |= METEOR_WANT_ODD;
1259                 if(type == METEOR_SINGLE)
1260                         *cap = 0x0ff8 | mtr->range_enable;
1261                 else
1262                         *cap = 0x0ff2 | mtr->range_enable;
1263                 break;
1264         default:
1265                 mtr->flags |= METEOR_WANT_MASK;
1266                 if(type == METEOR_SINGLE)
1267                         *cap = 0x0ffc | mtr->range_enable;
1268                 else
1269                         *cap = 0x0ff3 | mtr->range_enable;
1270                 break;
1271         }
1272 }
1273
1274 int
1275 meteor_read(struct dev_read_args *ap)
1276 {
1277         cdev_t dev = ap->a_head.a_dev;
1278         struct uio *uio = ap->a_uio;
1279         meteor_reg_t *mtr;
1280         int     unit; 
1281         int     status;
1282         int     count;
1283
1284         unit = UNIT(minor(dev));
1285         if (unit >= NMETEOR)    /* unit out of range */
1286                 return(ENXIO);
1287
1288         mtr = &(meteor[unit]);
1289         if (mtr->bigbuf == 0)/* no frame buffer allocated (ioctl failed) */
1290                 return(ENOMEM);
1291
1292         if (mtr->flags & METEOR_CAP_MASK)
1293                 return(EIO);            /* already capturing */
1294
1295         count = mtr->rows * mtr->cols * mtr->depth;
1296         if (uio->uio_iov->iov_len < count)
1297                 return(EINVAL);
1298
1299         /* Start capture */
1300         start_capture(mtr, METEOR_SINGLE);
1301
1302         status=tsleep((caddr_t)mtr, METPRI, "capturing", 0);
1303         if (!status)            /* successful capture */
1304                 status = uiomove((caddr_t)mtr->bigbuf, count, uio);
1305         else
1306                 kprintf ("meteor%d: read: tsleep error %d\n", unit, status);
1307
1308         mtr->flags &= ~(METEOR_SINGLE | METEOR_WANT_MASK);
1309
1310         return(status);
1311 }
1312
1313 int
1314 meteor_write(struct dev_write_args *ap)
1315 {
1316         return(0);
1317 }
1318
1319 int
1320 meteor_ioctl(struct dev_ioctl_args *ap)
1321 {
1322         cdev_t dev = ap->a_head.a_dev;
1323         caddr_t data = ap->a_data;
1324         int     error;  
1325         int     unit;   
1326         unsigned int    temp;
1327         meteor_reg_t *mtr;
1328         struct meteor_counts *cnt;
1329         struct meteor_geomet *geo;
1330         struct meteor_mem *mem;
1331         struct meteor_capframe *frame;
1332 #ifdef METEOR_TEST_VIDEO
1333         struct meteor_video *video;
1334 #endif
1335         vm_offset_t buf;
1336         struct saa7116_regs *base;
1337
1338         error = 0;
1339
1340         if (data == NULL)
1341                 return(EINVAL);
1342         unit = UNIT(minor(dev));
1343         if (unit >= NMETEOR)    /* unit out of range */
1344                 return(ENXIO);
1345
1346         mtr = &(meteor[unit]);
1347         base = mtr->base;
1348
1349         switch (ap->a_cmd) {
1350         case METEORSTS:
1351                 if(*data)
1352                         mtr->flags |= METEOR_WANT_TS;
1353                 else
1354                         mtr->flags &= ~METEOR_WANT_TS;
1355                 break;
1356         case METEORGTS:
1357                 if(mtr->flags & METEOR_WANT_TS)
1358                         *data = 1;
1359                 else
1360                         *data = 0;
1361                 break;
1362 #ifdef METEOR_TEST_VIDEO
1363         case METEORGVIDEO:
1364                 video = (struct meteor_video *)data;
1365                 video->addr = mtr->video.addr;
1366                 video->width = mtr->video.width;
1367                 video->banksize = mtr->video.banksize;
1368                 video->ramsize = mtr->video.ramsize;
1369                 break;
1370         case METEORSVIDEO:
1371                 video = (struct meteor_video *)data;
1372                 mtr->video.addr = video->addr;
1373                 mtr->video.width = video->width;
1374                 mtr->video.banksize = video->banksize;
1375                 mtr->video.ramsize = video->ramsize;
1376                 break;
1377 #endif
1378         case METEORSFPS:
1379                 set_fps(mtr, *(u_short *)data);
1380                 break;
1381         case METEORGFPS:
1382                 *(u_short *)data = mtr->fps;
1383                 break;
1384         case METEORSSIGNAL:
1385                 if (*(int *)data < 0 || *(int *)data > _SIG_MAXSIG)
1386                         return EINVAL;
1387                 mtr->signal = *(int *) data;
1388                 if (mtr->signal) {
1389                   mtr->proc = curproc;  /* might be NULL */
1390                 } else {
1391                   mtr->proc = NULL;
1392                 }
1393                 break;
1394         case METEORGSIGNAL:
1395                 *(int *)data = mtr->signal;
1396                 break;
1397         case METEORSTATUS:      /* get 7196 status */
1398                 temp = 0;
1399                 SAA7196_WRITE(mtr, SAA7196_STDC,
1400                         SAA7196_REG(mtr, SAA7196_STDC) | 0x02);
1401                 SAA7196_READ(mtr);
1402                 temp |= (base->i2c_read & 0xff000000L) >> 24;
1403                 SAA7196_WRITE(mtr, SAA7196_STDC,
1404                         SAA7196_REG(mtr, SAA7196_STDC) & ~0x02);
1405                 SAA7196_READ(mtr);
1406                 temp |= (base->i2c_read & 0xff000000L) >> 16;
1407                 *(u_short *)data = temp;
1408                 break;
1409         case METEORSHUE:        /* set hue */
1410                 SAA7196_WRITE(mtr, SAA7196_HUEC, *(char *)data);
1411                 break;
1412         case METEORGHUE:        /* get hue */
1413                 *(char *)data = SAA7196_REG(mtr, SAA7196_HUEC);
1414                 break;
1415         case METEORSCHCV:       /* set chrominance gain */
1416                 SAA7196_WRITE(mtr, SAA7196_CGAINR, *(char *)data);
1417                 break;
1418         case METEORGCHCV:       /* get chrominance gain */
1419                 *(char *)data = SAA7196_REG(mtr, SAA7196_CGAINR);
1420                 break;
1421         case METEORSBRIG:       /* set brightness */
1422                 SAA7196_WRITE(mtr, SAA7196_BRIG, *(char *)data);
1423                 break;
1424         case METEORGBRIG:       /* get brightness */
1425                 *(char *)data = SAA7196_REG(mtr, SAA7196_BRIG);
1426                 break;
1427         case METEORSCSAT:       /* set chroma saturation */
1428                 SAA7196_WRITE(mtr, SAA7196_CSAT, *(char *)data);
1429                 break;
1430         case METEORGCSAT:       /* get chroma saturation */
1431                 *(char *)data = SAA7196_REG(mtr, SAA7196_CSAT);
1432                 break;
1433         case METEORSCONT:       /* set contrast */
1434                 SAA7196_WRITE(mtr, SAA7196_CONT, *(char *)data);
1435                 break;
1436         case METEORGCONT:       /* get contrast */
1437                 *(char *)data = SAA7196_REG(mtr, SAA7196_CONT);
1438                 break;
1439         case METEORSBT254:
1440                 if((mtr->flags & METEOR_RGB) == 0)
1441                         return EINVAL;
1442                 temp = *(unsigned short *)data;
1443                 bt254_write(mtr, temp & 0xf, (temp & 0x0ff0) >> 4);
1444                 break;
1445         case METEORGBT254:
1446                 if((mtr->flags & METEOR_RGB) == 0)
1447                         return EINVAL;
1448                 temp = *(unsigned short *)data & 0x7;
1449                 *(unsigned short *)data = mtr->bt254_reg[temp] << 4 | temp;
1450                 break;
1451         case METEORSHWS:        /* set horizontal window start */
1452                 SAA7196_WRITE(mtr, SAA7196_HWS, *(char *)data);
1453                 break;
1454         case METEORGHWS:        /* get horizontal window start */
1455                 *(char *)data = SAA7196_REG(mtr, SAA7196_HWS);
1456                 break;
1457         case METEORSVWS:        /* set vertical window start */
1458                 SAA7196_WRITE(mtr, SAA7196_VWS, *(char *)data);
1459                 break;
1460         case METEORGVWS:        /* get vertical window start */
1461                 *(char *)data = SAA7196_REG(mtr, SAA7196_VWS);
1462                 break;
1463         case METEORSINPUT:      /* set input device */
1464                 switch(*(unsigned long *)data & METEOR_DEV_MASK) {
1465                 case 0:                 /* default */
1466                 case METEOR_INPUT_DEV0:
1467                         if(mtr->flags & METEOR_RGB)
1468                                 select_saa7196(mtr);
1469                         mtr->flags = (mtr->flags & ~METEOR_DEV_MASK)
1470                                 | METEOR_DEV0;
1471                         SAA7196_WRITE(mtr, 0x0e,
1472                                 (SAA7196_REG(mtr, 0x0e) & ~0x3) | 0x0);
1473                         SAA7196_WRITE(mtr, 0x06,
1474                                 (SAA7196_REG(mtr, 0x06) & ~0x80));
1475                         break;
1476                 case METEOR_INPUT_DEV1:
1477                         if(mtr->flags & METEOR_RGB)
1478                                 select_saa7196(mtr);
1479                         mtr->flags = (mtr->flags & ~METEOR_DEV_MASK)
1480                                                | METEOR_DEV1;
1481                         SAA7196_WRITE(mtr, 0x0e,
1482                                 (SAA7196_REG(mtr, 0x0e) & ~0x3) | 0x1);
1483                         SAA7196_WRITE(mtr, 0x06,
1484                                 (SAA7196_REG(mtr, 0x06) & ~0x80));
1485                         break;
1486                 case METEOR_INPUT_DEV2:
1487                         if(mtr->flags & METEOR_RGB)
1488                                 select_saa7196(mtr);
1489                         mtr->flags = (mtr->flags & ~METEOR_DEV_MASK)
1490                                                | METEOR_DEV2;
1491                         SAA7196_WRITE(mtr, 0x0e,
1492                                 (SAA7196_REG(mtr, 0x0e) & ~0x3) | 0x2);
1493                         SAA7196_WRITE(mtr, 0x06,
1494                                 (SAA7196_REG(mtr, 0x06) & ~0x80));
1495                         break;
1496                 case METEOR_INPUT_DEV3:
1497                         if(mtr->flags & METEOR_RGB)
1498                                 select_saa7196(mtr);
1499                         mtr->flags = (mtr->flags & ~METEOR_DEV_MASK)
1500                                                | METEOR_DEV3;
1501                         SAA7196_WRITE(mtr, 0x0e,
1502                                 (SAA7196_REG(mtr, 0x0e) | 0x3));
1503                         SAA7196_WRITE(mtr, 0x06,
1504                                 (SAA7196_REG(mtr, 0x06) & ~0x80) );
1505                         break;
1506                 case METEOR_INPUT_DEV_SVIDEO:
1507                         if(mtr->flags & METEOR_RGB)
1508                                 select_saa7196(mtr);
1509                         mtr->flags = (mtr->flags & ~METEOR_DEV_MASK)
1510                                                | METEOR_DEV_SVIDEO;
1511                         SAA7196_WRITE(mtr, 0x0e,
1512                                 (SAA7196_REG(mtr, 0x0e) & ~0x3) | 0x2);
1513                         SAA7196_WRITE(mtr, 0x06,
1514                                 (SAA7196_REG(mtr, 0x06) & ~0x80) | 0x80);
1515                         break;
1516                 case METEOR_INPUT_DEV_RGB:
1517                         if((mtr->flags & METEOR_RGB) == 0)
1518                                 return EINVAL;
1519                         mtr->flags = (mtr->flags & ~METEOR_DEV_MASK)
1520                                                | METEOR_DEV_RGB;
1521                         SAA7196_WRITE(mtr, 0x0e,
1522                                 (SAA7196_REG(mtr, 0x0e) & ~0x3) | 0x3);
1523                         SAA7196_WRITE(mtr, 0x06,
1524                                 (SAA7196_REG(mtr, 0x06) & ~0x80));
1525                         select_bt254(mtr);
1526                         SAA7196_WRITE(mtr, 0x0e,        /* chn 3 for synch */
1527                                 (SAA7196_REG(mtr, 0x0e) & ~0x3) | 0x3);
1528                         break;
1529                 default:
1530                         return EINVAL;
1531                 }
1532                 break;
1533         case METEORGINPUT:      /* get input device */
1534                 *(u_long *)data = mtr->flags & METEOR_DEV_MASK;
1535                 break;
1536         case METEORSFMT:        /* set input format */
1537                 switch(*(unsigned long *)data & METEOR_FORM_MASK ) {
1538                 case 0:                 /* default */
1539                 case METEOR_FMT_NTSC:
1540                         mtr->flags = (mtr->flags & ~METEOR_FORM_MASK) |
1541                                 METEOR_NTSC;
1542                         SAA7196_WRITE(mtr, SAA7196_STDC, 
1543                                 (SAA7196_REG(mtr, SAA7196_STDC) & ~0x01));
1544                         SAA7196_WRITE(mtr, 0x0f,
1545                                 (SAA7196_REG(mtr, 0x0f) & ~0xe0) | 0x40);
1546                         SAA7196_WRITE(mtr, 0x22, 0x80);
1547                         SAA7196_WRITE(mtr, 0x24, 
1548                                 (SAA7196_REG(mtr, 0x24) & ~0x0c) | 0x08);
1549                         SAA7196_WRITE(mtr, 0x26, 0xf0);
1550                         SAA7196_WRITE(mtr, 0x28, 
1551                                 (SAA7196_REG(mtr, 0x28) & ~0x0c)) ;
1552                         if(mtr->flags & METEOR_RGB){
1553                           bt254_ntsc(mtr, 1);                     
1554                         }
1555                 break;
1556                 case METEOR_FMT_PAL:
1557                         mtr->flags = (mtr->flags & ~METEOR_FORM_MASK) |
1558                                 METEOR_PAL;
1559                         SAA7196_WRITE(mtr, SAA7196_STDC, 
1560                                 (SAA7196_REG(mtr, SAA7196_STDC) & ~0x01));
1561                         SAA7196_WRITE(mtr, 0x0f, 
1562                                 (SAA7196_REG(mtr, 0x0f) & ~0xe0));
1563                         SAA7196_WRITE(mtr, 0x22, 0x00);
1564                         SAA7196_WRITE(mtr, 0x24, 
1565                                 (SAA7196_REG(mtr, 0x24) | 0x0c));
1566                         SAA7196_WRITE(mtr, 0x26, 0x20);
1567                         SAA7196_WRITE(mtr, 0x28, 
1568                                 (SAA7196_REG(mtr, 0x28) & ~0x0c) | 0x04) ;
1569                         if(mtr->flags & METEOR_RGB){
1570                           bt254_ntsc(mtr, 0);                     
1571                         }
1572                 break;
1573                 case METEOR_FMT_SECAM:
1574                         mtr->flags = (mtr->flags & ~METEOR_FORM_MASK) |
1575                                 METEOR_SECAM;
1576                         SAA7196_WRITE(mtr, SAA7196_STDC, 
1577                                 (SAA7196_REG(mtr, SAA7196_STDC) & ~0x01) | 0x1);
1578                         SAA7196_WRITE(mtr, 0x0f, 
1579                                 (SAA7196_REG(mtr, 0x0f) & ~0xe0) | 0x20);
1580                         SAA7196_WRITE(mtr, 0x22, 0x00);
1581                         SAA7196_WRITE(mtr, 0x24, 
1582                                 (SAA7196_REG(mtr, 0x24) | 0x0c));
1583                         SAA7196_WRITE(mtr, 0x26, 0x20);
1584                         SAA7196_WRITE(mtr, 0x28, 
1585                                 (SAA7196_REG(mtr, 0x28) & ~0x0c) | 0x04) ;
1586                         if(mtr->flags & METEOR_RGB){
1587                           bt254_ntsc(mtr, 0);
1588                         }
1589                 break;
1590                 case METEOR_FMT_AUTOMODE:
1591                         mtr->flags = (mtr->flags & ~METEOR_FORM_MASK) |
1592                                 METEOR_AUTOMODE;
1593                         SAA7196_WRITE(mtr, SAA7196_STDC, 
1594                                 (SAA7196_REG(mtr, SAA7196_STDC) & ~0x01));
1595                         SAA7196_WRITE(mtr, 0x0f, 
1596                                 (SAA7196_REG(mtr, 0x0f) & ~0xe0) | 0x80);
1597                 break;
1598                 default:
1599                         return EINVAL;
1600                 }
1601                 break;
1602         case METEORGFMT:        /* get input format */
1603                 *(u_long *)data = mtr->flags & METEOR_FORM_MASK;
1604                 break;
1605         case METEORCAPTUR:
1606                 temp = mtr->flags;
1607                 switch (*(int *) data) {
1608                 case METEOR_CAP_SINGLE:
1609                         if (mtr->bigbuf==0)     /* no frame buffer allocated */
1610                                 return(ENOMEM);
1611
1612                         if (temp & METEOR_CAP_MASK)
1613                                 return(EIO);            /* already capturing */
1614
1615                         start_capture(mtr, METEOR_SINGLE);
1616
1617                         /* wait for capture to complete */
1618                         error=tsleep((caddr_t)mtr, METPRI, "capturing", 0);
1619                         if(error)
1620                                 kprintf("meteor%d: ioctl: tsleep error %d\n",
1621                                         unit, error);
1622                         mtr->flags &= ~(METEOR_SINGLE|METEOR_WANT_MASK);
1623                         break;
1624                 case METEOR_CAP_CONTINOUS:
1625                         if (mtr->bigbuf==0)     /* no frame buffer allocated */
1626                                 return(ENOMEM);
1627
1628                         if (temp & METEOR_CAP_MASK)
1629                                 return(EIO);            /* already capturing */
1630
1631                         start_capture(mtr, METEOR_CONTIN);
1632
1633                         break;
1634                 case METEOR_CAP_STOP_CONT:
1635                         if (mtr->flags & METEOR_CONTIN) {
1636                                                         /* turn off capture */
1637                                 base->cap_cntl = 0x8ff0;
1638                                 mtr->flags &= ~(METEOR_CONTIN|METEOR_WANT_MASK);
1639                         }
1640                         break;
1641         
1642                 default:
1643                         error = EINVAL;
1644                         break;
1645                 }
1646                 break;
1647         case METEORCAPFRM:
1648             frame = (struct meteor_capframe *) data;
1649             if (!frame) 
1650                 return(EINVAL);
1651             switch (frame->command) {
1652             case METEOR_CAP_N_FRAMES:
1653                 if (mtr->flags & METEOR_CAP_MASK)
1654                         return(EIO);
1655                 if (mtr->flags & (METEOR_YUV_PLANAR | METEOR_YUV_422)) /* XXX */
1656                         return(EINVAL); /* should fix intr so we allow these */
1657                 if (mtr->bigbuf == 0)
1658                         return(ENOMEM);
1659                 if ((mtr->frames < 2) ||
1660                     (frame->lowat < 1 || frame->lowat >= mtr->frames) ||
1661                     (frame->hiwat < 1 || frame->hiwat >= mtr->frames) ||
1662                     (frame->lowat > frame->hiwat)) 
1663                         return(EINVAL);
1664                         /* meteor_mem structure is on the page after the data */
1665                 mem = mtr->mem = (struct meteor_mem *) (mtr->bigbuf +
1666                                 (round_page(mtr->frame_size * mtr->frames)));
1667                 mtr->current = 1;
1668                 mtr->synch_wait = 0;
1669                 mem->num_bufs = mtr->frames;
1670                 mem->frame_size= mtr->frame_size;
1671                 /* user and kernel change these */ 
1672                 mem->lowat = frame->lowat;
1673                 mem->hiwat = frame->hiwat;
1674                 mem->active = 0;
1675                 mem->num_active_bufs = 0;
1676                 /* Start capture */
1677                 start_capture(mtr, METEOR_SYNCAP);
1678                 break;
1679             case METEOR_CAP_STOP_FRAMES:
1680                 if (mtr->flags & METEOR_SYNCAP) {
1681                                                 /* turn off capture */
1682                         base->cap_cntl = 0x8ff0;
1683                         mtr->flags &= ~(METEOR_SYNCAP|METEOR_WANT_MASK);
1684                 }
1685                 break;
1686             case METEOR_HALT_N_FRAMES:
1687                 if(mtr->flags & METEOR_SYNCAP) {
1688                         base->cap_cntl = 0x8ff0;
1689                         mtr->flags &= ~(METEOR_WANT_MASK);
1690                 }
1691                 break;
1692             case METEOR_CONT_N_FRAMES:
1693                 if(!(mtr->flags & METEOR_SYNCAP)) {
1694                         error = EINVAL;
1695                         break;
1696                 }
1697                 start_capture(mtr, METEOR_SYNCAP);
1698                 break;
1699             default:
1700                 error = EINVAL;
1701                 break;
1702             }
1703             break;
1704  
1705         case METEORSETGEO:
1706                 geo = (struct meteor_geomet *) data;
1707
1708                 /* Either even or odd, if even & odd, then these a zero */
1709                 if((geo->oformat & METEOR_GEO_ODD_ONLY) &&
1710                         (geo->oformat & METEOR_GEO_EVEN_ONLY)) {
1711                         kprintf("meteor%d: ioctl: Geometry odd or even only.\n",
1712                                 unit);
1713                         return EINVAL;
1714                 }
1715                 /* set/clear even/odd flags */
1716                 if(geo->oformat & METEOR_GEO_ODD_ONLY)
1717                         mtr->flags |= METEOR_ONLY_ODD_FIELDS;
1718                 else
1719                         mtr->flags &= ~METEOR_ONLY_ODD_FIELDS;
1720                 if(geo->oformat & METEOR_GEO_EVEN_ONLY)
1721                         mtr->flags |= METEOR_ONLY_EVEN_FIELDS;
1722                 else
1723                         mtr->flags &= ~METEOR_ONLY_EVEN_FIELDS;
1724
1725                 /* can't change parameters while capturing */
1726                 if (mtr->flags & METEOR_CAP_MASK)
1727                         return(EBUSY);
1728
1729                 if ((geo->columns & 0x3fe) != geo->columns) {
1730                         kprintf(
1731                         "meteor%d: ioctl: %d: columns too large or not even.\n",
1732                                 unit, geo->columns);
1733                         error = EINVAL;
1734                 }
1735                 if (((geo->rows & 0x7fe) != geo->rows) ||
1736                         ((geo->oformat & METEOR_GEO_FIELD_MASK) &&
1737                                 ((geo->rows & 0x3fe) != geo->rows)) ) {
1738                         kprintf(
1739                         "meteor%d: ioctl: %d: rows too large or not even.\n",
1740                                 unit, geo->rows);
1741                         error = EINVAL;
1742                 }
1743                 if (geo->frames > 32) {
1744                         kprintf("meteor%d: ioctl: too many frames.\n", unit);
1745                         error = EINVAL;
1746                 }
1747                 if(error) return error;
1748
1749                 if ((temp=geo->rows * geo->columns * geo->frames * 2) != 0) {
1750                         if (geo->oformat & METEOR_GEO_RGB24) temp = temp * 2;
1751
1752                         /* meteor_mem structure for SYNC Capture */
1753                         if (geo->frames > 1) temp += PAGE_SIZE;
1754
1755                         temp = btoc(temp);
1756                         if (temp > mtr->alloc_pages
1757 #ifdef METEOR_TEST_VIDEO
1758                             && mtr->video.addr == 0
1759 #endif
1760                         ) {
1761                                 buf = get_meteor_mem(unit, temp*PAGE_SIZE);
1762                                 if(buf != 0) {
1763                                         kmem_free(&kernel_map, mtr->bigbuf,
1764                                           (mtr->alloc_pages * PAGE_SIZE));
1765                                         mtr->bigbuf = buf;
1766                                         mtr->alloc_pages = temp;
1767                                         if(bootverbose)
1768                                                 kprintf(
1769                                 "meteor%d: ioctl: Allocating %d bytes\n",
1770                                                         unit, temp*PAGE_SIZE);
1771                                 } else {
1772                                         error = ENOMEM;
1773                                 }
1774                         }
1775                 }
1776                 if(error) return error;
1777
1778                 mtr->rows = geo->rows;
1779                 mtr->cols = geo->columns;
1780                 mtr->frames = geo->frames;
1781
1782 #ifdef METEOR_TEST_VIDEO
1783                 if(mtr->video.addr)
1784                         buf = vtophys(mtr->video.addr);
1785                 else
1786 #endif
1787                         buf = vtophys(mtr->bigbuf);
1788
1789                 /* set defaults and end of buffer locations */
1790                 base->dma1e = buf;
1791                 base->dma2e = buf;
1792                 base->dma3e = buf;
1793                 base->dma1o = buf;
1794                 base->dma2o = buf;
1795                 base->dma3o = buf;
1796                 base->stride1e = 0;
1797                 base->stride2e = 0;
1798                 base->stride3e = 0;
1799                 base->stride1o = 0;
1800                 base->stride2o = 0;
1801                 base->stride3o = 0;
1802                                 /* set end of DMA location, even/odd */
1803                 base->dma_end_e =
1804                 base->dma_end_o = buf + mtr->alloc_pages * PAGE_SIZE;
1805
1806                 /*
1807                  * Determine if we can use the hardware range detect.
1808                  */
1809                 if(mtr->alloc_pages * PAGE_SIZE < RANGE_BOUNDARY &&
1810                   ((buf & 0xff000000) | base->dma_end_e) ==
1811                         (buf + mtr->alloc_pages * PAGE_SIZE) )
1812                         mtr->range_enable = 0x8000;
1813                 else {
1814                         mtr->range_enable = 0x0;
1815                         base->dma_end_e =
1816                         base->dma_end_o = 0xffffffff;
1817                 }
1818
1819
1820                 switch (geo->oformat & METEOR_GEO_OUTPUT_MASK) {
1821                 case 0:                 /* default */
1822                 case METEOR_GEO_RGB16:
1823                         mtr->depth = 2;
1824                         mtr->frame_size = mtr->rows * mtr->cols * mtr->depth;
1825                         mtr->flags &= ~METEOR_OUTPUT_FMT_MASK;
1826                         mtr->flags |= METEOR_RGB16;
1827                         temp = mtr->cols * mtr->depth;
1828                         /* recal stride and starting point */
1829                         switch(mtr->flags & METEOR_ONLY_FIELDS_MASK) {
1830                         case METEOR_ONLY_ODD_FIELDS:
1831                                 base->dma1o = buf;
1832 #ifdef METEOR_TEST_VIDEO
1833                                 if(mtr->video.addr && mtr->video.width) 
1834                                         base->stride1o = mtr->video.width-temp;
1835 #endif
1836                                 SAA7196_WRITE(mtr, 0x20, 0xd0);
1837                                 break;
1838                         case METEOR_ONLY_EVEN_FIELDS:
1839                                 base->dma1e = buf;
1840 #ifdef METEOR_TEST_VIDEO
1841                                 if(mtr->video.addr && mtr->video.width) 
1842                                         base->stride1e = mtr->video.width-temp;
1843 #endif
1844                                 SAA7196_WRITE(mtr, 0x20, 0xf0);
1845                                 break;
1846                         default: /* interlaced even/odd */
1847                                 base->dma1e = buf;              
1848                                 base->dma1o = buf + temp;
1849                                 base->stride1e = base->stride1o = temp;
1850 #ifdef METEOR_TEST_VIDEO
1851                                 if(mtr->video.addr && mtr->video.width) {
1852                                         base->dma1o = buf + mtr->video.width;
1853                                         base->stride1e = base->stride1o =
1854                                                 mtr->video.width -
1855                                                 temp + mtr->video.width;
1856                                 }
1857 #endif
1858                                 SAA7196_WRITE(mtr, 0x20, 0x90);
1859                                 break;
1860                         }
1861                         base->routee = base->routeo  = 0xeeeeee01;
1862                         break;
1863                 case METEOR_GEO_RGB24:
1864                         mtr->depth = 4;
1865                         mtr->frame_size = mtr->rows * mtr->cols * mtr->depth;
1866                         mtr->flags &= ~METEOR_OUTPUT_FMT_MASK;
1867                         mtr->flags |= METEOR_RGB24;
1868                         temp = mtr->cols * mtr->depth;
1869                         /* recal stride and starting point */
1870                         switch(mtr->flags & METEOR_ONLY_FIELDS_MASK) {
1871                         case METEOR_ONLY_ODD_FIELDS:
1872                                 base->dma1o = buf;
1873 #ifdef METEOR_TEST_VIDEO
1874                                 if(mtr->video.addr && mtr->video.width) 
1875                                         base->stride1o = mtr->video.width-temp;
1876 #endif
1877                                 SAA7196_WRITE(mtr, 0x20, 0xd2);
1878                                 break;
1879                         case METEOR_ONLY_EVEN_FIELDS:
1880                                 base->dma1e = buf;
1881 #ifdef METEOR_TEST_VIDEO
1882                                 if(mtr->video.addr && mtr->video.width) 
1883                                         base->stride1e = mtr->video.width-temp;
1884 #endif
1885                                 SAA7196_WRITE(mtr, 0x20, 0xf2);
1886                                 break;
1887                         default: /* interlaced even/odd */
1888                                 base->dma1e = buf;
1889                                 base->dma1o = buf + mtr->cols * mtr->depth;
1890                                 base->stride1e = base->stride1o =
1891                                         mtr->cols * mtr->depth;
1892 #ifdef METEOR_TEST_VIDEO
1893                                 if(mtr->video.addr && mtr->video.width) {
1894                                         base->dma1o = buf + mtr->video.width;
1895                                         base->stride1e = base->stride1o = 
1896                                                 mtr->video.width -
1897                                                 temp + mtr->video.width;
1898                                 }
1899 #endif
1900                                 SAA7196_WRITE(mtr, 0x20, 0x92);
1901                                 break;
1902                         }
1903                         base->routee= base->routeo= 0x39393900;
1904                         break;
1905                 case METEOR_GEO_YUV_PLANAR:
1906                         mtr->depth = 2;
1907                         temp = mtr->rows * mtr->cols;   /* compute frame size */
1908                         mtr->frame_size = temp * mtr->depth;
1909                         mtr->flags &= ~METEOR_OUTPUT_FMT_MASK;
1910                         mtr->flags |= METEOR_YUV_PLANAR;
1911                         /* recal stride and starting point */
1912                         switch(mtr->flags & METEOR_ONLY_FIELDS_MASK) {
1913                         case METEOR_ONLY_ODD_FIELDS:
1914                                 base->dma1o = buf;              /* Y Odd */
1915                                 base->dma2o = buf + temp;       /* U Odd */
1916                                 temp >>= 1;
1917                                 base->dma3o = base->dma2o + temp; /* V Odd */
1918                                 SAA7196_WRITE(mtr, 0x20, 0xd1);
1919                                 break;
1920                         case METEOR_ONLY_EVEN_FIELDS:
1921                                 base->dma1e = buf;              /* Y Even */
1922                                 base->dma2e = buf + temp;       /* U Even */
1923                                 temp >>= 1;
1924                                 base->dma2e= base->dma2e + temp; /* V Even */
1925                                 SAA7196_WRITE(mtr, 0x20, 0xf1);
1926                                 break;
1927                         default: /* interlaced even/odd */
1928                                 base->dma1e = buf;              /* Y Even */
1929                                 base->dma2e = buf + temp;       /* U Even */
1930                                 temp >>= 2;
1931                                 base->dma3e = base->dma2e + temp; /* V Even */
1932                                 base->dma1o = base->dma1e+mtr->cols;/* Y Odd */
1933                                 base->dma2o = base->dma3e + temp; /* U Odd */
1934                                 base->dma3o = base->dma2o + temp; /* V Odd */
1935                                 base->stride1e = base->stride1o = mtr->cols;
1936                                 SAA7196_WRITE(mtr, 0x20, 0x91);
1937                                 break;
1938                         }
1939                         switch (geo->oformat &
1940                                 (METEOR_GEO_YUV_12 | METEOR_GEO_YUV_9)) {
1941                                 case METEOR_GEO_YUV_9:
1942                                         base->routee=base->routeo = 0xaaaaffc3;
1943                                         break;
1944                                 case METEOR_GEO_YUV_12:
1945                                         base->routee=base->routeo = 0xaaaaffc2;
1946                                         break;
1947                                 default:
1948                                         base->routee=base->routeo = 0xaaaaffc1;
1949                                         break;
1950                         }
1951                         break;
1952                 case METEOR_GEO_YUV_422:/* same as planer, different uv order */
1953                         mtr->depth = 2;
1954                         temp = mtr->rows * mtr->cols;   /* compute frame size */
1955                         mtr->frame_size = temp * mtr->depth;
1956                         mtr->flags &= ~METEOR_OUTPUT_FMT_MASK;
1957                         mtr->flags |= METEOR_YUV_422;
1958                         switch(mtr->flags & METEOR_ONLY_FIELDS_MASK) {
1959                         case METEOR_ONLY_ODD_FIELDS:
1960                                 base->dma1o = buf;
1961                                 base->dma2o = buf + temp;
1962                                 base->dma3o = base->dma2o  + (temp >> 1);
1963                                 SAA7196_WRITE(mtr, 0x20, 0xd1);
1964                                 break;
1965                         case METEOR_ONLY_EVEN_FIELDS:
1966                                 base->dma1e = buf;
1967                                 base->dma2e = buf + temp;
1968                                 base->dma3e = base->dma2e + (temp >> 1);
1969                                 SAA7196_WRITE(mtr, 0x20, 0xf1);
1970                                 break;
1971                         default: /* interlaced even/odd */
1972                                 base->dma1e = buf;              /* Y even */
1973                                 base->dma2e = buf + temp;       /* U even */
1974                                 base->dma3e =
1975                                         base->dma2e + (temp >> 1);/* V even */
1976                                 base->dma1o = base->dma1e+mtr->cols;/* Y odd */
1977                                 temp = mtr->cols >> 1;
1978                                 base->dma2o = base->dma2e+temp; /* U odd */
1979                                 base->dma3o = base->dma3e+temp; /* V odd */
1980                                 base->stride1e =
1981                                 base->stride1o = mtr->cols;     /* Y stride */
1982                                 base->stride2e = 
1983                                 base->stride2o = temp;          /* U stride */
1984                                 base->stride3e =
1985                                 base->stride3o = temp;          /* V stride */
1986                                 SAA7196_WRITE(mtr, 0x20, 0x91);
1987                                 break;
1988                         }
1989                         switch (geo->oformat &
1990                                 (METEOR_GEO_YUV_12 | METEOR_GEO_YUV_9)) {
1991                                 case METEOR_GEO_YUV_9:
1992                                         base->routee=base->routeo = 0xaaaaffc3;
1993                                         break;
1994                                 case METEOR_GEO_YUV_12:
1995                                         base->routee=base->routeo = 0xaaaaffc2;
1996                                         break;
1997                                 default:
1998                                         base->routee=base->routeo = 0xaaaaffc1;
1999                                         break;
2000                         }
2001                         break;
2002                 case METEOR_GEO_YUV_PACKED:
2003                         mtr->depth = 2;
2004                         mtr->frame_size = mtr->rows * mtr->cols * mtr->depth;
2005                         mtr->flags &= ~METEOR_OUTPUT_FMT_MASK;
2006                         mtr->flags |= METEOR_YUV_PACKED;
2007                         /* recal stride and odd starting point */
2008                         switch(mtr->flags & METEOR_ONLY_FIELDS_MASK) {
2009                         case METEOR_ONLY_ODD_FIELDS:
2010                                 base->dma1o = buf;
2011                                 SAA7196_WRITE(mtr, 0x20, 0xd1);
2012                                 break;
2013                         case METEOR_ONLY_EVEN_FIELDS:
2014                                 base->dma1e = buf;
2015                                 SAA7196_WRITE(mtr, 0x20, 0xf1);
2016                                 break;
2017                         default: /* interlaced even/odd */
2018                                 base->dma1e = buf;
2019                                 base->dma1o = buf + mtr->cols * mtr->depth;
2020                                 base->stride1e = base->stride1o =
2021                                         mtr->cols * mtr->depth;
2022                                 SAA7196_WRITE(mtr, 0x20, 0x91);
2023                                 break;
2024                         }
2025                         base->routee = base->routeo = 0xeeeeee41;
2026                         break;
2027                 default:
2028                         error = EINVAL; /* invalid argument */
2029                         kprintf("meteor%d: ioctl: invalid output format\n",unit);
2030                         break;
2031                 }
2032                 /* set cols */
2033                 SAA7196_WRITE(mtr, 0x21, mtr->cols & 0xff);
2034                 SAA7196_WRITE(mtr, 0x24,
2035                                 ((SAA7196_REG(mtr, 0x24) & ~0x03) |
2036                                 ((mtr->cols >> 8) & 0x03)));
2037                 /* set rows */
2038                 if(mtr->flags & METEOR_ONLY_FIELDS_MASK) {
2039                         SAA7196_WRITE(mtr, 0x25, ((mtr->rows) & 0xff));
2040                         SAA7196_WRITE(mtr, 0x28,
2041                                         ((SAA7196_REG(mtr, 0x28) & ~0x03) |
2042                                         ((mtr->rows >> 8) & 0x03)));
2043                 } else {        /* Interlaced */
2044                         SAA7196_WRITE(mtr, 0x25, ((mtr->rows >> 1) & 0xff));
2045                         SAA7196_WRITE(mtr, 0x28,
2046                                         ((SAA7196_REG(mtr, 0x28) & ~0x03) |
2047                                         ((mtr->rows >> 9) & 0x03)));
2048                 }
2049                 /* set signed/unsigned chrominance */
2050                 SAA7196_WRITE(mtr, 0x30, (SAA7196_REG(mtr, 0x30) & ~0x10) |
2051                                 ((geo->oformat&METEOR_GEO_UNSIGNED)?0:0x10));
2052                 break;
2053         case METEORGETGEO:
2054                 geo = (struct meteor_geomet *) data;
2055                 geo->rows = mtr->rows;
2056                 geo->columns = mtr->cols;
2057                 geo->frames = mtr->frames;
2058                 geo->oformat = (mtr->flags & METEOR_OUTPUT_FMT_MASK) |
2059                                (mtr->flags & METEOR_ONLY_FIELDS_MASK) |
2060                                (SAA7196_REG(mtr, 0x30) & 0x10 ? 
2061                                 0:METEOR_GEO_UNSIGNED);
2062                 switch(base->routee & 0xff) {
2063                 case    0xc3:
2064                         geo->oformat |=  METEOR_GEO_YUV_9;
2065                         break;
2066                 case    0xc2:
2067                         geo->oformat |=  METEOR_GEO_YUV_12;
2068                         break;
2069                 default:
2070                         break;
2071                 }
2072                 break;
2073         case METEORSCOUNT:      /* (re)set error counts */
2074                 cnt = (struct meteor_counts *) data;
2075                 mtr->fifo_errors = cnt->fifo_errors;
2076                 mtr->dma_errors = cnt->dma_errors;
2077                 mtr->frames_captured = cnt->frames_captured;
2078                 mtr->even_fields_captured = cnt->even_fields_captured;
2079                 mtr->odd_fields_captured = cnt->odd_fields_captured;
2080                 break;
2081         case METEORGCOUNT:      /* get error counts */
2082                 cnt = (struct meteor_counts *) data;
2083                 cnt->fifo_errors = mtr->fifo_errors;
2084                 cnt->dma_errors = mtr->dma_errors;
2085                 cnt->frames_captured = mtr->frames_captured;
2086                 cnt->even_fields_captured = mtr->even_fields_captured;
2087                 cnt->odd_fields_captured = mtr->odd_fields_captured;
2088                 break;
2089         default:
2090                 kprintf("meteor%d: ioctl: invalid ioctl request\n", unit);
2091                 error = ENOTTY;
2092                 break;
2093         }
2094         return(error);
2095 }
2096
2097 int
2098 meteor_mmap(struct dev_mmap_args *ap)
2099 {
2100         cdev_t dev = ap->a_head.a_dev;
2101         int     unit;
2102         meteor_reg_t *mtr;
2103
2104         unit = UNIT(minor(dev));
2105         if (unit >= NMETEOR)            /* at this point could this happen? */
2106                 return(-1);
2107
2108         mtr = &(meteor[unit]);
2109
2110
2111         if (ap->a_nprot & PROT_EXEC)
2112                 return -1;
2113
2114         if (ap->a_offset >= mtr->alloc_pages * PAGE_SIZE)
2115                 return -1;
2116
2117         return i386_btop(vtophys(mtr->bigbuf) + ap->a_offset);
2118 }